Compare commits
70 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0d5226915 | ||
|
|
b3d06906ff | ||
|
|
3f2e6fdb4e | ||
|
|
c00750c95a | ||
|
|
b959afe8c2 | ||
|
|
2810e06b3e | ||
|
|
5cf467a421 | ||
|
|
01b6f9099c | ||
|
|
616441e049 | ||
|
|
b205438601 | ||
|
|
e6d9439ba9 | ||
|
|
0a886bd8a8 | ||
|
|
43fe34dcbf | ||
|
|
7d49642376 | ||
|
|
01b7d96ebd | ||
|
|
6fcfa075f8 | ||
|
|
d888aeb2b4 | ||
|
|
92f34e2a99 | ||
|
|
424787c735 | ||
|
|
eb712a352d | ||
|
|
5fab9ee507 | ||
|
|
9c8771a378 | ||
|
|
9a7e44a96d | ||
|
|
112fea2f04 | ||
|
|
f9d62c324d | ||
|
|
55571ca3dd | ||
|
|
b06e1da529 | ||
|
|
0cefb47b66 | ||
|
|
a918c83ec1 | ||
|
|
2c8e1470d1 | ||
|
|
64e1f78739 | ||
|
|
ba95747ef9 | ||
|
|
3575cbc543 | ||
|
|
01ba8160ef | ||
|
|
939e365a4f | ||
|
|
803ce23169 | ||
|
|
00bc875846 | ||
|
|
5f186164a0 | ||
|
|
3a68e70f03 | ||
|
|
e9c6a97a07 | ||
|
|
3770c72ec0 | ||
|
|
c4a7f91d56 | ||
|
|
6db1406d68 | ||
|
|
e81449eddf | ||
|
|
7595ae3926 | ||
|
|
e9dbee6667 | ||
|
|
fa4d1d72dc | ||
|
|
0301f608bd | ||
|
|
a543568e1d | ||
|
|
576a3565f7 | ||
|
|
62cb2bb8b7 | ||
|
|
8e00882bb3 | ||
|
|
df3767df29 | ||
|
|
90998e2279 | ||
|
|
6bca7431b7 | ||
|
|
91b00817e3 | ||
|
|
d80ea40848 | ||
|
|
bedd88be2e | ||
|
|
bc892da992 | ||
|
|
fabceb52d3 | ||
|
|
b68539cc0c | ||
|
|
44bad77e93 | ||
|
|
e63843c6bb | ||
|
|
692994c2d3 | ||
|
|
facc17ec1b | ||
|
|
4c9691e192 | ||
|
|
c75cb9fb48 | ||
|
|
d362d8c3b3 | ||
|
|
eb9210de1c | ||
|
|
9cf541a6ba |
233 changed files with 54213 additions and 274 deletions
206
.clang-format
206
.clang-format
|
|
@ -1,21 +1,55 @@
|
|||
# Generated from CLion C/C++ Code Style settings
|
||||
---
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignArrayOfStructures: Left
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: Align
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AlignTrailingComments:
|
||||
Kind: Always
|
||||
OverEmptyLines: 0
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: Always
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Always
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BreakBeforeBraces: Custom
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BitFieldColonSpacing: Both
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
|
|
@ -23,44 +57,172 @@ BraceWrapping:
|
|||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakAfterAttributes: Never
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakArrays: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
ColumnLimit: 0
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 180
|
||||
CommentPragmas: "^ IWYU pragma:"
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: ^"(llvm|llvm-c|clang|clang-c)/
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: ^(<|"(gtest|gmock|isl|json)/)
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: .*
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: (Test)?$
|
||||
IncludeIsMainSourceRegex: ""
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseBlocks: true
|
||||
IndentCaseLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentExternBlock: Indent
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: BeforeHash
|
||||
IndentRequiresClause: true
|
||||
IndentWidth: 2
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MaxEmptyLinesToKeep: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertBraces: true
|
||||
InsertNewlineAtEOF: true
|
||||
InsertTrailingCommas: None
|
||||
IntegerLiteralSeparator:
|
||||
Binary: 0
|
||||
BinaryMinDigits: 0
|
||||
Decimal: 0
|
||||
DecimalMinDigits: 0
|
||||
Hex: 0
|
||||
HexMinDigits: 0
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
LambdaBodyIndentation: Signature
|
||||
Language: Cpp
|
||||
LineEnding: DeriveLF
|
||||
MacroBlockBegin: ""
|
||||
MacroBlockEnd: ""
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: All
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PPIndentWidth: -1
|
||||
PackConstructorInitializers: CurrentLine
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Left
|
||||
ReflowComments: false
|
||||
QualifierAlignment: Custom
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: true
|
||||
RemoveBracesLLVM: false
|
||||
RemoveSemicolon: true
|
||||
RequiresClausePosition: OwnLine
|
||||
RequiresExpressionIndentation: OuterScope
|
||||
SeparateDefinitionBlocks: Always
|
||||
ShortNamespaceLines: 1000
|
||||
SortIncludes: CaseSensitive
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: LexicographicNumeric
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: true
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: false
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterForeachMacros: true
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterIfMacros: true
|
||||
AfterOverloadedOperator: false
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 0
|
||||
SpacesInAngles: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: Never
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Latest
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 2
|
||||
UseTab: Always
|
||||
UseTab: Never
|
||||
WhitespaceSensitiveMacros:
|
||||
- BOOST_PP_STRINGIZE
|
||||
- CF_SWIFT_NAME
|
||||
- NS_SWIFT_NAME
|
||||
- PP_STRINGIZE
|
||||
- STRINGIZE
|
||||
QualifierOrder:
|
||||
- inline
|
||||
- static
|
||||
- const
|
||||
- type
|
||||
|
|
|
|||
20
.github/workflows/cmake.yml
vendored
20
.github/workflows/cmake.yml
vendored
|
|
@ -20,11 +20,25 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install LLVM
|
||||
run: sudo apt-get install -y llvm
|
||||
- name: Setup externals
|
||||
shell: bash
|
||||
run: |
|
||||
# If your submodules are configured to use SSH instead of HTTPS please uncomment the following line
|
||||
# git config --global url."https://github.com/".insteadOf "git@github.com:"
|
||||
auth_header="$(git config --local --get http.https://github.com/.extraheader)"
|
||||
git submodule sync --recursive
|
||||
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install python3 python-is-python3
|
||||
sudo apt-get install -y libx11-dev libgl1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev
|
||||
|
||||
cd Externals/glew/
|
||||
make extensions
|
||||
|
||||
- name: Set LLVM Toolchain
|
||||
run: |
|
||||
sudo apt-get install -y llvm
|
||||
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++ 10
|
||||
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 20
|
||||
|
||||
|
|
@ -40,3 +54,5 @@ jobs:
|
|||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
||||
run: ctest -C ${{env.BUILD_TYPE}}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
15
.gitmodules
vendored
Normal file
15
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[submodule "Externals/asio"]
|
||||
path = Externals/asio
|
||||
url = https://github.com/IlyaShurupov/asio.git
|
||||
[submodule "Externals/glfw"]
|
||||
path = Externals/glfw
|
||||
url = https://github.com/IlyaShurupov/glfw.git
|
||||
[submodule "Externals/imgui"]
|
||||
path = Externals/imgui
|
||||
url = https://github.com/IlyaShurupov/imgui.git
|
||||
[submodule "Externals/glew"]
|
||||
path = Externals/glew
|
||||
url = https://github.com/IlyaShurupov/glew.git
|
||||
[submodule "Externals/nanovg"]
|
||||
path = Externals/nanovg
|
||||
url = https://github.com/IlyaShurupov/nanovg.git
|
||||
943
.outdated/graphics/ext/easytab.h
Normal file
943
.outdated/graphics/ext/easytab.h
Normal file
|
|
@ -0,0 +1,943 @@
|
|||
/*
|
||||
EasyTab.h - Single-header multi-platform tablet library
|
||||
https://github.com/ApoorvaJ/EasyTab
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
USAGE
|
||||
----------------------------------------------------------------------------
|
||||
1) Add the following lines in exactly one of your cpp files to compile the
|
||||
implementation.
|
||||
|
||||
#define EASYTAB_IMPLEMENTATION
|
||||
#include "easytab.h"
|
||||
|
||||
2) Call EasyTab_Load() with correct parameters to initialize EasyTab. These
|
||||
parameters vary per OS, so look at the function declarations or examples
|
||||
below. Function returns EASYTAB_OK if initialization was successful.
|
||||
|
||||
3) Call EasyTab_HandleEvent() in your message-handling code. The function
|
||||
returns EASYTAB_OK if the message was a tablet message, and
|
||||
EASYTAB_EVENT_NOT_HANDLED otherwise.
|
||||
|
||||
4) Call EasyTab_Unload() in your shutdown code.
|
||||
|
||||
5) Once initialized, you can query tablet state using the EasyTab pointer.
|
||||
e.g.:
|
||||
|
||||
EasyTab->PosX // X position of the pen
|
||||
EasyTab->PosY // Y position of the pen
|
||||
EasyTab->Pressure // Pressure of the pen ranging from 0.0f to 1.0f
|
||||
|
||||
For more info, have a look at the EasyTabInfo struct below.
|
||||
|
||||
|
||||
* Add -lXi to compiler options to link XInput on Linux.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
EXAMPLES
|
||||
----------------------------------------------------------------------------
|
||||
1) Windows:
|
||||
|
||||
int CALLBACK WinMain(...)
|
||||
{
|
||||
HWND Window;
|
||||
|
||||
...
|
||||
|
||||
if (EasyTab_Load(Window) != EASYTAB_OK) // Load
|
||||
{
|
||||
OutputDebugStringA("Tablet init failed\n");
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
// Once you've set up EasyTab loading, unloading and event handling,
|
||||
// use the EasyTab variable at any point in your program to access
|
||||
// the tablet state:
|
||||
// EasyTab->PosX
|
||||
// EasyTab->PosY
|
||||
// EasyTab->Pressure
|
||||
// For more tablet information, look at the EasyTabInfo struct.
|
||||
|
||||
...
|
||||
|
||||
EasyTab_Unload(); // Unload
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WindowProc(
|
||||
HWND Window,
|
||||
UINT Message,
|
||||
WPARAM WParam,
|
||||
LPARAM LParam)
|
||||
{
|
||||
if (EasyTab_HandleEvent(Window, Message, LParam, WParam) == EASYTAB_OK) // Event
|
||||
{
|
||||
return true; // Tablet event handled
|
||||
}
|
||||
|
||||
switch (Message)
|
||||
{
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2) Linux:
|
||||
|
||||
int main(...)
|
||||
{
|
||||
Display* Disp;
|
||||
Window Win;
|
||||
|
||||
...
|
||||
|
||||
if (EasyTab_Load(Disp, Win) != EASYTAB_OK) // Load
|
||||
{
|
||||
printf("Tablet init failed\n");
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
while (XPending(Disp)) // Event loop
|
||||
{
|
||||
XEvent Event;
|
||||
XNextEvent(XlibDisplay, &Event);
|
||||
|
||||
if (EasyTab_HandleEvent(&Event) == EASYTAB_OK) // Event
|
||||
{
|
||||
continue; // Tablet event handled
|
||||
}
|
||||
|
||||
switch (Event.type)
|
||||
{
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
// Once you've set up EasyTab loading, unloading and event handling,
|
||||
// use the EasyTab variable at any point in your program to access
|
||||
// the tablet state:
|
||||
// EasyTab->PosX
|
||||
// EasyTab->PosY
|
||||
// EasyTab->Pressure
|
||||
// For more tablet information, look at the EasyTabInfo struct.
|
||||
|
||||
...
|
||||
|
||||
EasyTab_Unload(); // Unload
|
||||
}
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
CREDITS
|
||||
----------------------------------------------------------------------------
|
||||
Apoorva Joshi apoorvaj.io
|
||||
Sergio Gonzalez s3rg.io
|
||||
|
||||
This library is coded in the spirit of the stb libraries and follows the stb
|
||||
guidelines.
|
||||
|
||||
*/
|
||||
|
||||
// TODO: Null checks and warnings for EasyTab
|
||||
// TODO: Differentiate between stylus and eraser in the API
|
||||
// TODO: Linux support for relative mode
|
||||
// TODO: Documentation for relative mode
|
||||
|
||||
// =============================================================================
|
||||
// EasyTab header section
|
||||
// =============================================================================
|
||||
|
||||
#ifndef EASYTAB_H
|
||||
#define EASYTAB_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <X11/extensions/XInput.h>
|
||||
#endif // __linux__
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif // _WIN32
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EASYTAB_OK = 0,
|
||||
|
||||
// Errors
|
||||
EASYTAB_MEMORY_ERROR = -1,
|
||||
EASYTAB_X11_ERROR = -2,
|
||||
EASYTAB_DLL_LOAD_ERROR = -3,
|
||||
EASYTAB_WACOM_WIN32_ERROR = -4,
|
||||
EASYTAB_INVALID_FUNCTION_ERROR = -5,
|
||||
|
||||
EASYTAB_EVENT_NOT_HANDLED = -16,
|
||||
} EasyTabResult;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EASYTAB_TRACKING_MODE_SYSTEM = 0,
|
||||
EASYTAB_TRACKING_MODE_RELATIVE = 1,
|
||||
} EasyTabTrackingMode;
|
||||
|
||||
#ifdef WIN32
|
||||
// -----------------------------------------------------------------------------
|
||||
// wintab.h
|
||||
// -----------------------------------------------------------------------------
|
||||
#if 1
|
||||
|
||||
DECLARE_HANDLE(HMGR);
|
||||
DECLARE_HANDLE(HCTX);
|
||||
|
||||
typedef DWORD WTPKT;
|
||||
typedef DWORD FIX32;
|
||||
|
||||
// Messages
|
||||
#if 1
|
||||
|
||||
#define WT_DEFBASE 0x7FF0
|
||||
#define WT_MAXOFFSET 0xF
|
||||
|
||||
#define _WT_PACKET(b) ((b)+0)
|
||||
#define _WT_CTXOPEN(b) ((b)+1)
|
||||
#define _WT_CTXCLOSE(b) ((b)+2)
|
||||
#define _WT_CTXUPDATE(b) ((b)+3)
|
||||
#define _WT_CTXOVERLAP(b) ((b)+4)
|
||||
#define _WT_PROXIMITY(b) ((b)+5)
|
||||
#define _WT_INFOCHANGE(b) ((b)+6)
|
||||
#define _WT_CSRCHANGE(b) ((b)+7) /* 1.1 */
|
||||
#define _WT_PACKETEXT(b) ((b)+8) /* 1.4 */
|
||||
#define _WT_MAX(b) ((b)+WT_MAXOFFSET)
|
||||
|
||||
#define WT_PACKET _WT_PACKET(WT_DEFBASE)
|
||||
#define WT_CTXOPEN _WT_CTXOPEN(WT_DEFBASE)
|
||||
#define WT_CTXCLOSE _WT_CTXCLOSE(WT_DEFBASE)
|
||||
#define WT_CTXUPDATE _WT_CTXUPDATE(WT_DEFBASE)
|
||||
#define WT_CTXOVERLAP _WT_CTXOVERLAP(WT_DEFBASE)
|
||||
#define WT_PROXIMITY _WT_PROXIMITY(WT_DEFBASE)
|
||||
#define WT_INFOCHANGE _WT_INFOCHANGE(WT_DEFBASE)
|
||||
#define WT_CSRCHANGE _WT_CSRCHANGE(WT_DEFBASE) /* 1.1 */
|
||||
#define WT_PACKETEXT _WT_PACKETEXT(WT_DEFBASE) /* 1.4 */
|
||||
#define WT_MAX _WT_MAX(WT_DEFBASE)
|
||||
|
||||
#endif // Messages
|
||||
|
||||
// Flags
|
||||
#if 1
|
||||
|
||||
#define CTX_NAME 1
|
||||
#define CTX_OPTIONS 2
|
||||
#define CTX_STATUS 3
|
||||
#define CTX_LOCKS 4
|
||||
#define CTX_MSGBASE 5
|
||||
#define CTX_DEVICE 6
|
||||
#define CTX_PKTRATE 7
|
||||
#define CTX_PKTDATA 8
|
||||
#define CTX_PKTMODE 9
|
||||
#define CTX_MOVEMASK 10
|
||||
#define CTX_BTNDNMASK 11
|
||||
#define CTX_BTNUPMASK 12
|
||||
#define CTX_INORGX 13
|
||||
#define CTX_INORGY 14
|
||||
#define CTX_INORGZ 15
|
||||
#define CTX_INEXTX 16
|
||||
#define CTX_INEXTY 17
|
||||
#define CTX_INEXTZ 18
|
||||
#define CTX_OUTORGX 19
|
||||
#define CTX_OUTORGY 20
|
||||
#define CTX_OUTORGZ 21
|
||||
#define CTX_OUTEXTX 22
|
||||
#define CTX_OUTEXTY 23
|
||||
#define CTX_OUTEXTZ 24
|
||||
#define CTX_SENSX 25
|
||||
#define CTX_SENSY 26
|
||||
#define CTX_SENSZ 27
|
||||
#define CTX_SYSMODE 28
|
||||
#define CTX_SYSORGX 29
|
||||
#define CTX_SYSORGY 30
|
||||
#define CTX_SYSEXTX 31
|
||||
#define CTX_SYSEXTY 32
|
||||
#define CTX_SYSSENSX 33
|
||||
#define CTX_SYSSENSY 34
|
||||
#define CTX_MAX 34
|
||||
|
||||
// Context option values
|
||||
#define CXO_SYSTEM 0x0001
|
||||
#define CXO_PEN 0x0002
|
||||
#define CXO_MESSAGES 0x0004
|
||||
#define CXO_MARGIN 0x8000
|
||||
#define CXO_MGNINSIDE 0x4000
|
||||
#define CXO_CSRMESSAGES 0x0008 /* 1.1 */
|
||||
|
||||
#define DVC_NAME 1
|
||||
#define DVC_HARDWARE 2
|
||||
#define DVC_NCSRTYPES 3
|
||||
#define DVC_FIRSTCSR 4
|
||||
#define DVC_PKTRATE 5
|
||||
#define DVC_PKTDATA 6
|
||||
#define DVC_PKTMODE 7
|
||||
#define DVC_CSRDATA 8
|
||||
#define DVC_XMARGIN 9
|
||||
#define DVC_YMARGIN 10
|
||||
#define DVC_ZMARGIN 11
|
||||
#define DVC_X 12
|
||||
#define DVC_Y 13
|
||||
#define DVC_Z 14
|
||||
#define DVC_NPRESSURE 15
|
||||
#define DVC_TPRESSURE 16
|
||||
#define DVC_ORIENTATION 17
|
||||
#define DVC_ROTATION 18 /* 1.1 */
|
||||
#define DVC_PNPID 19 /* 1.1 */
|
||||
#define DVC_MAX 19
|
||||
|
||||
#define PK_CONTEXT 0x0001 // reporting context
|
||||
#define PK_STATUS 0x0002 // status bits
|
||||
#define PK_TIME 0x0004 // time stamp
|
||||
#define PK_CHANGED 0x0008 // change bit vector
|
||||
#define PK_SERIAL_NUMBER 0x0010 // packet serial number
|
||||
#define PK_CURSOR 0x0020 // reporting cursor
|
||||
#define PK_BUTTONS 0x0040 // button information
|
||||
#define PK_X 0x0080 // x axis
|
||||
#define PK_Y 0x0100 // y axis
|
||||
#define PK_Z 0x0200 // z axis
|
||||
#define PK_NORMAL_PRESSURE 0x0400 // normal or tip pressure
|
||||
#define PK_TANGENT_PRESSURE 0x0800 // tangential or barrel pressure
|
||||
#define PK_ORIENTATION 0x1000 // orientation info: tilts
|
||||
#define PK_ROTATION 0x2000 // rotation info; 1.1
|
||||
|
||||
// constants for use with pktdef.h
|
||||
#define PKEXT_ABSOLUTE 1
|
||||
#define PKEXT_RELATIVE 2
|
||||
|
||||
#define WTI_DEFCONTEXT 3
|
||||
#define WTI_DEFSYSCTX 4
|
||||
#define WTI_DEVICES 100
|
||||
#define WTI_DDCTXS 400 /* 1.1 */
|
||||
#define WTI_DSCTXS 500 /* 1.1 */
|
||||
|
||||
#endif // Flags
|
||||
|
||||
typedef struct tagAXIS {
|
||||
LONG axMin;
|
||||
LONG axMax;
|
||||
UINT axUnits;
|
||||
FIX32 axResolution;
|
||||
} AXIS, *PAXIS, NEAR *NPAXIS, FAR *LPAXIS;
|
||||
|
||||
#define LCNAMELEN 40
|
||||
typedef struct tagLOGCONTEXTA {
|
||||
char lcName[LCNAMELEN];
|
||||
UINT lcOptions;
|
||||
UINT lcStatus;
|
||||
UINT lcLocks;
|
||||
UINT lcMsgBase;
|
||||
UINT lcDevice;
|
||||
UINT lcPktRate;
|
||||
WTPKT lcPktData;
|
||||
WTPKT lcPktMode;
|
||||
WTPKT lcMoveMask;
|
||||
DWORD lcBtnDnMask;
|
||||
DWORD lcBtnUpMask;
|
||||
LONG lcInOrgX;
|
||||
LONG lcInOrgY;
|
||||
LONG lcInOrgZ;
|
||||
LONG lcInExtX;
|
||||
LONG lcInExtY;
|
||||
LONG lcInExtZ;
|
||||
LONG lcOutOrgX;
|
||||
LONG lcOutOrgY;
|
||||
LONG lcOutOrgZ;
|
||||
LONG lcOutExtX;
|
||||
LONG lcOutExtY;
|
||||
LONG lcOutExtZ;
|
||||
FIX32 lcSensX;
|
||||
FIX32 lcSensY;
|
||||
FIX32 lcSensZ;
|
||||
BOOL lcSysMode;
|
||||
int lcSysOrgX;
|
||||
int lcSysOrgY;
|
||||
int lcSysExtX;
|
||||
int lcSysExtY;
|
||||
FIX32 lcSysSensX;
|
||||
FIX32 lcSysSensY;
|
||||
} LOGCONTEXTA, *PLOGCONTEXTA, NEAR *NPLOGCONTEXTA, FAR *LPLOGCONTEXTA;
|
||||
|
||||
typedef struct tagEXTENSIONBASE { /* 1.4 */
|
||||
HCTX nContext;
|
||||
UINT nStatus;
|
||||
DWORD nTime;
|
||||
UINT nSerialNumber;
|
||||
} EXTENSIONBASE;
|
||||
|
||||
#endif // wintab.h
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#define PACKETDATA PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE
|
||||
#define PACKETMODE 0
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// pktdef.h
|
||||
// -----------------------------------------------------------------------------
|
||||
#if 1
|
||||
|
||||
// TODO: Simplify this file if we have a fixed packet format.
|
||||
// The macros here are too ugly.
|
||||
|
||||
#ifndef PACKETNAME
|
||||
/* if no packet name prefix */
|
||||
#define __PFX(x) x
|
||||
#define __IFX(x,y) x ## y
|
||||
#else
|
||||
/* add prefixes and infixes to packet format names */
|
||||
#define __PFX(x) __PFX2(PACKETNAME,x)
|
||||
#define __PFX2(p,x) __PFX3(p,x)
|
||||
#define __PFX3(p,x) p ## x
|
||||
#define __IFX(x,y) __IFX2(x,PACKETNAME,y)
|
||||
#define __IFX2(x,i,y) __IFX3(x,i,y)
|
||||
#define __IFX3(x,i,y) x ## i ## y
|
||||
#endif
|
||||
|
||||
#define __SFX2(x,s) __SFX3(x,s)
|
||||
#define __SFX3(x,s) x ## s
|
||||
|
||||
#define __TAG __IFX(tag,PACKET)
|
||||
#define __TYPES __PFX(PACKET), * __IFX(P,PACKET), NEAR * __IFX(NP,PACKET), FAR * __IFX(LP,PACKET)
|
||||
|
||||
#define __TAGE __IFX(tag,PACKETEXT)
|
||||
#define __TYPESE __PFX(PACKETEXT), * __IFX(P,PACKETEXT), NEAR * __IFX(NP,PACKETEXT), FAR * __IFX(LP,PACKETEXT)
|
||||
|
||||
#define __DATA (__PFX(PACKETDATA))
|
||||
#define __MODE (__PFX(PACKETMODE))
|
||||
#define __EXT(x) __SFX2(__PFX(PACKET),x)
|
||||
|
||||
|
||||
typedef struct __TAG {
|
||||
#if (__DATA & PK_CONTEXT)
|
||||
HCTX pkContext;
|
||||
#endif
|
||||
#if (__DATA & PK_STATUS)
|
||||
UINT pkStatus;
|
||||
#endif
|
||||
#if (__DATA & PK_TIME)
|
||||
DWORD pkTime;
|
||||
#endif
|
||||
#if (__DATA & PK_CHANGED)
|
||||
WTPKT pkChanged;
|
||||
#endif
|
||||
#if (__DATA & PK_SERIAL_NUMBER)
|
||||
UINT pkSerialNumber;
|
||||
#endif
|
||||
#if (__DATA & PK_CURSOR)
|
||||
UINT pkCursor;
|
||||
#endif
|
||||
#if (__DATA & PK_BUTTONS)
|
||||
DWORD pkButtons;
|
||||
#endif
|
||||
#if (__DATA & PK_X)
|
||||
LONG pkX;
|
||||
#endif
|
||||
#if (__DATA & PK_Y)
|
||||
LONG pkY;
|
||||
#endif
|
||||
#if (__DATA & PK_Z)
|
||||
LONG pkZ;
|
||||
#endif
|
||||
#if (__DATA & PK_NORMAL_PRESSURE)
|
||||
#if (__MODE & PK_NORMAL_PRESSURE)
|
||||
/* relative */
|
||||
int pkNormalPressure;
|
||||
#else
|
||||
/* absolute */
|
||||
UINT pkNormalPressure;
|
||||
#endif
|
||||
#endif
|
||||
#if (__DATA & PK_TANGENT_PRESSURE)
|
||||
#if (__MODE & PK_TANGENT_PRESSURE)
|
||||
/* relative */
|
||||
int pkTangentPressure;
|
||||
#else
|
||||
/* absolute */
|
||||
UINT pkTangentPressure;
|
||||
#endif
|
||||
#endif
|
||||
#if (__DATA & PK_ORIENTATION)
|
||||
ORIENTATION pkOrientation;
|
||||
#endif
|
||||
#if (__DATA & PK_ROTATION)
|
||||
ROTATION pkRotation; /* 1.1 */
|
||||
#endif
|
||||
|
||||
#ifndef NOWTEXTENSIONS
|
||||
/* extensions begin here. */
|
||||
#if (__EXT(FKEYS) == PKEXT_RELATIVE) || (__EXT(FKEYS) == PKEXT_ABSOLUTE)
|
||||
UINT pkFKeys;
|
||||
#endif
|
||||
#if (__EXT(TILT) == PKEXT_RELATIVE) || (__EXT(TILT) == PKEXT_ABSOLUTE)
|
||||
TILT pkTilt;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} __TYPES;
|
||||
|
||||
#ifndef NOWTEXTENSIONS
|
||||
typedef struct __TAGE {
|
||||
EXTENSIONBASE pkBase;
|
||||
|
||||
#if (__EXT(EXPKEYS) == PKEXT_RELATIVE) || (__EXT(EXPKEYS) == PKEXT_ABSOLUTE)
|
||||
EXPKEYSDATA pkExpKeys; /* 1.4 */
|
||||
#endif
|
||||
#if (__EXT(TOUCHSTRIP) == PKEXT_RELATIVE) || (__EXT(TOUCHSTRIP) == PKEXT_ABSOLUTE)
|
||||
SLIDERDATA pkTouchStrip; /* 1.4 */
|
||||
#endif
|
||||
#if (__EXT(TOUCHRING) == PKEXT_RELATIVE) || (__EXT(TOUCHRING) == PKEXT_ABSOLUTE)
|
||||
SLIDERDATA pkTouchRing; /* 1.4 */
|
||||
#endif
|
||||
|
||||
} __TYPESE;
|
||||
#endif
|
||||
|
||||
#undef PACKETNAME
|
||||
#undef __TAG
|
||||
#undef __TAGE
|
||||
#undef __TAG2
|
||||
#undef __TYPES
|
||||
#undef __TYPESE
|
||||
#undef __TYPES2
|
||||
#undef __DATA
|
||||
#undef __MODE
|
||||
#undef __PFX
|
||||
#undef __PFX2
|
||||
#undef __PFX3
|
||||
#undef __IFX
|
||||
#undef __IFX2
|
||||
#undef __IFX3
|
||||
#undef __SFX2
|
||||
#undef __SFX3
|
||||
|
||||
#endif // pktdef.h
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
typedef UINT (WINAPI * WTINFOA) (UINT, UINT, LPVOID);
|
||||
typedef HCTX (WINAPI * WTOPENA) (HWND, LPLOGCONTEXTA, BOOL);
|
||||
typedef BOOL (WINAPI * WTGETA) (HCTX, LPLOGCONTEXTA);
|
||||
typedef BOOL (WINAPI * WTSETA) (HCTX, LPLOGCONTEXTA);
|
||||
typedef BOOL (WINAPI * WTCLOSE) (HCTX);
|
||||
typedef BOOL (WINAPI * WTENABLE) (HCTX, BOOL);
|
||||
typedef BOOL (WINAPI * WTPACKET) (HCTX, UINT, LPVOID);
|
||||
typedef BOOL (WINAPI * WTOVERLAP) (HCTX, BOOL);
|
||||
typedef BOOL (WINAPI * WTSAVE) (HCTX, LPVOID);
|
||||
typedef BOOL (WINAPI * WTCONFIG) (HCTX, HWND);
|
||||
typedef HCTX (WINAPI * WTRESTORE) (HWND, LPVOID, BOOL);
|
||||
typedef BOOL (WINAPI * WTEXTSET) (HCTX, UINT, LPVOID);
|
||||
typedef BOOL (WINAPI * WTEXTGET) (HCTX, UINT, LPVOID);
|
||||
typedef BOOL (WINAPI * WTQUEUESIZESET) (HCTX, int);
|
||||
typedef int (WINAPI * WTDATAPEEK) (HCTX, UINT, UINT, int, LPVOID, LPINT);
|
||||
typedef int (WINAPI * WTPACKETSGET) (HCTX, int, LPVOID);
|
||||
typedef HMGR (WINAPI * WTMGROPEN) (HWND, UINT);
|
||||
typedef BOOL (WINAPI * WTMGRCLOSE) (HMGR);
|
||||
typedef HCTX (WINAPI * WTMGRDEFCONTEXT) (HMGR, BOOL);
|
||||
typedef HCTX (WINAPI * WTMGRDEFCONTEXTEX) (HMGR, UINT, BOOL);
|
||||
|
||||
#endif // WIN32
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Enums
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Use this enum in conjunction with EasyTab->Buttons to check for tablet button
|
||||
presses.
|
||||
e.g. To check for lower pen button press, use:
|
||||
|
||||
if (EasyTab->Buttons & EasyTab_Buttons_Pen_Lower)
|
||||
{
|
||||
// Lower button is pressed
|
||||
}
|
||||
*/
|
||||
enum EasyTab_Buttons_
|
||||
{
|
||||
EasyTab_Buttons_Pen_Touch = 1 << 0, // Pen is touching tablet
|
||||
EasyTab_Buttons_Pen_Lower = 1 << 1, // Lower pen button is pressed
|
||||
EasyTab_Buttons_Pen_Upper = 1 << 2, // Upper pen button is pressed
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Structs
|
||||
// -----------------------------------------------------------------------------
|
||||
typedef struct
|
||||
{
|
||||
int32_t PosX, PosY;
|
||||
float Pressure; // Range: 0.0f to 1.0f
|
||||
int32_t Buttons; // Bit field. Use with the EasyTab_Buttons_ enum.
|
||||
|
||||
int32_t RangeX, RangeY;
|
||||
int32_t MaxPressure;
|
||||
|
||||
#ifdef __linux__
|
||||
XDevice* Device;
|
||||
uint32_t MotionType;
|
||||
XEventClass EventClasses[1024];
|
||||
uint32_t NumEventClasses;
|
||||
#endif // __linux__
|
||||
|
||||
#ifdef WIN32
|
||||
HINSTANCE Dll;
|
||||
HCTX Context;
|
||||
|
||||
WTINFOA WTInfoA;
|
||||
WTOPENA WTOpenA;
|
||||
WTGETA WTGetA;
|
||||
WTSETA WTSetA;
|
||||
WTCLOSE WTClose;
|
||||
WTPACKET WTPacket;
|
||||
WTENABLE WTEnable;
|
||||
WTOVERLAP WTOverlap;
|
||||
WTSAVE WTSave;
|
||||
WTCONFIG WTConfig;
|
||||
WTRESTORE WTRestore;
|
||||
WTEXTSET WTExtSet;
|
||||
WTEXTGET WTExtGet;
|
||||
WTQUEUESIZESET WTQueueSizeSet;
|
||||
WTDATAPEEK WTDataPeek;
|
||||
WTPACKETSGET WTPacketsGet;
|
||||
WTMGROPEN WTMgrOpen;
|
||||
WTMGRCLOSE WTMgrClose;
|
||||
WTMGRDEFCONTEXT WTMgrDefContext;
|
||||
WTMGRDEFCONTEXTEX WTMgrDefContextEx;
|
||||
#endif // WIN32
|
||||
} EasyTabInfo;
|
||||
|
||||
extern EasyTabInfo* EasyTab;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Function declarations
|
||||
// -----------------------------------------------------------------------------
|
||||
#if defined(__linux__)
|
||||
|
||||
EasyTabResult EasyTab_Load(Display* Disp, Window Win);
|
||||
EasyTabResult EasyTab_HandleEvent(XEvent* Event);
|
||||
void EasyTab_Unload(Display* Disp);
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
EasyTabResult EasyTab_Load(HWND Window);
|
||||
EasyTabResult EasyTab_Load_Ex(HWND Window,
|
||||
EasyTabTrackingMode Mode,
|
||||
float RelativeModeSensitivity,
|
||||
int32_t MoveCursor);
|
||||
EasyTabResult EasyTab_HandleEvent(HWND Window,
|
||||
UINT Message,
|
||||
LPARAM LParam,
|
||||
WPARAM WParam);
|
||||
void EasyTab_Unload();
|
||||
|
||||
#else
|
||||
|
||||
// Save some trouble when porting.
|
||||
#error "Unsupported platform."
|
||||
|
||||
#endif // __linux__ _WIN32
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#endif // EASYTAB_H
|
||||
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// EasyTab implementation section
|
||||
// =============================================================================
|
||||
|
||||
#ifdef EASYTAB_IMPLEMENTATION
|
||||
|
||||
EasyTabInfo* EasyTab;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Linux implementation
|
||||
// -----------------------------------------------------------------------------
|
||||
#ifdef __linux__
|
||||
|
||||
EasyTabResult EasyTab_Load(Display* Disp, Window Win)
|
||||
{
|
||||
EasyTab = (EasyTabInfo*)calloc(1, sizeof(EasyTabInfo)); // We want init to zero, hence calloc.
|
||||
if (!EasyTab) { return EASYTAB_MEMORY_ERROR; }
|
||||
|
||||
int32_t Count;
|
||||
XDeviceInfoPtr Devices = (XDeviceInfoPtr)XListInputDevices(Disp, &Count);
|
||||
if (!Devices) { return EASYTAB_X11_ERROR; }
|
||||
|
||||
for (int32_t i = 0; i < Count; i++)
|
||||
{
|
||||
if (!strstr(Devices[i].name, "stylus") &&
|
||||
!strstr(Devices[i].name, "eraser")) { continue; }
|
||||
|
||||
EasyTab->Device = XOpenDevice(Disp, Devices[i].id);
|
||||
XAnyClassPtr ClassPtr = Devices[i].inputclassinfo;
|
||||
|
||||
for (int32_t j = 0; j < Devices[i].num_classes; j++)
|
||||
{
|
||||
#if defined(__cplusplus)
|
||||
switch (ClassPtr->c_class)
|
||||
#else
|
||||
switch (ClassPtr->class)
|
||||
#endif
|
||||
{
|
||||
case ValuatorClass:
|
||||
{
|
||||
XValuatorInfo *Info = (XValuatorInfo *)ClassPtr;
|
||||
// X
|
||||
if (Info->num_axes > 0)
|
||||
{
|
||||
int32_t min = Info->axes[0].min_value;
|
||||
EasyTab->RangeX = Info->axes[0].max_value;
|
||||
//printf("Max/min x values: %d, %d\n", min, EasyTab->RangeX); // TODO: Platform-print macro
|
||||
}
|
||||
|
||||
// Y
|
||||
if (Info->num_axes > 1)
|
||||
{
|
||||
int32_t min = Info->axes[1].min_value;
|
||||
EasyTab->RangeY = Info->axes[1].max_value;
|
||||
//printf("Max/min y values: %d, %d\n", min, EasyTab->RangeY);
|
||||
}
|
||||
|
||||
// Pressure
|
||||
if (Info->num_axes > 2)
|
||||
{
|
||||
int32_t min = Info->axes[2].min_value;
|
||||
EasyTab->MaxPressure = Info->axes[2].max_value;
|
||||
//printf("Max/min pressure values: %d, %d\n", min, EasyTab->MaxPressure);
|
||||
}
|
||||
|
||||
XEventClass EventClass;
|
||||
DeviceMotionNotify(EasyTab->Device, EasyTab->MotionType, EventClass);
|
||||
if (EventClass)
|
||||
{
|
||||
EasyTab->EventClasses[EasyTab->NumEventClasses] = EventClass;
|
||||
EasyTab->NumEventClasses++;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
ClassPtr = (XAnyClassPtr) ((uint8_t*)ClassPtr + ClassPtr->length); // TODO: Access this as an array to avoid pointer arithmetic?
|
||||
}
|
||||
|
||||
XSelectExtensionEvent(Disp, Win, EasyTab->EventClasses, EasyTab->NumEventClasses);
|
||||
}
|
||||
|
||||
XFreeDeviceList(Devices);
|
||||
|
||||
if (EasyTab->Device != 0) { return EASYTAB_OK; }
|
||||
else { return EASYTAB_X11_ERROR; }
|
||||
}
|
||||
|
||||
EasyTabResult EasyTab_HandleEvent(XEvent* Event)
|
||||
{
|
||||
if (Event->type != EasyTab->MotionType) { return EASYTAB_EVENT_NOT_HANDLED; }
|
||||
|
||||
XDeviceMotionEvent* MotionEvent = (XDeviceMotionEvent*)(Event);
|
||||
EasyTab->PosX = MotionEvent->x;
|
||||
EasyTab->PosY = MotionEvent->y;
|
||||
EasyTab->Pressure = (float)MotionEvent->axis_data[2] / (float)EasyTab->MaxPressure;
|
||||
return EASYTAB_OK;
|
||||
}
|
||||
|
||||
void EasyTab_Unload(Display* Disp)
|
||||
{
|
||||
XCloseDevice(Disp, EasyTab->Device);
|
||||
free(EasyTab);
|
||||
EasyTab = NULL;
|
||||
}
|
||||
|
||||
#endif // __linux__
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Windows implementation
|
||||
// -----------------------------------------------------------------------------
|
||||
#ifdef WIN32
|
||||
|
||||
#define GETPROCADDRESS(type, func) \
|
||||
EasyTab->func = (type)GetProcAddress(EasyTab->Dll, #func); \
|
||||
if (!EasyTab->func) \
|
||||
{ \
|
||||
OutputDebugStringA("Function " #func " not found in Wintab32.dll.\n"); \
|
||||
return EASYTAB_INVALID_FUNCTION_ERROR; \
|
||||
}
|
||||
|
||||
|
||||
EasyTabResult EasyTab_Load(HWND Window)
|
||||
{
|
||||
return EasyTab_Load_Ex(Window, EASYTAB_TRACKING_MODE_SYSTEM, 0, 1);
|
||||
}
|
||||
|
||||
EasyTabResult EasyTab_Load_Ex(HWND Window,
|
||||
EasyTabTrackingMode TrackingMode,
|
||||
float RelativeModeSensitivity,
|
||||
int32_t MoveCursor)
|
||||
{
|
||||
EasyTab = (EasyTabInfo*)calloc(1, sizeof(EasyTabInfo)); // We want init to zero, hence calloc.
|
||||
if (!EasyTab) { return EASYTAB_MEMORY_ERROR; }
|
||||
|
||||
// Load Wintab DLL and get function addresses
|
||||
{
|
||||
EasyTab->Dll = LoadLibraryA("Wintab32.dll");
|
||||
if (!EasyTab->Dll)
|
||||
{
|
||||
OutputDebugStringA("Wintab32.dll not found.\n");
|
||||
return EASYTAB_DLL_LOAD_ERROR;
|
||||
}
|
||||
|
||||
GETPROCADDRESS(WTINFOA , WTInfoA);
|
||||
GETPROCADDRESS(WTOPENA , WTOpenA);
|
||||
GETPROCADDRESS(WTGETA , WTGetA);
|
||||
GETPROCADDRESS(WTSETA , WTSetA);
|
||||
GETPROCADDRESS(WTCLOSE , WTClose);
|
||||
GETPROCADDRESS(WTPACKET , WTPacket);
|
||||
GETPROCADDRESS(WTENABLE , WTEnable);
|
||||
GETPROCADDRESS(WTOVERLAP , WTOverlap);
|
||||
GETPROCADDRESS(WTSAVE , WTSave);
|
||||
GETPROCADDRESS(WTCONFIG , WTConfig);
|
||||
GETPROCADDRESS(WTRESTORE , WTRestore);
|
||||
GETPROCADDRESS(WTEXTSET , WTExtSet);
|
||||
GETPROCADDRESS(WTEXTGET , WTExtGet);
|
||||
GETPROCADDRESS(WTQUEUESIZESET , WTQueueSizeSet);
|
||||
GETPROCADDRESS(WTDATAPEEK , WTDataPeek);
|
||||
GETPROCADDRESS(WTPACKETSGET , WTPacketsGet);
|
||||
GETPROCADDRESS(WTMGROPEN , WTMgrOpen);
|
||||
GETPROCADDRESS(WTMGRCLOSE , WTMgrClose);
|
||||
GETPROCADDRESS(WTMGRDEFCONTEXT , WTMgrDefContext);
|
||||
GETPROCADDRESS(WTMGRDEFCONTEXTEX , WTMgrDefContextEx);
|
||||
}
|
||||
|
||||
if (!EasyTab->WTInfoA(0, 0, NULL))
|
||||
{
|
||||
OutputDebugStringA("Wintab services not available.\n");
|
||||
return EASYTAB_WACOM_WIN32_ERROR;
|
||||
}
|
||||
|
||||
// Open context
|
||||
{
|
||||
LOGCONTEXTA LogContext = {0};
|
||||
AXIS RangeX = {0};
|
||||
AXIS RangeY = {0};
|
||||
AXIS Pressure = {0};
|
||||
|
||||
EasyTab->WTInfoA(WTI_DDCTXS, 0, &LogContext);
|
||||
EasyTab->WTInfoA(WTI_DEVICES, DVC_X, &RangeX);
|
||||
EasyTab->WTInfoA(WTI_DEVICES, DVC_Y, &RangeY);
|
||||
EasyTab->WTInfoA(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
|
||||
|
||||
LogContext.lcPktData = PACKETDATA; // ??
|
||||
LogContext.lcOptions |= CXO_MESSAGES;
|
||||
if (MoveCursor) { LogContext.lcOptions |= CXO_SYSTEM; }
|
||||
LogContext.lcPktMode = PACKETMODE;
|
||||
LogContext.lcMoveMask = PACKETDATA;
|
||||
LogContext.lcBtnUpMask = LogContext.lcBtnDnMask;
|
||||
|
||||
LogContext.lcOutOrgX = 0;
|
||||
LogContext.lcOutOrgY = 0;
|
||||
LogContext.lcOutExtX = GetSystemMetrics(SM_CXSCREEN);
|
||||
LogContext.lcOutExtY = -GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
LogContext.lcSysOrgX = 0;
|
||||
LogContext.lcSysOrgY = 0;
|
||||
LogContext.lcSysExtX = GetSystemMetrics(SM_CXSCREEN);
|
||||
LogContext.lcSysExtY = GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
if (TrackingMode == EASYTAB_TRACKING_MODE_RELATIVE)
|
||||
{
|
||||
LogContext.lcPktMode |= PK_X | PK_Y; // TODO: Should this be included in the
|
||||
// PACKETMODE macro define up top?
|
||||
LogContext.lcSysMode = 1;
|
||||
|
||||
if (RelativeModeSensitivity > 1.0f)
|
||||
{
|
||||
RelativeModeSensitivity = 1.0f;
|
||||
}
|
||||
else if (RelativeModeSensitivity < 0.0f)
|
||||
{
|
||||
RelativeModeSensitivity = 0.0f;
|
||||
}
|
||||
|
||||
// Wintab expects sensitivity to be a 32-bit fixed point number
|
||||
// with the radix point between the two words. Thus, the type
|
||||
// contains 16 bits to the left of the radix point and 16 bits to
|
||||
// the right of it.
|
||||
//
|
||||
// 0x10000 Hex
|
||||
// = 65,536 Decimal
|
||||
// = 0000 0000 0000 0001 . 0000 0000 0000 0000 Binary
|
||||
// = 1.0 Fixed Point
|
||||
uint32_t Sensitivity = (uint32_t)(0x10000 * RelativeModeSensitivity);
|
||||
|
||||
if (MoveCursor)
|
||||
{
|
||||
LogContext.lcSysSensX = LogContext.lcSysSensY = Sensitivity;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogContext.lcSensX = LogContext.lcSensY = Sensitivity;
|
||||
}
|
||||
}
|
||||
|
||||
EasyTab->Context = EasyTab->WTOpenA(Window, &LogContext, TRUE);
|
||||
|
||||
if (!EasyTab->Context)
|
||||
{
|
||||
OutputDebugStringA("Wintab context couldn't be opened.\n");
|
||||
return EASYTAB_WACOM_WIN32_ERROR;
|
||||
}
|
||||
|
||||
// Get tablet capabilites
|
||||
{
|
||||
EasyTab->MaxPressure = Pressure.axMax;
|
||||
EasyTab->RangeX = RangeX.axMax;
|
||||
EasyTab->RangeY = RangeY.axMax;
|
||||
}
|
||||
}
|
||||
|
||||
return EASYTAB_OK;
|
||||
}
|
||||
|
||||
#undef GETPROCADDRESS
|
||||
|
||||
EasyTabResult EasyTab_HandleEvent(HWND Window, UINT Message, LPARAM LParam, WPARAM WParam)
|
||||
{
|
||||
PACKET Packet = { 0 };
|
||||
|
||||
if (Message == WT_PACKET &&
|
||||
(HCTX)LParam == EasyTab->Context &&
|
||||
EasyTab->WTPacket(EasyTab->Context, (UINT)WParam, &Packet))
|
||||
{
|
||||
POINT Point = { 0 };
|
||||
Point.x = Packet.pkX;
|
||||
Point.y = Packet.pkY;
|
||||
ScreenToClient(Window, &Point);
|
||||
EasyTab->PosX = Point.x;
|
||||
EasyTab->PosY = Point.y;
|
||||
|
||||
EasyTab->Pressure = (float)Packet.pkNormalPressure / (float)EasyTab->MaxPressure;
|
||||
EasyTab->Buttons = Packet.pkButtons;
|
||||
return EASYTAB_OK;
|
||||
}
|
||||
|
||||
return EASYTAB_EVENT_NOT_HANDLED;
|
||||
}
|
||||
|
||||
void EasyTab_Unload()
|
||||
{
|
||||
if (EasyTab->Context) { EasyTab->WTClose(EasyTab->Context); }
|
||||
if (EasyTab->Dll) { FreeLibrary(EasyTab->Dll); }
|
||||
free(EasyTab);
|
||||
EasyTab = NULL;
|
||||
}
|
||||
|
||||
#endif // WIN32
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif // EASYTAB_IMPLEMENTATION
|
||||
1191
.outdated/graphics/ext/objloader.h
Normal file
1191
.outdated/graphics/ext/objloader.h
Normal file
File diff suppressed because it is too large
Load diff
19
.outdated/graphics/inc/GraphicsLibApi.h
Normal file
19
.outdated/graphics/inc/GraphicsLibApi.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "env.h"
|
||||
|
||||
#ifdef ENV_OS_ANDROID
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES3/gl32.h>
|
||||
#else
|
||||
#include "GL/glew.h"
|
||||
#endif
|
||||
|
||||
#ifdef ENV_OS_ANDROID
|
||||
#define GLW_CONTEXT_DEPTH_BITS 16
|
||||
#define GLW_CONTEXT_DEPTH_COMPONENT GL_DEPTH_COMPONENT16
|
||||
#else
|
||||
#define GLW_CONTEXT_DEPTH_BITS 32
|
||||
#define GLW_CONTEXT_DEPTH_COMPONENT GL_DEPTH_COMPONENT32
|
||||
#endif
|
||||
53
.outdated/graphics/inc/animations.h
Normal file
53
.outdated/graphics/inc/animations.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#pragma once
|
||||
|
||||
#include "rect.h"
|
||||
#include "color.h"
|
||||
|
||||
namespace tp {
|
||||
namespace glw {
|
||||
|
||||
extern bool gInTransition;
|
||||
|
||||
struct AnimValue {
|
||||
halnf mValPrev = 0;
|
||||
halnf mVal = 0;
|
||||
time_ms mTimeStart = 0;
|
||||
halni mTimeAnim = 250;
|
||||
|
||||
halnf interpolate() const;
|
||||
|
||||
AnimValue();
|
||||
AnimValue(halnf val);
|
||||
|
||||
halnf prev() { return mValPrev; }
|
||||
void set(halnf val);
|
||||
void setNoTransition(halnf);
|
||||
void setAnimTime(halni time);
|
||||
halnf get() const;
|
||||
halnf getTarget() const;
|
||||
bool inTransition() const;
|
||||
explicit operator halnf() const;
|
||||
void operator=(halnf val);
|
||||
};
|
||||
|
||||
struct AnimRect : rect<AnimValue> {
|
||||
|
||||
AnimRect() {
|
||||
set({ 0, 0, 0, 0 });
|
||||
setAnimTime(450);
|
||||
}
|
||||
|
||||
rectf get() const;
|
||||
rectf getTarget() const;
|
||||
void setNoTransition(rectf);
|
||||
void set(const rectf&);
|
||||
void setAnimTime(halni time_ms);
|
||||
};
|
||||
|
||||
struct AnimColor {
|
||||
AnimRect mColor;
|
||||
rgba get() const;
|
||||
void set(const rgba&);
|
||||
};
|
||||
};
|
||||
};
|
||||
84
.outdated/graphics/inc/canvas.h
Normal file
84
.outdated/graphics/inc/canvas.h
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "stringt.h"
|
||||
#include "fbuffer.h"
|
||||
|
||||
namespace tp {
|
||||
namespace glw {
|
||||
class Canvas {
|
||||
|
||||
typedef rectf Rect;
|
||||
typedef vec2f Vec2;
|
||||
typedef rgba Col;
|
||||
typedef tp::halnf Val;
|
||||
|
||||
Col mColorPrimary;
|
||||
Col mColorSecondary;
|
||||
|
||||
void* mCtx = NULL;
|
||||
tp::halnf mDpmm = 1;
|
||||
tp::halnf mUIScale = 1;
|
||||
|
||||
public:
|
||||
|
||||
Rect mClamping;
|
||||
Rect mVieport;
|
||||
|
||||
enum Align : uint4 {
|
||||
LEFT = 1 << 0, // Default, horizontally to left.
|
||||
CENTER = 1 << 1, // horizontally to center.
|
||||
RIGHT = 1 << 2, // horizontally to right.
|
||||
TOP = 1 << 3, // vertically to top.
|
||||
MIDDLE = 1 << 4, // vertically to middle.
|
||||
BOTTOM = 1 << 5, // vertically to bottom.
|
||||
BASELINE = 1 << 6, // Default, vertically to baseline.
|
||||
CENTER_MIDDLE = CENTER | MIDDLE,
|
||||
LEFT_MIDDLE = LEFT | MIDDLE,
|
||||
};
|
||||
|
||||
Canvas();
|
||||
|
||||
Val& convert2pxls(Val&);
|
||||
Rect& convert2pxls(Rect&);
|
||||
Vec2& convert2pxls(Vec2&);
|
||||
Val as2pxls(Val);
|
||||
|
||||
// Canvas Manipulation
|
||||
void beginDraw(Rect viewport, tp::halnf dpmm, tp::halnf uiscale);
|
||||
void clear(Col color = 0);
|
||||
void endDraw();
|
||||
|
||||
void setClamping(Rect rec);
|
||||
void resetViewport();
|
||||
|
||||
// Params control
|
||||
void setCol1(const Col& col);
|
||||
void setCol2(const Col& col);
|
||||
|
||||
// Shapes
|
||||
void rect(Rect rec, halnf rounding = 0, halnf borders = 0);
|
||||
void circle(Vec2 rec, halnf radius, halnf borders = 0);
|
||||
void trig(Vec2 p1, Vec2 p2, Vec2 p3);
|
||||
void line(Vec2 p1, Vec2 p2, halnf thikness = 2);
|
||||
|
||||
// Text
|
||||
void text(const string text, Rect rec, halnf size, Align align = Align::CENTER_MIDDLE);
|
||||
void text(const char* start, const char* end, Rect rec, halnf size, Align align = Align::CENTER_MIDDLE);
|
||||
|
||||
void drawColorwheel(Rect rec, const rgb& col);
|
||||
|
||||
// image
|
||||
struct ImageHandle {
|
||||
halni mId = NULL;
|
||||
void createFromBuff(glw::fbuffer* buff, Canvas* drawer);
|
||||
void free(Canvas* drawer);
|
||||
~ImageHandle();
|
||||
};
|
||||
|
||||
void drawImage(Rect rec, ImageHandle* image, halnf angle = 0.f, halnf alpha = 1.f, halnf rounding = 0.f);
|
||||
|
||||
~Canvas();
|
||||
};
|
||||
};
|
||||
};
|
||||
48
.outdated/graphics/inc/debugui.h
Normal file
48
.outdated/graphics/inc/debugui.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
|
||||
#include "window.h"
|
||||
|
||||
namespace ImGui {
|
||||
|
||||
bool SubMenuBegin(const char* desc, int level);
|
||||
void SubMenuEnd(int level);
|
||||
|
||||
void ToolTip(const char* desc);
|
||||
|
||||
struct PopupData {
|
||||
bool opened = false;
|
||||
bool ishovered = false;
|
||||
tp::vec2f p1 = 0;
|
||||
tp::vec2f p2 = 0;
|
||||
operator bool() {
|
||||
return opened;
|
||||
}
|
||||
};
|
||||
|
||||
PopupData HoverPopupBeginButton(const char* id, tp::vec2f butsize = 200, tp::vec2f popupsize = 200);
|
||||
PopupData HoverPopupBegin(const char* id, tp::vec2f size = 200, tp::vec2f pos = -1, int flags = 0);
|
||||
void HoverPopupEnd(PopupData& in);
|
||||
|
||||
void ApplyStyle(tp::halnf dpmm, float font_size_mm = 5, float ui_scale = 1);
|
||||
};
|
||||
|
||||
namespace tp {
|
||||
namespace glw {
|
||||
|
||||
typedef void (DebugUiDrawCallBack)(void* cd);
|
||||
|
||||
struct DebugUI {
|
||||
tp::halnf mDPMM = 1;
|
||||
tp::halnf mFontSizeMM = 3;
|
||||
tp::halnf mUIScale = 1;
|
||||
|
||||
DebugUiDrawCallBack* cb = NULL;
|
||||
void* cd = NULL;
|
||||
|
||||
struct DebugUiInternalContext* mCtx = NULL;
|
||||
|
||||
DebugUI(Window& window, DebugUiDrawCallBack* acb, void* acd);
|
||||
void drawDebugUI(tp::halnf dpmm);
|
||||
~DebugUI();
|
||||
};
|
||||
};
|
||||
};
|
||||
40
.outdated/graphics/inc/fbuffer.h
Normal file
40
.outdated/graphics/inc/fbuffer.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "rect.h"
|
||||
#include "color.h"
|
||||
|
||||
namespace tp {
|
||||
namespace glw {
|
||||
class fbuffer {
|
||||
|
||||
uint4 mFrameBufferID = 0; // regroups 0, 1, or more textures, and 0 or 1 depth buffer.
|
||||
uint4 mTextureId = 0; // texture we're going to render to ( colour attachement #0 )
|
||||
uint4 mDepthBufferID = 0;
|
||||
uint4 mDrawBuffers[1];
|
||||
|
||||
vec2f mSize;
|
||||
|
||||
public:
|
||||
|
||||
rgba mClearCol = 0.f;
|
||||
|
||||
fbuffer(const vec2f& size);
|
||||
fbuffer(const vec2f& size, tp::uint1 samples);
|
||||
|
||||
void beginDraw();
|
||||
void setViewport(const rectf& viewport);
|
||||
void clear();
|
||||
void endDraw();
|
||||
|
||||
uint4 texId() const;
|
||||
uint4 buffId() const;
|
||||
|
||||
const vec2f& getSize() const;
|
||||
uhalni sizeAllocatedMem() const;
|
||||
uhalni sizeUsedMem() const;
|
||||
|
||||
~fbuffer();
|
||||
};
|
||||
};
|
||||
};
|
||||
167
.outdated/graphics/inc/keycodes.h
Normal file
167
.outdated/graphics/inc/keycodes.h
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
namespace tp {
|
||||
|
||||
// basically copy of glfw keys
|
||||
enum class Keycode {
|
||||
|
||||
/* Printable keys */
|
||||
SPACE = 32,
|
||||
APOSTROPHE = 39, /* ' */
|
||||
COMMA = 44, /* , */
|
||||
MINUS = 45, /* - */
|
||||
PERIOD = 46, /* . */
|
||||
SLASH = 0xBF, /* \ */
|
||||
N0 = 48,
|
||||
N1 = 49,
|
||||
N2 = 50,
|
||||
N3 = 51,
|
||||
N4 = 52,
|
||||
N5 = 53,
|
||||
N6 = 54,
|
||||
N7 = 55,
|
||||
N8 = 56,
|
||||
N9 = 57,
|
||||
SEMICOLON = 59, /* ; */
|
||||
EQUAL = 61, /* = */
|
||||
A = 65,
|
||||
B = 66,
|
||||
C = 67,
|
||||
D = 68,
|
||||
E = 69,
|
||||
F = 70,
|
||||
G = 71,
|
||||
H = 72,
|
||||
I = 73,
|
||||
J = 74,
|
||||
K = 75,
|
||||
L = 76,
|
||||
M = 77,
|
||||
N = 78,
|
||||
O = 79,
|
||||
P = 80,
|
||||
Q = 81,
|
||||
R = 82,
|
||||
S = 83,
|
||||
T = 84,
|
||||
U = 85,
|
||||
V = 86,
|
||||
W = 87,
|
||||
X = 88,
|
||||
Y = 89,
|
||||
Z = 90,
|
||||
LEFT_BRACKET = 91, /* [ */
|
||||
BACKSLASH = 92, /* \ */
|
||||
RIGHT_BRACKET = 93, /* ] */
|
||||
GRAVE_ACCENT = 96, /* ` */
|
||||
WORLD_1 = 161, /* non-US #1 */
|
||||
WORLD_2 = 162, /* non-US #2 */
|
||||
|
||||
/* function keys */
|
||||
|
||||
ESCAPE = 256,
|
||||
ENTER = 257,
|
||||
TAB = 258,
|
||||
BACKSPACE = 259,
|
||||
INSERT = 260,
|
||||
DELETE = 261,
|
||||
RIGHT = 262,
|
||||
LEFT = 263,
|
||||
DOWN = 264,
|
||||
UP = 265,
|
||||
PAGE_UP = 266,
|
||||
PAGE_DOWN = 267,
|
||||
HOME = 268,
|
||||
END = 269,
|
||||
CAPS_LOCK = 280,
|
||||
SCROLL_LOCK = 281,
|
||||
NUM_LOCK = 282,
|
||||
PRINT_SCREEN = 283,
|
||||
PAUSE = 284,
|
||||
F1 = 290,
|
||||
F2 = 291,
|
||||
F3 = 292,
|
||||
F4 = 293,
|
||||
F5 = 294,
|
||||
F6 = 295,
|
||||
F7 = 296,
|
||||
F8 = 297,
|
||||
F9 = 298,
|
||||
F10 = 299,
|
||||
F11 = 300,
|
||||
F12 = 301,
|
||||
F13 = 302,
|
||||
F14 = 303,
|
||||
F15 = 304,
|
||||
F16 = 305,
|
||||
F17 = 306,
|
||||
F18 = 307,
|
||||
F19 = 308,
|
||||
F20 = 309,
|
||||
F21 = 310,
|
||||
F22 = 311,
|
||||
F23 = 312,
|
||||
F24 = 313,
|
||||
F25 = 314,
|
||||
KP_0 = 320,
|
||||
KP_1 = 321,
|
||||
KP_2 = 322,
|
||||
KP_3 = 323,
|
||||
KP_4 = 324,
|
||||
KP_5 = 325,
|
||||
KP_6 = 326,
|
||||
KP_7 = 327,
|
||||
KP_8 = 328,
|
||||
KP_9 = 329,
|
||||
KP_DECIMAL = 330,
|
||||
KP_DIVIDE = 331,
|
||||
KP_MULTIPLY = 332,
|
||||
KP_SUBTRACT = 333,
|
||||
KP_ADD = 334,
|
||||
KP_ENTER = 335,
|
||||
KP_EQUAL = 336,
|
||||
LEFT_SHIFT = 340,
|
||||
LEFT_CONTROL = 341,
|
||||
LEFT_ALT = 342,
|
||||
LEFT_SUPER = 343,
|
||||
RIGHT_SHIFT = 344,
|
||||
RIGHT_CONTROL = 345,
|
||||
RIGHT_ALT = 346,
|
||||
RIGHT_SUPER = 347,
|
||||
MENU = 348,
|
||||
|
||||
INV_SLASH = 0xDC,
|
||||
BRA = 0xDB,
|
||||
KET = 0xDD,
|
||||
TILDA = 0xC0,
|
||||
DOUBLE_DOT = 0xBA,
|
||||
QUOTES = 0xDE,
|
||||
|
||||
MOUSE1 = 501,
|
||||
MOUSE2 = 502,
|
||||
MOUSE3 = 503,
|
||||
MOUSE4 = 504,
|
||||
MOUSE5 = 505,
|
||||
MOUSE_UP = 506,
|
||||
MOUSE_DOWN = 507,
|
||||
};
|
||||
|
||||
|
||||
enum class Keystate {
|
||||
PRESSED,
|
||||
RELEASED,
|
||||
HOLD,
|
||||
REPEAT,
|
||||
NONE,
|
||||
};
|
||||
|
||||
struct KeyEvent {
|
||||
Keycode code;
|
||||
enum class EventState {
|
||||
RELEASED = 0,
|
||||
PRESSED = 1,
|
||||
REPEAT = 2,
|
||||
} event_state;
|
||||
};
|
||||
};
|
||||
36
.outdated/graphics/inc/shader.h
Normal file
36
.outdated/graphics/inc/shader.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
namespace tp {
|
||||
namespace glw {
|
||||
class shader {
|
||||
|
||||
uint4 programm;
|
||||
uint4 VertexShaderID;
|
||||
uint4 FragmentShaderID;
|
||||
uint4 GeometryShaderID;
|
||||
|
||||
public:
|
||||
|
||||
bool compile_shader(const char* ShaderCode, uint4 ShaderID);
|
||||
void load(const char* vert, const char* geom, const char* frag, bool paths);
|
||||
|
||||
shader();
|
||||
|
||||
void vert_bind_source(const char* vert_src);
|
||||
void frag_bind_source(const char* frag_src);
|
||||
void geom_bind_source(const char* geom_src);
|
||||
|
||||
void compile();
|
||||
|
||||
shader(const char* vertid, const char* geomid, const char* fragid, bool paths = true);
|
||||
void bind();
|
||||
uint4 getu(const char* uid);
|
||||
void unbind();
|
||||
~shader();
|
||||
|
||||
alni sizeAllocatedMem();
|
||||
alni sizeUsedMem();
|
||||
};
|
||||
};
|
||||
};
|
||||
71
.outdated/graphics/inc/simplegui.h
Normal file
71
.outdated/graphics/inc/simplegui.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#pragma once
|
||||
|
||||
#include "window.h"
|
||||
#include "canvas.h"
|
||||
#include "animations.h"
|
||||
|
||||
namespace tp {
|
||||
namespace glw {
|
||||
|
||||
class WindowSimpleInputs {
|
||||
enum class Mouse : uint1 { NONE, PRESSED, HOLD, RELEASED } mMouse;
|
||||
enum class Move : uint1 { NONE, LEFT, RIGHT, UP, DOWN } mMove;
|
||||
public:
|
||||
|
||||
halnf mScaleVal = 0;
|
||||
vec2f mWindowSizeMM;
|
||||
vec2f mCrs;
|
||||
vec2f mCrsPrev;
|
||||
vec2f mCrsmDelta;
|
||||
halnf mPressure = 0.f;
|
||||
|
||||
void update(const glw::Window& window, halnf uiscale);
|
||||
bool Activated();
|
||||
bool Anticipating();
|
||||
bool Selected();
|
||||
bool MoveLeft();
|
||||
bool MoveRight();
|
||||
bool MoveUp();
|
||||
bool MoveDown();
|
||||
bool Drag();
|
||||
};
|
||||
|
||||
struct ButtonWidget {
|
||||
rectf mRect = { 0.f, 10.f };
|
||||
rgba mCol = { 0.3f, 0.3f, 0.3f, 1.f };
|
||||
bool mPressed = false;
|
||||
AnimRect mAnimRec;
|
||||
void draw(glw::Canvas& canvas);
|
||||
void proc(glw::WindowSimpleInputs& inputs);
|
||||
};
|
||||
|
||||
struct CheckBoxWidget {
|
||||
rectf mRect = { 0.f, 10.f };
|
||||
rgba mCol = { 0.3f, 0.3f, 0.3f, 1.f };
|
||||
rgba mColActive = { 0.5f, 0.5f, 0.5f, 1.f };
|
||||
|
||||
bool mValue = false;
|
||||
AnimRect mAnimRec;
|
||||
AnimColor mAnimCol;
|
||||
|
||||
void draw(glw::Canvas& canvas);
|
||||
void proc(glw::WindowSimpleInputs& inputs);
|
||||
};
|
||||
|
||||
struct WindowsHeaderWidget {
|
||||
rectf header_rec = { 10, 10, 50, 10 };
|
||||
rgba col = { 0.13f, 0.13f, 0.13f, 0.9f };
|
||||
rectf grab_rec = 0.f;
|
||||
|
||||
ButtonWidget mExitButton;
|
||||
ButtonWidget mMaxButton;
|
||||
ButtonWidget mMinButton;
|
||||
CheckBoxWidget mPinButton;
|
||||
|
||||
void updRecs();
|
||||
void draw(glw::Canvas& canvas);
|
||||
void proc(glw::Window& window, glw::WindowSimpleInputs& inputs);
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
31
.outdated/graphics/inc/texture.h
Normal file
31
.outdated/graphics/inc/texture.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "array2d.h"
|
||||
#include "color.h"
|
||||
#include "vec.h"
|
||||
|
||||
namespace tp {
|
||||
namespace glw {
|
||||
class texture {
|
||||
uint4 id;
|
||||
public:
|
||||
|
||||
texture();
|
||||
~texture();
|
||||
|
||||
uint4 getid();
|
||||
void update(const Array2D<rgba>& buff);
|
||||
void draw(const uint4& out = 0);
|
||||
|
||||
alni sizeAllocatedMem();
|
||||
alni sizeUsedMem();
|
||||
|
||||
static void init();
|
||||
static void deinit();
|
||||
static void draw_texture(uint4 out, uint4 in);
|
||||
static uint4 get_tex(const char* TexId);
|
||||
static void drawCurcle(vec2f pos, double radius, rgba col);
|
||||
};
|
||||
};
|
||||
};
|
||||
114
.outdated/graphics/inc/window.h
Normal file
114
.outdated/graphics/inc/window.h
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "vec.h"
|
||||
#include "rect.h"
|
||||
#include "color.h"
|
||||
#include "stringt.h"
|
||||
#include "array.h"
|
||||
#include "map.h"
|
||||
|
||||
#include "keycodes.h"
|
||||
#include "queue.h"
|
||||
|
||||
namespace tp {
|
||||
|
||||
extern tp::ModuleManifest gModuleGlw;
|
||||
|
||||
namespace glw {
|
||||
|
||||
struct PlatformContext;
|
||||
|
||||
class Window {
|
||||
|
||||
public:
|
||||
|
||||
struct Device {
|
||||
time_ms FrameRate = NULL; // monitor fps
|
||||
vec2f Size; // size of the monitor
|
||||
tp::halnf mDPMM = 1;
|
||||
};
|
||||
|
||||
struct Events {
|
||||
tp::Queue<KeyEvent> mKeysQueue;
|
||||
tp::uhalni mRedraw = 2;
|
||||
bool mClose = false;
|
||||
|
||||
vec2f mCursor = 0;
|
||||
halnf mPressure = 1.f;
|
||||
|
||||
vec2f mCursorPrev = 0.f;
|
||||
halnf mPressurePrev = 1.f;
|
||||
};
|
||||
|
||||
struct Appearence {
|
||||
vec2f mPos = { 100.f, 100.f }; // global position
|
||||
vec2f mSize = { 300.f, 300.f }; // width and height of window
|
||||
vec2f mSizeMin = { 100.f, 100.f }; // min size possiable
|
||||
vec2f mSizeMax = { 700.f, 700.f }; // max size possiable
|
||||
|
||||
bool mHiden = true;
|
||||
bool mMaximized = false;
|
||||
bool mMinimized = false;
|
||||
bool mTopZ = false;
|
||||
bool mAllDesktops = false;
|
||||
|
||||
rgba mResizeColor = rgba(0.13f, 0.13f, 0.13f, 0.9f);
|
||||
|
||||
rectf mMinMaxBox;
|
||||
|
||||
tp::Array<rectf> mCaptionsAddArea;
|
||||
tp::Array<rectf> mCaptionsRemoveArea;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
PlatformContext* mPlatformCtx = NULL;
|
||||
void platformCallback();
|
||||
void* platform_window() const;
|
||||
|
||||
struct NativeEventListenerCallback {
|
||||
typedef void (call_back_func)(PlatformContext* ctx, void* cd);
|
||||
call_back_func* exec_begin = NULL;
|
||||
call_back_func* exec = NULL;
|
||||
call_back_func* exec_end = NULL;
|
||||
void* cd = NULL;
|
||||
};
|
||||
|
||||
tp::HashMap<NativeEventListenerCallback, string> mNativeEventListeners;
|
||||
|
||||
private:
|
||||
|
||||
struct Cache {
|
||||
Appearence mAppearencePrev;
|
||||
vec2f mWindowSize = 0;
|
||||
rectf mRectBeforResizing = 0;
|
||||
bool mUserResizing = false;
|
||||
bool mMinMaxHover = false;
|
||||
bool mMouseTracked = false;
|
||||
} mCache;
|
||||
|
||||
void applyAppearance();
|
||||
void initialize();
|
||||
|
||||
public:
|
||||
|
||||
static Device mDevice;
|
||||
Appearence mAppearence;
|
||||
Events mEvents;
|
||||
|
||||
Window();
|
||||
Window(const Appearence& aAppearence);
|
||||
|
||||
void pollEvents();
|
||||
void beginDraw();
|
||||
void endDraw();
|
||||
|
||||
alni sizeAllocatedMem();
|
||||
alni sizeUsedMem();
|
||||
|
||||
~Window();
|
||||
};
|
||||
};
|
||||
};
|
||||
25
.outdated/graphics/src/android_api.h
Normal file
25
.outdated/graphics/src/android_api.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "queue.h"
|
||||
|
||||
struct AndroidApi {
|
||||
|
||||
union Event {
|
||||
|
||||
enum Type : tp::uint1 {
|
||||
EV_NONE = 0,
|
||||
} type = EV_NONE;
|
||||
|
||||
struct None {
|
||||
|
||||
} none;
|
||||
|
||||
|
||||
};
|
||||
|
||||
tp::Queue<Event> events;
|
||||
|
||||
};
|
||||
|
||||
extern AndroidApi* gAndroidApi;
|
||||
804
.outdated/graphics/src/android_main.cpp
Normal file
804
.outdated/graphics/src/android_main.cpp
Normal file
|
|
@ -0,0 +1,804 @@
|
|||
|
||||
// Copyright (C) 2010 The Android Open Source Project
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// own headers
|
||||
#include "window.h"
|
||||
|
||||
#include "GraphicsLibApi.h"
|
||||
|
||||
// STL
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <stdlib.h>
|
||||
|
||||
// jni
|
||||
//#include <initializer_list>
|
||||
//#include <memory>
|
||||
//#include <cstdlib>
|
||||
//#include <cstring>
|
||||
#include <jni.h>
|
||||
//#include <cerrno>
|
||||
//#include <cassert>
|
||||
|
||||
// opengl
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES3/gl32.h>
|
||||
//#include "GL/glew.h"
|
||||
|
||||
// glue
|
||||
#include <android/sensor.h>
|
||||
#include <android/log.h>
|
||||
#include <android/input.h>
|
||||
#include <../../../android/native_app_glue/android_native_app_glue.h>
|
||||
|
||||
// AcquireASensorManagerInstance
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
|
||||
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
|
||||
|
||||
// application side entry point
|
||||
int main();
|
||||
|
||||
// first function to be called in "main thread"
|
||||
void* main_wrap(void* p);
|
||||
|
||||
// AcquireASensorManagerInstance(void)
|
||||
// Workaround ASensorManager_getInstance() deprecation false alarm
|
||||
// for Android-N and before, when compiling with NDK-r15
|
||||
ASensorManager* AcquireASensorManagerInstance(android_app* app) {
|
||||
|
||||
if (!app)
|
||||
return nullptr;
|
||||
|
||||
typedef ASensorManager* (*PF_GETINSTANCEFORPACKAGE)(const char* name);
|
||||
void* androidHandle = dlopen("libandroid.so", RTLD_NOW);
|
||||
auto getInstanceForPackageFunc = (PF_GETINSTANCEFORPACKAGE)
|
||||
dlsym(androidHandle, "ASensorManager_getInstanceForPackage");
|
||||
if (getInstanceForPackageFunc) {
|
||||
JNIEnv* env = nullptr;
|
||||
app->activity->vm->AttachCurrentThread(&env, nullptr);
|
||||
|
||||
jclass android_content_Context = env->GetObjectClass(app->activity->clazz);
|
||||
jmethodID midGetPackageName = env->GetMethodID(android_content_Context,
|
||||
"getPackageName",
|
||||
"()Ljava/lang/String;");
|
||||
auto packageName = (jstring)env->CallObjectMethod(app->activity->clazz,
|
||||
midGetPackageName);
|
||||
|
||||
const char* nativePackageName = env->GetStringUTFChars(packageName, nullptr);
|
||||
ASensorManager* mgr = getInstanceForPackageFunc(nativePackageName);
|
||||
env->ReleaseStringUTFChars(packageName, nativePackageName);
|
||||
app->activity->vm->DetachCurrentThread();
|
||||
if (mgr) {
|
||||
dlclose(androidHandle);
|
||||
return mgr;
|
||||
}
|
||||
}
|
||||
|
||||
typedef ASensorManager* (*PF_GETINSTANCE)();
|
||||
auto getInstanceFunc = (PF_GETINSTANCE)
|
||||
dlsym(androidHandle, "ASensorManager_getInstance");
|
||||
// by all means at this point, ASensorManager_getInstance should be available
|
||||
assert(getInstanceFunc);
|
||||
dlclose(androidHandle);
|
||||
|
||||
return getInstanceFunc();
|
||||
}
|
||||
|
||||
void GL_APIENTRY MessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) {
|
||||
DBG_BREAK(true);
|
||||
LOGW("GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), type, severity, message);
|
||||
}
|
||||
|
||||
char const* gl_error_string(GLenum const err) {
|
||||
switch (err) {
|
||||
case GL_NO_ERROR: return "GL_NO_ERROR";
|
||||
case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
|
||||
case GL_INVALID_VALUE: return "GL_INVALID_VALUE";
|
||||
case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
|
||||
case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW";
|
||||
case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW";
|
||||
case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
|
||||
case GL_INVALID_FRAMEBUFFER_OPERATION: return "GL_INVALID_FRAMEBUFFER_OPERATION";
|
||||
default: return "unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
void glerr(GLenum type) {
|
||||
DBG_BREAK(true);
|
||||
const GLchar* message = gl_error_string(type);
|
||||
LOGW("GL CALLBACK: %s type = 0x%x, message = %s\n", (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), type, message);
|
||||
}
|
||||
|
||||
void glerr(GLenum type);
|
||||
#define AssertGL(x) { x; GLenum __gle = glGetError(); if (__gle != GL_NO_ERROR) glerr(__gle); }
|
||||
|
||||
// --------------------------------- Data --------------------------------------- //
|
||||
|
||||
struct MutexEvent {
|
||||
pthread_mutex_t mutex;
|
||||
tp::glw::Window* active_windw;
|
||||
bool parent_thread_has_events = false;
|
||||
bool child_whaiting = false;
|
||||
} mutex_event;
|
||||
|
||||
struct ANativeActivityCtx* android_ctx = NULL;
|
||||
|
||||
tp::glw::Window::Device tp::glw::Window::mDevice;
|
||||
extern const char* g_android_internal_data_path;
|
||||
|
||||
static pthread_t worker_thread;
|
||||
static pthread_mutex_t worker_finished_mutex;
|
||||
static pthread_cond_t worker_finished_cond;
|
||||
static bool worker_finished = false;
|
||||
|
||||
namespace tp {
|
||||
namespace glw {
|
||||
struct PlatformContext {
|
||||
|
||||
int col = 255;
|
||||
|
||||
EGLint w, h, format;
|
||||
EGLint numConfigs;
|
||||
EGLConfig config = nullptr;
|
||||
EGLSurface surface;
|
||||
EGLContext context;
|
||||
EGLDisplay display = nullptr;
|
||||
|
||||
AInputEvent* chache_event = NULL;
|
||||
|
||||
EGLint majorVersion, minorVersion;
|
||||
|
||||
// Initialize an EGL context for the current display.
|
||||
PlatformContext(ANativeWindow* window) {
|
||||
|
||||
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (EGL_NO_DISPLAY == display) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (eglInitialize(display, &majorVersion, &minorVersion) != EGL_TRUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Here specify the attributes of the desired configuration.
|
||||
// Below, we select an EGLConfig with at least 8 bits per color component compatible with on-screen windows
|
||||
const EGLint attribs[] = {
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, // request OpenGL ES 3.0
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_DEPTH_SIZE, GLW_CONTEXT_DEPTH_BITS,
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
// Here, the application chooses the configuration it desires.
|
||||
// find the best match if possible, otherwise use the very first one
|
||||
{
|
||||
if (eglChooseConfig(display, attribs, nullptr, 0, &numConfigs) != EGL_TRUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<EGLConfig[]> supportedConfigs(new EGLConfig[numConfigs]);
|
||||
assert(supportedConfigs);
|
||||
|
||||
if (eglChooseConfig(display, attribs, supportedConfigs.get(), numConfigs, &numConfigs) != EGL_TRUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(numConfigs);
|
||||
auto i = 0;
|
||||
for (; i < numConfigs; i++) {
|
||||
auto& cfg = supportedConfigs[i];
|
||||
EGLint r, g, b, d;
|
||||
if (eglGetConfigAttrib(display, cfg, EGL_RED_SIZE, &r) &&
|
||||
eglGetConfigAttrib(display, cfg, EGL_GREEN_SIZE, &g) &&
|
||||
eglGetConfigAttrib(display, cfg, EGL_BLUE_SIZE, &b) &&
|
||||
eglGetConfigAttrib(display, cfg, EGL_DEPTH_SIZE, &d) &&
|
||||
r == 8 && g == 8 && b == 8 && d == GLW_CONTEXT_DEPTH_BITS) {
|
||||
|
||||
config = supportedConfigs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == numConfigs) {
|
||||
config = supportedConfigs[0];
|
||||
}
|
||||
|
||||
if (config == nullptr) {
|
||||
LOGW("Unable to initialize EGLConfig");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const EGLint egl_context_attributes[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 3,
|
||||
//EGL_CONTEXT_MAJOR_VERSION, 3,
|
||||
//EGL_CONTEXT_MINOR_VERSION, 0,
|
||||
EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
|
||||
#ifdef ENV_BUILD_DEBUG
|
||||
//EGL_CONTEXT_OPENGL_DEBUG, EGL_TRUE,
|
||||
#endif
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
// EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
|
||||
// guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
|
||||
// As soon as we picked a EGLConfig, we can safely reconfigure the
|
||||
// ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID
|
||||
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
|
||||
surface = eglCreateWindowSurface(display, config, window, nullptr);
|
||||
context = eglCreateContext(display, config, EGL_NO_CONTEXT, egl_context_attributes);
|
||||
|
||||
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
|
||||
LOGW("Unable to eglMakeCurrent");
|
||||
return;
|
||||
}
|
||||
|
||||
eglQuerySurface(display, surface, EGL_WIDTH, &w);
|
||||
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
|
||||
|
||||
// Check openGL on the system
|
||||
auto opengl_info = { GL_VENDOR, GL_RENDERER, GL_VERSION, GL_EXTENSIONS };
|
||||
for (auto name : opengl_info) {
|
||||
auto info = glGetString(name);
|
||||
LOGI("OpenGL Info: %s", info);
|
||||
}
|
||||
|
||||
// Initialize GL state.
|
||||
//glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
|
||||
AssertGL(glEnable(GL_CULL_FACE));
|
||||
//AssertGL(glShadeModel(GL_SMOOTH));
|
||||
AssertGL(glEnable(GL_DEPTH_TEST));
|
||||
AssertGL(glDepthFunc(GL_LESS));
|
||||
|
||||
GLint major = 0;
|
||||
GLint minor = 0;
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &major);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &minor);
|
||||
|
||||
glGetIntegerv(GL_DEPTH, &minor);
|
||||
|
||||
AssertGL(glEnable(GL_DEBUG_OUTPUT));
|
||||
AssertGL(glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS));
|
||||
AssertGL(glDebugMessageCallback(MessageCallback, 0));
|
||||
|
||||
tp::glw::Window::mDevice.Size = { w, h };
|
||||
tp::glw::Window::mDevice.FrameRate = 60;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void beginDraw() {
|
||||
if (this->display == nullptr) { return; }
|
||||
|
||||
glViewport(0, 0, tp::glw::Window::mDevice.Size.x, tp::glw::Window::mDevice.Size.y);
|
||||
|
||||
//glClearColor(col / 255.f, col / 255.f, col / 255.f, 1);
|
||||
//glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
//if (col++ > 255) {
|
||||
//col = 0;
|
||||
//}
|
||||
}
|
||||
|
||||
void endDraw() {
|
||||
eglSwapBuffers(display, surface);
|
||||
}
|
||||
|
||||
// Tear down the EGL context currently associated with the display.
|
||||
~PlatformContext() {
|
||||
if (this->display != EGL_NO_DISPLAY) {
|
||||
eglMakeCurrent(this->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
if (this->context != EGL_NO_CONTEXT) {
|
||||
eglDestroyContext(this->display, this->context);
|
||||
}
|
||||
if (this->surface != EGL_NO_SURFACE) {
|
||||
eglDestroySurface(this->display, this->surface);
|
||||
}
|
||||
eglTerminate(this->display);
|
||||
}
|
||||
|
||||
display = EGL_NO_DISPLAY;
|
||||
context = EGL_NO_CONTEXT;
|
||||
surface = EGL_NO_SURFACE;
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// ---------------------------------- Parent Thread ------------------------------------ //
|
||||
#ifndef PARENT_THREAD
|
||||
|
||||
// Shared state for our app.
|
||||
struct ANativeActivityCtx {
|
||||
|
||||
// Our saved state data.
|
||||
struct saved_state {
|
||||
float angle;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
};
|
||||
|
||||
android_app* app;
|
||||
|
||||
ASensorManager* sensorManager;
|
||||
const ASensor* accelerometerSensor;
|
||||
ASensorEventQueue* sensorEventQueue;
|
||||
|
||||
int animating;
|
||||
EGLDisplay display;
|
||||
EGLSurface surface;
|
||||
EGLContext context;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
saved_state state;
|
||||
|
||||
ANativeActivityCtx(android_app* state) {
|
||||
memset(this, 0, sizeof(*this));
|
||||
|
||||
state->userData = this;
|
||||
state->onAppCmd = engine_handle_cmd;
|
||||
state->onInputEvent = engine_handle_input;
|
||||
|
||||
app = state;
|
||||
|
||||
// Prepare to monitor accelerometer
|
||||
sensorManager = AcquireASensorManagerInstance(state);
|
||||
accelerometerSensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_ACCELEROMETER);
|
||||
sensorEventQueue = ASensorManager_createEventQueue(sensorManager, state->looper, LOOPER_ID_USER, 0, 0);
|
||||
|
||||
// We are starting with a previous saved state; restore from it.
|
||||
if (state->savedState != nullptr) {
|
||||
this->state = *(saved_state*)state->savedState;
|
||||
}
|
||||
}
|
||||
|
||||
void proc_events_util() {
|
||||
int ident;
|
||||
int events;
|
||||
struct android_poll_source* source;
|
||||
|
||||
auto window = mutex_event.active_windw;
|
||||
|
||||
if (window) {
|
||||
for (auto proc : window->mNativeEventListeners) {
|
||||
proc->val.exec_begin(window->mPlatformCtx, proc->val.cd);
|
||||
}
|
||||
}
|
||||
|
||||
// we loop until all events are read
|
||||
while ((ident = ALooper_pollAll(0, nullptr, &events, (void**)&source)) >= 0) {
|
||||
|
||||
// Process this event.
|
||||
if (source != nullptr) {
|
||||
source->process(this->app, source);
|
||||
}
|
||||
|
||||
// If a sensor has data, process it now.
|
||||
if (ident == LOOPER_ID_USER) {
|
||||
if (this->accelerometerSensor != nullptr) {
|
||||
ASensorEvent event;
|
||||
while (ASensorEventQueue_getEvents(this->sensorEventQueue, &event, 1) > 0) {
|
||||
LOGI("accelerometer: x=%f y=%f z=%f", event.acceleration.x, event.acceleration.y, event.acceleration.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we are exiting.
|
||||
if (this->app->destroyRequested != 0) {
|
||||
DBG_BREAK(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (window) {
|
||||
for (auto proc : window->mNativeEventListeners) {
|
||||
proc->val.exec_end(window->mPlatformCtx, proc->val.cd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void proc_events() {
|
||||
|
||||
pthread_mutex_lock(&mutex_event.mutex);
|
||||
auto threaded = mutex_event.active_windw;
|
||||
pthread_mutex_unlock(&mutex_event.mutex);
|
||||
|
||||
if (!threaded) {
|
||||
proc_events_util();
|
||||
return;
|
||||
}
|
||||
|
||||
// Read all pending events.
|
||||
int ident;
|
||||
int events;
|
||||
struct android_poll_source* source;
|
||||
|
||||
// check if events exist and if so prepare to proccess them
|
||||
if ((ident = ALooper_pollAll(0, nullptr, &events, (void**)&source)) >= 0) {
|
||||
|
||||
// signal child thread that we need to process those events
|
||||
pthread_mutex_lock(&mutex_event.mutex);
|
||||
mutex_event.parent_thread_has_events = true;
|
||||
pthread_mutex_unlock(&mutex_event.mutex);
|
||||
|
||||
// whait until child thread pauses
|
||||
bool whait = true;
|
||||
|
||||
while (whait) {
|
||||
pthread_mutex_lock(&mutex_event.mutex);
|
||||
whait = !mutex_event.child_whaiting;
|
||||
pthread_mutex_unlock(&mutex_event.mutex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
pthread_mutex_lock(&mutex_event.mutex);
|
||||
auto window = mutex_event.active_windw;
|
||||
pthread_mutex_unlock(&mutex_event.mutex);
|
||||
|
||||
proc_events_util();
|
||||
|
||||
// signal to child continue to do its work
|
||||
pthread_mutex_lock(&mutex_event.mutex);
|
||||
mutex_event.parent_thread_has_events = false;
|
||||
pthread_mutex_unlock(&mutex_event.mutex);
|
||||
}
|
||||
|
||||
// Process the next input event.
|
||||
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
|
||||
auto* engine = (struct ANativeActivityCtx*)app->userData;
|
||||
auto window = mutex_event.active_windw;
|
||||
|
||||
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
|
||||
window->mEvents.mCursorPrev = window->mEvents.mCursor;
|
||||
|
||||
window->mEvents.mCursor.x = AMotionEvent_getX(event, 0);
|
||||
window->mEvents.mCursor.y = AMotionEvent_getY(event, 0);
|
||||
|
||||
window->mEvents.mRedraw = 2;
|
||||
|
||||
int32_t event_action = AMotionEvent_getAction(event);
|
||||
int32_t event_pointer_index = (event_action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
||||
event_action &= AMOTION_EVENT_ACTION_MASK;
|
||||
|
||||
if ((AMotionEvent_getToolType(event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_FINGER)
|
||||
|| (AMotionEvent_getToolType(event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_UNKNOWN)) {
|
||||
|
||||
if (event_action == AMOTION_EVENT_ACTION_DOWN) {
|
||||
window->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode::MOUSE1, tp::KeyEvent::EventState::PRESSED });
|
||||
}
|
||||
else if (event_action == AMOTION_EVENT_ACTION_UP) {
|
||||
window->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode::MOUSE1, tp::KeyEvent::EventState::RELEASED });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (window) {
|
||||
window->mPlatformCtx->chache_event = event;
|
||||
for (auto proc : window->mNativeEventListeners) {
|
||||
proc->val.exec(window->mPlatformCtx, proc->val.cd);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Process the next main command.
|
||||
static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
|
||||
auto* engine = (struct ANativeActivityCtx*)app->userData;
|
||||
auto window = mutex_event.active_windw;
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
// The system has asked us to save our current state. Do so.
|
||||
case APP_CMD_SAVE_STATE: {
|
||||
engine->app->savedState = malloc(sizeof(ANativeActivityCtx::saved_state));
|
||||
*((ANativeActivityCtx::saved_state*)engine->app->savedState) = engine->state;
|
||||
engine->app->savedStateSize = sizeof(ANativeActivityCtx::saved_state);
|
||||
} break;
|
||||
|
||||
// The window is being shown, get it ready.
|
||||
case APP_CMD_INIT_WINDOW: {
|
||||
if (engine->app->window != nullptr) {
|
||||
//engine->init_display();
|
||||
//engine->draw_frame();
|
||||
}
|
||||
} break;
|
||||
|
||||
// The window is being hidden or closed, clean it up.
|
||||
case APP_CMD_TERM_WINDOW: {
|
||||
//engine->term_display();
|
||||
} break;
|
||||
|
||||
// When our app gains focus, we start monitoring the accelerometer.
|
||||
case APP_CMD_GAINED_FOCUS: {
|
||||
if (engine->accelerometerSensor != nullptr) {
|
||||
ASensorEventQueue_enableSensor(engine->sensorEventQueue,
|
||||
engine->accelerometerSensor);
|
||||
// We'd like to get 60 events per second (in us).
|
||||
ASensorEventQueue_setEventRate(engine->sensorEventQueue,
|
||||
engine->accelerometerSensor,
|
||||
(1000L / 60) * 1000);
|
||||
}
|
||||
} break;
|
||||
|
||||
// When our app loses focus, we stop monitoring the accelerometer.
|
||||
// This is to avoid consuming battery while not being used.
|
||||
case APP_CMD_LOST_FOCUS: {
|
||||
if (engine->accelerometerSensor != nullptr) {
|
||||
ASensorEventQueue_disableSensor(engine->sensorEventQueue,
|
||||
engine->accelerometerSensor);
|
||||
}
|
||||
// Also stop animating.
|
||||
engine->animating = 0;
|
||||
//engine->draw_frame();
|
||||
} break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
void unsure_dir_exist(const char* path_to_file) {
|
||||
char* temp_path = strdup(path_to_file);
|
||||
|
||||
for (char* p = temp_path + 1; *p; p++) {
|
||||
if (*p == '/') {
|
||||
*p = '\0';
|
||||
int status = mkdir(temp_path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
if (status != 0 && errno != EEXIST) {
|
||||
// handle error
|
||||
break;
|
||||
}
|
||||
*p = '/';
|
||||
}
|
||||
}
|
||||
|
||||
free(temp_path);
|
||||
}
|
||||
|
||||
// FIXME
|
||||
void unpackAsset(AAssetManager* mgr, const char* filename, const std::string& path) {
|
||||
AAsset* asset = AAssetManager_open(mgr, filename, AASSET_MODE_STREAMING);
|
||||
if (asset == NULL) {
|
||||
return;
|
||||
}
|
||||
off_t length = AAsset_getLength(asset);
|
||||
char* buffer = new char[length];
|
||||
AAsset_read(asset, buffer, length);
|
||||
|
||||
unsure_dir_exist(path.c_str());
|
||||
FILE* out = fopen(path.c_str(), "w");
|
||||
if (out != NULL) {
|
||||
fwrite(buffer, length, 1, out);
|
||||
fclose(out);
|
||||
}
|
||||
delete[] buffer;
|
||||
AAsset_close(asset);
|
||||
}
|
||||
|
||||
// FIXME
|
||||
void unpackDirectory(AAssetManager* mgr, const char* dirname, const std::string& path) {
|
||||
|
||||
AAssetDir* assetDir = AAssetManager_openDir(mgr, dirname);
|
||||
const char* filename = NULL;
|
||||
|
||||
while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) {
|
||||
std::string assetPath = std::string(dirname) + "/" + filename;
|
||||
std::string internalPath = path + "/" + std::string(dirname) + "/" + filename;
|
||||
|
||||
struct stat sb;
|
||||
stat(assetPath.c_str(), &sb);
|
||||
if (S_ISDIR(sb.st_mode)) {
|
||||
unpackDirectory(mgr, assetPath.c_str(), internalPath);
|
||||
}
|
||||
else {
|
||||
unpackAsset(mgr, assetPath.c_str(), internalPath);
|
||||
}
|
||||
}
|
||||
AAssetDir_close(assetDir);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
// This is the main entry point of a native application that is using
|
||||
// android_native_app_glue. It runs in its own thread, with its own
|
||||
// event loop for receiving input events and doing other things.
|
||||
void android_main(android_app* state) {
|
||||
|
||||
tp::print_env_info();
|
||||
tp::alloc_init();
|
||||
|
||||
ANativeActivityCtx engine(state);
|
||||
|
||||
unpackDirectory(state->activity->assetManager, "", state->activity->internalDataPath);
|
||||
unpackDirectory(state->activity->assetManager, "rsc", state->activity->internalDataPath);
|
||||
unpackDirectory(state->activity->assetManager, "rsc/fonts", state->activity->internalDataPath);
|
||||
|
||||
android_ctx = &engine;
|
||||
|
||||
bool running = true;
|
||||
while (running) {
|
||||
|
||||
engine.proc_events();
|
||||
|
||||
// whait until our app fully initialized
|
||||
if (!engine.app->window) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// run once
|
||||
static bool main_thread_started = false;
|
||||
if (!main_thread_started) {
|
||||
|
||||
// init types
|
||||
g_android_internal_data_path = state->activity->internalDataPath;
|
||||
|
||||
// create main thread
|
||||
pthread_create(&worker_thread, NULL, main_wrap, NULL);
|
||||
pthread_mutex_init(&worker_finished_mutex, NULL);
|
||||
pthread_cond_init(&worker_finished_cond, NULL);
|
||||
|
||||
main_thread_started = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// check for exit
|
||||
pthread_mutex_lock(&worker_finished_mutex);
|
||||
running = !worker_finished;
|
||||
pthread_mutex_unlock(&worker_finished_mutex);
|
||||
}
|
||||
|
||||
pthread_join(worker_thread, NULL);
|
||||
|
||||
tp::alloc_uninit();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------- Child thread --------------------------------------- //
|
||||
#ifndef CHILD_THREAD
|
||||
|
||||
//#include <android/configuration.h>
|
||||
//#include <android/native_activity.h>
|
||||
|
||||
AInputEvent* androidPlatformContextGetEvent(tp::glw::PlatformContext* ctx) {
|
||||
return ctx->chache_event;
|
||||
}
|
||||
|
||||
int32_t getDensityDpi(android_app* app) {
|
||||
AConfiguration* config = AConfiguration_new();
|
||||
AConfiguration_fromAssetManager(config, app->activity->assetManager);
|
||||
int32_t density = AConfiguration_getDensity(config);
|
||||
AConfiguration_delete(config);
|
||||
return density;
|
||||
}
|
||||
|
||||
// statics
|
||||
void tp::glw::Window::init() {}
|
||||
void tp::glw::Window::deinit() {}
|
||||
|
||||
void tp::glw::Window::initialize() {
|
||||
mPlatformCtx = new PlatformContext(android_ctx->app->window);
|
||||
applyAppearance();
|
||||
|
||||
|
||||
AConfiguration* config = AConfiguration_new();
|
||||
AConfiguration_fromAssetManager(config, android_ctx->app->activity->assetManager);
|
||||
int32_t density = AConfiguration_getDensity(config);
|
||||
AConfiguration_delete(config);
|
||||
|
||||
mDevice.mDPMM = density / 25.4f;
|
||||
}
|
||||
|
||||
tp::glw::Window::Window() {
|
||||
initialize();
|
||||
|
||||
pthread_mutex_lock(&mutex_event.mutex);
|
||||
mutex_event.active_windw = this;
|
||||
pthread_mutex_unlock(&mutex_event.mutex);
|
||||
}
|
||||
|
||||
tp::glw::Window::Window(const Appearence& aAppearence) {
|
||||
mAppearence = aAppearence;
|
||||
initialize();
|
||||
}
|
||||
|
||||
tp::glw::Window::~Window() {
|
||||
delete mPlatformCtx;
|
||||
}
|
||||
|
||||
void tp::glw::Window::applyAppearance() {
|
||||
int width = ANativeWindow_getWidth(android_ctx->app->window);
|
||||
int height = ANativeWindow_getHeight(android_ctx->app->window);
|
||||
|
||||
if (width != mAppearence.mSize.x || height != mAppearence.mSize.y) {
|
||||
mEvents.mRedraw = 2;
|
||||
}
|
||||
|
||||
mAppearence.mPos = mCache.mAppearencePrev.mPos = 0;
|
||||
mAppearence.mSize.x = mCache.mAppearencePrev.mSize.x = tp::glw::Window::mDevice.Size.x = width;
|
||||
mAppearence.mSize.y = mCache.mAppearencePrev.mSize.y = tp::glw::Window::mDevice.Size.y = height;
|
||||
}
|
||||
|
||||
void tp::glw::Window::pollEvents() {
|
||||
applyAppearance();
|
||||
|
||||
// check if parent thread has some events to pass
|
||||
|
||||
pthread_mutex_lock(&mutex_event.mutex);
|
||||
bool has_event = mutex_event.parent_thread_has_events;
|
||||
mutex_event.child_whaiting = has_event;
|
||||
pthread_mutex_unlock(&mutex_event.mutex);
|
||||
|
||||
while (has_event) {
|
||||
pthread_mutex_lock(&mutex_event.mutex);
|
||||
has_event = mutex_event.parent_thread_has_events;
|
||||
pthread_mutex_unlock(&mutex_event.mutex);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mutex_event.mutex);
|
||||
mutex_event.child_whaiting = false;
|
||||
pthread_mutex_unlock(&mutex_event.mutex);
|
||||
}
|
||||
|
||||
void tp::glw::Window::platformCallback() {}
|
||||
|
||||
void tp::glw::Window::beginDraw() {
|
||||
mPlatformCtx->beginDraw();
|
||||
}
|
||||
|
||||
void tp::glw::Window::endDraw() {
|
||||
mPlatformCtx->endDraw();
|
||||
if (mEvents.mRedraw-- < 0) mEvents.mRedraw = 0;
|
||||
}
|
||||
|
||||
void* tp::glw::Window::platform_window() const { return android_ctx->app->window; }
|
||||
|
||||
tp::alni tp::glw::Window::sizeAllocatedMem() { return 0; }
|
||||
|
||||
tp::alni tp::glw::Window::sizeUsedMem() { return 0; }
|
||||
|
||||
|
||||
void* main_wrap(void* p) {
|
||||
|
||||
// exec main
|
||||
main();
|
||||
|
||||
// mark as doen after completion
|
||||
pthread_mutex_lock(&worker_finished_mutex);
|
||||
worker_finished = true;
|
||||
pthread_cond_signal(&worker_finished_cond);
|
||||
pthread_mutex_unlock(&worker_finished_mutex);
|
||||
|
||||
// exit "main thread"
|
||||
pthread_exit(NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
453
.outdated/graphics/src/android_native_app_glue.c
Normal file
453
.outdated/graphics/src/android_native_app_glue.c
Normal file
|
|
@ -0,0 +1,453 @@
|
|||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "android_native_app_glue.h"
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__))
|
||||
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__))
|
||||
|
||||
/* For debug builds, always enable the debug traces in this library */
|
||||
#ifndef NDEBUG
|
||||
# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__))
|
||||
#else
|
||||
# define LOGV(...) ((void)0)
|
||||
#endif
|
||||
|
||||
void free_saved_state(struct android_app* android_app) {
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
if (android_app->savedState != NULL) {
|
||||
free(android_app->savedState);
|
||||
android_app->savedState = NULL;
|
||||
android_app->savedStateSize = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
}
|
||||
|
||||
int8_t android_app_read_cmd(struct android_app* android_app) {
|
||||
int8_t cmd;
|
||||
if (read(android_app->msgread, &cmd, sizeof(cmd)) != sizeof(cmd)) {
|
||||
LOGE("No data on command pipe!");
|
||||
return -1;
|
||||
}
|
||||
if (cmd == APP_CMD_SAVE_STATE) free_saved_state(android_app);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void print_cur_config(struct android_app* android_app) {
|
||||
char lang[2], country[2];
|
||||
AConfiguration_getLanguage(android_app->config, lang);
|
||||
AConfiguration_getCountry(android_app->config, country);
|
||||
|
||||
LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d "
|
||||
"keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d "
|
||||
"modetype=%d modenight=%d",
|
||||
AConfiguration_getMcc(android_app->config),
|
||||
AConfiguration_getMnc(android_app->config),
|
||||
lang[0], lang[1], country[0], country[1],
|
||||
AConfiguration_getOrientation(android_app->config),
|
||||
AConfiguration_getTouchscreen(android_app->config),
|
||||
AConfiguration_getDensity(android_app->config),
|
||||
AConfiguration_getKeyboard(android_app->config),
|
||||
AConfiguration_getNavigation(android_app->config),
|
||||
AConfiguration_getKeysHidden(android_app->config),
|
||||
AConfiguration_getNavHidden(android_app->config),
|
||||
AConfiguration_getSdkVersion(android_app->config),
|
||||
AConfiguration_getScreenSize(android_app->config),
|
||||
AConfiguration_getScreenLong(android_app->config),
|
||||
AConfiguration_getUiModeType(android_app->config),
|
||||
AConfiguration_getUiModeNight(android_app->config));
|
||||
}
|
||||
|
||||
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) {
|
||||
switch (cmd) {
|
||||
case APP_CMD_INPUT_CHANGED:
|
||||
LOGV("APP_CMD_INPUT_CHANGED");
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
if (android_app->inputQueue != NULL) {
|
||||
AInputQueue_detachLooper(android_app->inputQueue);
|
||||
}
|
||||
android_app->inputQueue = android_app->pendingInputQueue;
|
||||
if (android_app->inputQueue != NULL) {
|
||||
LOGV("Attaching input queue to looper");
|
||||
AInputQueue_attachLooper(android_app->inputQueue,
|
||||
android_app->looper, LOOPER_ID_INPUT, NULL,
|
||||
&android_app->inputPollSource);
|
||||
}
|
||||
pthread_cond_broadcast(&android_app->cond);
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
break;
|
||||
|
||||
case APP_CMD_INIT_WINDOW:
|
||||
LOGV("APP_CMD_INIT_WINDOW");
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app->window = android_app->pendingWindow;
|
||||
pthread_cond_broadcast(&android_app->cond);
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
break;
|
||||
|
||||
case APP_CMD_TERM_WINDOW:
|
||||
LOGV("APP_CMD_TERM_WINDOW");
|
||||
pthread_cond_broadcast(&android_app->cond);
|
||||
break;
|
||||
|
||||
case APP_CMD_RESUME:
|
||||
case APP_CMD_START:
|
||||
case APP_CMD_PAUSE:
|
||||
case APP_CMD_STOP:
|
||||
LOGV("activityState=%d", cmd);
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app->activityState = cmd;
|
||||
pthread_cond_broadcast(&android_app->cond);
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
break;
|
||||
|
||||
case APP_CMD_CONFIG_CHANGED:
|
||||
LOGV("APP_CMD_CONFIG_CHANGED");
|
||||
AConfiguration_fromAssetManager(android_app->config,
|
||||
android_app->activity->assetManager);
|
||||
print_cur_config(android_app);
|
||||
break;
|
||||
|
||||
case APP_CMD_DESTROY:
|
||||
LOGV("APP_CMD_DESTROY");
|
||||
android_app->destroyRequested = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) {
|
||||
switch (cmd) {
|
||||
case APP_CMD_TERM_WINDOW:
|
||||
LOGV("APP_CMD_TERM_WINDOW");
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app->window = NULL;
|
||||
pthread_cond_broadcast(&android_app->cond);
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
break;
|
||||
|
||||
case APP_CMD_SAVE_STATE:
|
||||
LOGV("APP_CMD_SAVE_STATE");
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app->stateSaved = 1;
|
||||
pthread_cond_broadcast(&android_app->cond);
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
break;
|
||||
|
||||
case APP_CMD_RESUME:
|
||||
free_saved_state(android_app);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void android_app_destroy(struct android_app* android_app) {
|
||||
LOGV("android_app_destroy!");
|
||||
free_saved_state(android_app);
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
if (android_app->inputQueue != NULL) {
|
||||
AInputQueue_detachLooper(android_app->inputQueue);
|
||||
}
|
||||
AConfiguration_delete(android_app->config);
|
||||
android_app->destroyed = 1;
|
||||
pthread_cond_broadcast(&android_app->cond);
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
// Can't touch android_app object after this.
|
||||
}
|
||||
|
||||
void process_input(struct android_app* app, struct android_poll_source* source) {
|
||||
AInputEvent* event = NULL;
|
||||
while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
|
||||
LOGV("New input event: type=%d", AInputEvent_getType(event));
|
||||
if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {
|
||||
continue;
|
||||
}
|
||||
int32_t handled = 0;
|
||||
if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
|
||||
AInputQueue_finishEvent(app->inputQueue, event, handled);
|
||||
}
|
||||
}
|
||||
|
||||
void process_cmd(struct android_app* app, struct android_poll_source* source) {
|
||||
int8_t cmd = android_app_read_cmd(app);
|
||||
android_app_pre_exec_cmd(app, cmd);
|
||||
if (app->onAppCmd != NULL) app->onAppCmd(app, cmd);
|
||||
android_app_post_exec_cmd(app, cmd);
|
||||
}
|
||||
|
||||
void* android_app_entry(void* param) {
|
||||
struct android_app* android_app = (struct android_app*)param;
|
||||
|
||||
android_app->config = AConfiguration_new();
|
||||
AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager);
|
||||
|
||||
print_cur_config(android_app);
|
||||
|
||||
android_app->cmdPollSource.id = LOOPER_ID_MAIN;
|
||||
android_app->cmdPollSource.app = android_app;
|
||||
android_app->cmdPollSource.process = process_cmd;
|
||||
android_app->inputPollSource.id = LOOPER_ID_INPUT;
|
||||
android_app->inputPollSource.app = android_app;
|
||||
android_app->inputPollSource.process = process_input;
|
||||
|
||||
ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
|
||||
ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL,
|
||||
&android_app->cmdPollSource);
|
||||
android_app->looper = looper;
|
||||
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app->running = 1;
|
||||
pthread_cond_broadcast(&android_app->cond);
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
|
||||
android_main(android_app);
|
||||
|
||||
android_app_destroy(android_app);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Native activity interaction (called from main thread)
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
struct android_app* android_app_create(ANativeActivity* activity,
|
||||
void* savedState, size_t savedStateSize) {
|
||||
struct android_app* android_app = calloc(1, sizeof(struct android_app));
|
||||
android_app->activity = activity;
|
||||
|
||||
pthread_mutex_init(&android_app->mutex, NULL);
|
||||
pthread_cond_init(&android_app->cond, NULL);
|
||||
|
||||
if (savedState != NULL) {
|
||||
android_app->savedState = malloc(savedStateSize);
|
||||
android_app->savedStateSize = savedStateSize;
|
||||
memcpy(android_app->savedState, savedState, savedStateSize);
|
||||
}
|
||||
|
||||
int msgpipe[2];
|
||||
if (pipe(msgpipe)) {
|
||||
LOGE("could not create pipe: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
android_app->msgread = msgpipe[0];
|
||||
android_app->msgwrite = msgpipe[1];
|
||||
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
pthread_create(&android_app->thread, &attr, android_app_entry, android_app);
|
||||
|
||||
// Wait for thread to start.
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
while (!android_app->running) {
|
||||
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
|
||||
return android_app;
|
||||
}
|
||||
|
||||
void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
|
||||
if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {
|
||||
LOGE("Failure writing android_app cmd: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) {
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app->pendingInputQueue = inputQueue;
|
||||
android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);
|
||||
while (android_app->inputQueue != android_app->pendingInputQueue) {
|
||||
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
}
|
||||
|
||||
void android_app_set_window(struct android_app* android_app, ANativeWindow* window) {
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
if (android_app->pendingWindow != NULL) {
|
||||
android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW);
|
||||
}
|
||||
android_app->pendingWindow = window;
|
||||
if (window != NULL) {
|
||||
android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW);
|
||||
}
|
||||
while (android_app->window != android_app->pendingWindow) {
|
||||
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
}
|
||||
|
||||
void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) {
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app_write_cmd(android_app, cmd);
|
||||
while (android_app->activityState != cmd) {
|
||||
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
}
|
||||
|
||||
void android_app_free(struct android_app* android_app) {
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app_write_cmd(android_app, APP_CMD_DESTROY);
|
||||
while (!android_app->destroyed) {
|
||||
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
|
||||
close(android_app->msgread);
|
||||
close(android_app->msgwrite);
|
||||
pthread_cond_destroy(&android_app->cond);
|
||||
pthread_mutex_destroy(&android_app->mutex);
|
||||
free(android_app);
|
||||
}
|
||||
|
||||
struct android_app* ToApp(ANativeActivity* activity) {
|
||||
return (struct android_app*) activity->instance;
|
||||
}
|
||||
|
||||
void onDestroy(ANativeActivity* activity) {
|
||||
LOGV("Destroy: %p", activity);
|
||||
android_app_free(ToApp(activity));
|
||||
}
|
||||
|
||||
void onStart(ANativeActivity* activity) {
|
||||
LOGV("Start: %p", activity);
|
||||
android_app_set_activity_state(ToApp(activity), APP_CMD_START);
|
||||
}
|
||||
|
||||
void onResume(ANativeActivity* activity) {
|
||||
LOGV("Resume: %p", activity);
|
||||
android_app_set_activity_state(ToApp(activity), APP_CMD_RESUME);
|
||||
}
|
||||
|
||||
void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {
|
||||
LOGV("SaveInstanceState: %p", activity);
|
||||
|
||||
struct android_app* android_app = ToApp(activity);
|
||||
void* savedState = NULL;
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app->stateSaved = 0;
|
||||
android_app_write_cmd(android_app, APP_CMD_SAVE_STATE);
|
||||
while (!android_app->stateSaved) {
|
||||
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||
}
|
||||
|
||||
if (android_app->savedState != NULL) {
|
||||
savedState = android_app->savedState;
|
||||
*outLen = android_app->savedStateSize;
|
||||
android_app->savedState = NULL;
|
||||
android_app->savedStateSize = 0;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
|
||||
return savedState;
|
||||
}
|
||||
|
||||
void onPause(ANativeActivity* activity) {
|
||||
LOGV("Pause: %p", activity);
|
||||
android_app_set_activity_state(ToApp(activity), APP_CMD_PAUSE);
|
||||
}
|
||||
|
||||
void onStop(ANativeActivity* activity) {
|
||||
LOGV("Stop: %p", activity);
|
||||
android_app_set_activity_state(ToApp(activity), APP_CMD_STOP);
|
||||
}
|
||||
|
||||
void onConfigurationChanged(ANativeActivity* activity) {
|
||||
LOGV("ConfigurationChanged: %p", activity);
|
||||
android_app_write_cmd(ToApp(activity), APP_CMD_CONFIG_CHANGED);
|
||||
}
|
||||
|
||||
void onContentRectChanged(ANativeActivity* activity, const ARect* r) {
|
||||
LOGV("ContentRectChanged: l=%d,t=%d,r=%d,b=%d", r->left, r->top, r->right, r->bottom);
|
||||
struct android_app* android_app = ToApp(activity);
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app->contentRect = *r;
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
android_app_write_cmd(ToApp(activity), APP_CMD_CONTENT_RECT_CHANGED);
|
||||
}
|
||||
|
||||
void onLowMemory(ANativeActivity* activity) {
|
||||
LOGV("LowMemory: %p", activity);
|
||||
android_app_write_cmd(ToApp(activity), APP_CMD_LOW_MEMORY);
|
||||
}
|
||||
|
||||
void onWindowFocusChanged(ANativeActivity* activity, int focused) {
|
||||
LOGV("WindowFocusChanged: %p -- %d", activity, focused);
|
||||
android_app_write_cmd(ToApp(activity), focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
|
||||
}
|
||||
|
||||
void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
|
||||
LOGV("NativeWindowCreated: %p -- %p", activity, window);
|
||||
android_app_set_window(ToApp(activity), window);
|
||||
}
|
||||
|
||||
void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
|
||||
LOGV("NativeWindowDestroyed: %p -- %p", activity, window);
|
||||
android_app_set_window(ToApp(activity), NULL);
|
||||
}
|
||||
|
||||
void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* window) {
|
||||
LOGV("NativeWindowRedrawNeeded: %p -- %p", activity, window);
|
||||
android_app_write_cmd(ToApp(activity), APP_CMD_WINDOW_REDRAW_NEEDED);
|
||||
}
|
||||
|
||||
void onNativeWindowResized(ANativeActivity* activity, ANativeWindow* window) {
|
||||
LOGV("NativeWindowResized: %p -- %p", activity, window);
|
||||
android_app_write_cmd(ToApp(activity), APP_CMD_WINDOW_RESIZED);
|
||||
}
|
||||
|
||||
void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
|
||||
LOGV("InputQueueCreated: %p -- %p", activity, queue);
|
||||
android_app_set_input(ToApp(activity), queue);
|
||||
}
|
||||
|
||||
void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
|
||||
LOGV("InputQueueDestroyed: %p -- %p", activity, queue);
|
||||
android_app_set_input(ToApp(activity), NULL);
|
||||
}
|
||||
|
||||
void ILOVEU_ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize) {
|
||||
LOGV("Creating: %p", activity);
|
||||
|
||||
activity->callbacks->onConfigurationChanged = onConfigurationChanged;
|
||||
activity->callbacks->onContentRectChanged = onContentRectChanged;
|
||||
activity->callbacks->onDestroy = onDestroy;
|
||||
activity->callbacks->onInputQueueCreated = onInputQueueCreated;
|
||||
activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
|
||||
activity->callbacks->onLowMemory = onLowMemory;
|
||||
activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
|
||||
activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
|
||||
activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded;
|
||||
activity->callbacks->onNativeWindowResized = onNativeWindowResized;
|
||||
activity->callbacks->onPause = onPause;
|
||||
activity->callbacks->onResume = onResume;
|
||||
activity->callbacks->onSaveInstanceState = onSaveInstanceState;
|
||||
activity->callbacks->onStart = onStart;
|
||||
activity->callbacks->onStop = onStop;
|
||||
activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
|
||||
|
||||
activity->instance = android_app_create(activity, savedState, savedStateSize);
|
||||
}
|
||||
350
.outdated/graphics/src/android_native_app_glue.h
Normal file
350
.outdated/graphics/src/android_native_app_glue.h
Normal file
|
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
|
||||
#include <android/configuration.h>
|
||||
#include <android/looper.h>
|
||||
#include <android/native_activity.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The native activity interface provided by <android/native_activity.h>
|
||||
* is based on a set of application-provided callbacks that will be called
|
||||
* by the Activity's main thread when certain events occur.
|
||||
*
|
||||
* This means that each one of this callbacks _should_ _not_ block, or they
|
||||
* risk having the system force-close the application. This programming
|
||||
* model is direct, lightweight, but constraining.
|
||||
*
|
||||
* The 'android_native_app_glue' static library is used to provide a different
|
||||
* execution model where the application can implement its own main event
|
||||
* loop in a different thread instead. Here's how it works:
|
||||
*
|
||||
* 1/ The application must provide a function named "android_main()" that
|
||||
* will be called when the activity is created, in a new thread that is
|
||||
* distinct from the activity's main thread.
|
||||
*
|
||||
* 2/ android_main() receives a pointer to a valid "android_app" structure
|
||||
* that contains references to other important objects, e.g. the
|
||||
* ANativeActivity obejct instance the application is running in.
|
||||
*
|
||||
* 3/ the "android_app" object holds an ALooper instance that already
|
||||
* listens to two important things:
|
||||
*
|
||||
* - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX
|
||||
* declarations below.
|
||||
*
|
||||
* - input events coming from the AInputQueue attached to the activity.
|
||||
*
|
||||
* Each of these correspond to an ALooper identifier returned by
|
||||
* ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT,
|
||||
* respectively.
|
||||
*
|
||||
* Your application can use the same ALooper to listen to additional
|
||||
* file-descriptors. They can either be callback based, or with return
|
||||
* identifiers starting with LOOPER_ID_USER.
|
||||
*
|
||||
* 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event,
|
||||
* the returned data will point to an android_poll_source structure. You
|
||||
* can call the process() function on it, and fill in android_app->onAppCmd
|
||||
* and android_app->onInputEvent to be called for your own processing
|
||||
* of the event.
|
||||
*
|
||||
* Alternatively, you can call the low-level functions to read and process
|
||||
* the data directly... look at the process_cmd() and process_input()
|
||||
* implementations in the glue to see how to do this.
|
||||
*
|
||||
* See the sample named "native-activity" that comes with the NDK with a
|
||||
* full usage example. Also look at the JavaDoc of NativeActivity.
|
||||
*/
|
||||
|
||||
struct android_app;
|
||||
|
||||
/**
|
||||
* Data associated with an ALooper fd that will be returned as the "outData"
|
||||
* when that source has data ready.
|
||||
*/
|
||||
struct android_poll_source {
|
||||
// The identifier of this source. May be LOOPER_ID_MAIN or
|
||||
// LOOPER_ID_INPUT.
|
||||
int32_t id;
|
||||
|
||||
// The android_app this ident is associated with.
|
||||
struct android_app* app;
|
||||
|
||||
// Function to call to perform the standard processing of data from
|
||||
// this source.
|
||||
void (*process)(struct android_app* app, struct android_poll_source* source);
|
||||
};
|
||||
|
||||
/**
|
||||
* This is the interface for the standard glue code of a threaded
|
||||
* application. In this model, the application's code is running
|
||||
* in its own thread separate from the main thread of the process.
|
||||
* It is not required that this thread be associated with the Java
|
||||
* VM, although it will need to be in order to make JNI calls any
|
||||
* Java objects.
|
||||
*/
|
||||
struct android_app {
|
||||
// The application can place a pointer to its own state object
|
||||
// here if it likes.
|
||||
void* userData;
|
||||
|
||||
// Fill this in with the function to process main app commands (APP_CMD_*)
|
||||
void (*onAppCmd)(struct android_app* app, int32_t cmd);
|
||||
|
||||
// Fill this in with the function to process input events. At this point
|
||||
// the event has already been pre-dispatched, and it will be finished upon
|
||||
// return. Return 1 if you have handled the event, 0 for any default
|
||||
// dispatching.
|
||||
int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
|
||||
|
||||
// The ANativeActivity object instance that this app is running in.
|
||||
ANativeActivity* activity;
|
||||
|
||||
// The current configuration the app is running in.
|
||||
AConfiguration* config;
|
||||
|
||||
// This is the last instance's saved state, as provided at creation time.
|
||||
// It is NULL if there was no state. You can use this as you need; the
|
||||
// memory will remain around until you call android_app_exec_cmd() for
|
||||
// APP_CMD_RESUME, at which point it will be freed and savedState set to NULL.
|
||||
// These variables should only be changed when processing a APP_CMD_SAVE_STATE,
|
||||
// at which point they will be initialized to NULL and you can malloc your
|
||||
// state and place the information here. In that case the memory will be
|
||||
// freed for you later.
|
||||
void* savedState;
|
||||
size_t savedStateSize;
|
||||
|
||||
// The ALooper associated with the app's thread.
|
||||
ALooper* looper;
|
||||
|
||||
// When non-NULL, this is the input queue from which the app will
|
||||
// receive user input events.
|
||||
AInputQueue* inputQueue;
|
||||
|
||||
// When non-NULL, this is the window surface that the app can draw in.
|
||||
ANativeWindow* window;
|
||||
|
||||
// Current content rectangle of the window; this is the area where the
|
||||
// window's content should be placed to be seen by the user.
|
||||
ARect contentRect;
|
||||
|
||||
// Current state of the app's activity. May be either APP_CMD_START,
|
||||
// APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
|
||||
int activityState;
|
||||
|
||||
// This is non-zero when the application's NativeActivity is being
|
||||
// destroyed and waiting for the app thread to complete.
|
||||
int destroyRequested;
|
||||
|
||||
// -------------------------------------------------
|
||||
// Below are "private" implementation of the glue code.
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
|
||||
int msgread;
|
||||
int msgwrite;
|
||||
|
||||
pthread_t thread;
|
||||
|
||||
struct android_poll_source cmdPollSource;
|
||||
struct android_poll_source inputPollSource;
|
||||
|
||||
int running;
|
||||
int stateSaved;
|
||||
int destroyed;
|
||||
int redrawNeeded;
|
||||
AInputQueue* pendingInputQueue;
|
||||
ANativeWindow* pendingWindow;
|
||||
ARect pendingContentRect;
|
||||
};
|
||||
|
||||
enum {
|
||||
/**
|
||||
* Looper data ID of commands coming from the app's main thread, which
|
||||
* is returned as an identifier from ALooper_pollOnce(). The data for this
|
||||
* identifier is a pointer to an android_poll_source structure.
|
||||
* These can be retrieved and processed with android_app_read_cmd()
|
||||
* and android_app_exec_cmd().
|
||||
*/
|
||||
LOOPER_ID_MAIN = 1,
|
||||
|
||||
/**
|
||||
* Looper data ID of events coming from the AInputQueue of the
|
||||
* application's window, which is returned as an identifier from
|
||||
* ALooper_pollOnce(). The data for this identifier is a pointer to an
|
||||
* android_poll_source structure. These can be read via the inputQueue
|
||||
* object of android_app.
|
||||
*/
|
||||
LOOPER_ID_INPUT = 2,
|
||||
|
||||
/**
|
||||
* Start of user-defined ALooper identifiers.
|
||||
*/
|
||||
LOOPER_ID_USER = 3,
|
||||
};
|
||||
|
||||
enum {
|
||||
/**
|
||||
* Command from main thread: the AInputQueue has changed. Upon processing
|
||||
* this command, android_app->inputQueue will be updated to the new queue
|
||||
* (or NULL).
|
||||
*/
|
||||
APP_CMD_INPUT_CHANGED,
|
||||
|
||||
/**
|
||||
* Command from main thread: a new ANativeWindow is ready for use. Upon
|
||||
* receiving this command, android_app->window will contain the new window
|
||||
* surface.
|
||||
*/
|
||||
APP_CMD_INIT_WINDOW,
|
||||
|
||||
/**
|
||||
* Command from main thread: the existing ANativeWindow needs to be
|
||||
* terminated. Upon receiving this command, android_app->window still
|
||||
* contains the existing window; after calling android_app_exec_cmd
|
||||
* it will be set to NULL.
|
||||
*/
|
||||
APP_CMD_TERM_WINDOW,
|
||||
|
||||
/**
|
||||
* Command from main thread: the current ANativeWindow has been resized.
|
||||
* Please redraw with its new size.
|
||||
*/
|
||||
APP_CMD_WINDOW_RESIZED,
|
||||
|
||||
/**
|
||||
* Command from main thread: the system needs that the current ANativeWindow
|
||||
* be redrawn. You should redraw the window before handing this to
|
||||
* android_app_exec_cmd() in order to avoid transient drawing glitches.
|
||||
*/
|
||||
APP_CMD_WINDOW_REDRAW_NEEDED,
|
||||
|
||||
/**
|
||||
* Command from main thread: the content area of the window has changed,
|
||||
* such as from the soft input window being shown or hidden. You can
|
||||
* find the new content rect in android_app::contentRect.
|
||||
*/
|
||||
APP_CMD_CONTENT_RECT_CHANGED,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity window has gained
|
||||
* input focus.
|
||||
*/
|
||||
APP_CMD_GAINED_FOCUS,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity window has lost
|
||||
* input focus.
|
||||
*/
|
||||
APP_CMD_LOST_FOCUS,
|
||||
|
||||
/**
|
||||
* Command from main thread: the current device configuration has changed.
|
||||
*/
|
||||
APP_CMD_CONFIG_CHANGED,
|
||||
|
||||
/**
|
||||
* Command from main thread: the system is running low on memory.
|
||||
* Try to reduce your memory use.
|
||||
*/
|
||||
APP_CMD_LOW_MEMORY,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity has been started.
|
||||
*/
|
||||
APP_CMD_START,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity has been resumed.
|
||||
*/
|
||||
APP_CMD_RESUME,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app should generate a new saved state
|
||||
* for itself, to restore from later if needed. If you have saved state,
|
||||
* allocate it with malloc and place it in android_app.savedState with
|
||||
* the size in android_app.savedStateSize. The will be freed for you
|
||||
* later.
|
||||
*/
|
||||
APP_CMD_SAVE_STATE,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity has been paused.
|
||||
*/
|
||||
APP_CMD_PAUSE,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity has been stopped.
|
||||
*/
|
||||
APP_CMD_STOP,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity is being destroyed,
|
||||
* and waiting for the app thread to clean up and exit before proceeding.
|
||||
*/
|
||||
APP_CMD_DESTROY,
|
||||
};
|
||||
|
||||
/**
|
||||
* Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next
|
||||
* app command message.
|
||||
*/
|
||||
int8_t android_app_read_cmd(struct android_app* android_app);
|
||||
|
||||
/**
|
||||
* Call with the command returned by android_app_read_cmd() to do the
|
||||
* initial pre-processing of the given command. You can perform your own
|
||||
* actions for the command after calling this function.
|
||||
*/
|
||||
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd);
|
||||
|
||||
/**
|
||||
* Call with the command returned by android_app_read_cmd() to do the
|
||||
* final post-processing of the given command. You must have done your own
|
||||
* actions for the command before calling this function.
|
||||
*/
|
||||
void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd);
|
||||
|
||||
/**
|
||||
* No-op function that used to be used to prevent the linker from stripping app
|
||||
* glue code. No longer necessary, since __attribute__((visibility("default")))
|
||||
* does this for us.
|
||||
*/
|
||||
__attribute__((
|
||||
deprecated("Calls to app_dummy are no longer necessary. See "
|
||||
"https://github.com/android-ndk/ndk/issues/381."))) void
|
||||
app_dummy();
|
||||
|
||||
/**
|
||||
* This is the function that application code must implement, representing
|
||||
* the main entry to the app.
|
||||
*/
|
||||
extern void android_main(struct android_app* app);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
115
.outdated/graphics/src/animations.cpp
Normal file
115
.outdated/graphics/src/animations.cpp
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
|
||||
#include "animations.h"
|
||||
#include "timer.h"
|
||||
|
||||
using namespace tp;
|
||||
using namespace glw;
|
||||
|
||||
bool tp::glw::gInTransition = false;
|
||||
|
||||
halnf AnimValue::interpolate() const {
|
||||
if (!mTimeAnim) {
|
||||
return mVal;
|
||||
}
|
||||
|
||||
auto dt = gCurrentTime - mTimeStart;
|
||||
if (dt > mTimeAnim) dt = mTimeAnim;
|
||||
auto t = (halnf)dt / mTimeAnim;
|
||||
t = (halnf)(0.511 + atan((t - 0.36) * 28) / 2.9);
|
||||
t = clamp(t, 0.f, 1.f);
|
||||
auto out = mValPrev + (mVal - mValPrev) * t;
|
||||
return out;
|
||||
}
|
||||
|
||||
AnimValue::AnimValue() {}
|
||||
|
||||
void AnimValue::setAnimTime(halni time) {
|
||||
mTimeAnim = time;
|
||||
}
|
||||
|
||||
AnimValue::AnimValue(halnf val) {
|
||||
mVal = val;
|
||||
mValPrev = mVal;
|
||||
mTimeStart = gCurrentTime;
|
||||
}
|
||||
|
||||
bool AnimValue::inTransition() const {
|
||||
auto time_pased = gCurrentTime - mTimeStart >= mTimeAnim;
|
||||
return !time_pased;
|
||||
}
|
||||
|
||||
void AnimValue::set(halnf val) {
|
||||
if (!inTransition()) {
|
||||
mValPrev = mVal;
|
||||
}
|
||||
|
||||
if (val == mVal) {
|
||||
return;
|
||||
}
|
||||
|
||||
mValPrev = get();
|
||||
mVal = val;
|
||||
|
||||
if (!inTransition()) {
|
||||
mTimeStart = (halni)gCurrentTime;
|
||||
}
|
||||
}
|
||||
|
||||
halnf AnimValue::getTarget() const {
|
||||
return mVal;
|
||||
}
|
||||
|
||||
void AnimValue::setNoTransition(halnf val) {
|
||||
mValPrev = val;
|
||||
mVal = val;
|
||||
mTimeStart -= mTimeStart;
|
||||
}
|
||||
|
||||
halnf AnimValue::get() const {
|
||||
if (inTransition()) {
|
||||
gInTransition = true;
|
||||
}
|
||||
return interpolate();
|
||||
}
|
||||
|
||||
AnimValue::operator halnf() const {
|
||||
return get();
|
||||
}
|
||||
|
||||
rectf AnimRect::get() const {
|
||||
return { x.get(), y.get() , z.get(), w.get() };
|
||||
}
|
||||
|
||||
rectf AnimRect::getTarget() const {
|
||||
return { x.getTarget(), y.getTarget() , z.getTarget(), w.getTarget() };
|
||||
}
|
||||
|
||||
void AnimRect::setNoTransition(rectf rec) {
|
||||
x.setNoTransition(rec.x);
|
||||
y.setNoTransition(rec.y);
|
||||
z.setNoTransition(rec.z);
|
||||
w.setNoTransition(rec.w);
|
||||
}
|
||||
|
||||
void AnimRect::setAnimTime(const halni time) {
|
||||
x.setAnimTime(time);
|
||||
y.setAnimTime(time);
|
||||
z.setAnimTime(time);
|
||||
w.setAnimTime(time);
|
||||
}
|
||||
|
||||
void AnimRect::set(const rectf& in) {
|
||||
x.set(in.x);
|
||||
y.set(in.y);
|
||||
z.set(in.z);
|
||||
w.set(in.w);
|
||||
}
|
||||
|
||||
rgba AnimColor::get() const {
|
||||
auto col = mColor.get();
|
||||
return rgba(col.x, col.y, col.z, col.w);
|
||||
}
|
||||
|
||||
void AnimColor::set(const rgba& col) {
|
||||
mColor.set(rectf(col.r, col.g, col.b, col.a));
|
||||
}
|
||||
378
.outdated/graphics/src/canvas.cpp
Normal file
378
.outdated/graphics/src/canvas.cpp
Normal file
|
|
@ -0,0 +1,378 @@
|
|||
|
||||
#include "canvas.h"
|
||||
|
||||
#include "GraphicsLibApi.h"
|
||||
|
||||
#ifdef ENV_OS_ANDROID
|
||||
const char* get_android_abs_path(const char* path, bool second = false);
|
||||
#define NANOVG_GLES3_IMPLEMENTATION // Use GLES3 implementation.
|
||||
#else
|
||||
#define NANOVG_GL3_IMPLEMENTATION // Use GL3 implementation.
|
||||
#endif
|
||||
|
||||
#include "nanovg.h"
|
||||
#include "nanovg_gl.h"
|
||||
#include "nanovg_gl_utils.h"
|
||||
|
||||
using namespace tp;
|
||||
using namespace glw;
|
||||
|
||||
#define NVG ((NVGcontext*) mCtx)
|
||||
|
||||
static const char* getFontPath() {
|
||||
#ifdef ENV_OS_ANDROID
|
||||
return get_android_abs_path("rsc/fonts/CONSOLAB.TTF");
|
||||
#else
|
||||
return "./rsc/fonts/CONSOLAB.TTF";
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
Canvas::Canvas() {
|
||||
|
||||
// create context
|
||||
mCtx =
|
||||
#ifdef ENV_OS_ANDROID
|
||||
nvgCreateGLES3
|
||||
#else
|
||||
nvgCreateGL3
|
||||
#endif
|
||||
(NVG_ANTIALIAS | NVG_STENCIL_STROKES
|
||||
#ifdef ENV_BUILD_DEBUG
|
||||
| NVG_DEBUG
|
||||
#endif
|
||||
);
|
||||
|
||||
mColorPrimary = rgba(0.5f, 0.5f, 0.5f, 0.9f);
|
||||
mColorSecondary = rgba(0.2f, 0.2f, 0.2f, 0.9f);
|
||||
|
||||
nvgCreateFont(NVG, "basic", getFontPath());
|
||||
}
|
||||
|
||||
Canvas::Val& Canvas::convert2pxls(Val& val) {
|
||||
val = val * mDpmm * mUIScale;
|
||||
return val;
|
||||
}
|
||||
|
||||
Canvas::Val Canvas::as2pxls(Val val) {
|
||||
return val * mDpmm * mUIScale;
|
||||
}
|
||||
|
||||
Canvas::Rect& Canvas::convert2pxls(Rect& rec) {
|
||||
convert2pxls(rec.x);
|
||||
convert2pxls(rec.y);
|
||||
convert2pxls(rec.z);
|
||||
convert2pxls(rec.w);
|
||||
return rec;
|
||||
}
|
||||
|
||||
Canvas::Vec2& Canvas::convert2pxls(Vec2& vec) {
|
||||
convert2pxls(vec.x);
|
||||
convert2pxls(vec.y);
|
||||
return vec;
|
||||
}
|
||||
|
||||
void Canvas::beginDraw(Rect viewport, tp::halnf dpmm, tp::halnf uiscale) {
|
||||
convert2pxls(viewport);
|
||||
nvgBeginFrame(NVG, viewport.size.x, viewport.size.y, 1);
|
||||
|
||||
mVieport = { 0.f, 0.f, viewport.size.x, viewport.size.y };
|
||||
glViewport((GLsizei)mVieport.x, (GLsizei)mVieport.y, (GLsizei)mVieport.size.x, (GLsizei)mVieport.size.y);
|
||||
|
||||
mDpmm = dpmm;
|
||||
mUIScale = tp::clamp(uiscale, 0.03f, 100.f);
|
||||
|
||||
mClamping = mVieport;
|
||||
}
|
||||
|
||||
void Canvas::resetViewport() {
|
||||
glViewport((GLsizei)mVieport.x, (GLsizei)mVieport.y, (GLsizei)mVieport.size.x, (GLsizei)mVieport.size.y);
|
||||
}
|
||||
|
||||
void Canvas::clear(Col color) {
|
||||
glClearColor(color.r, color.g, color.b, color.a);
|
||||
//glClearDepth(0.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void Canvas::endDraw() {
|
||||
nvgEndFrame(NVG);
|
||||
}
|
||||
|
||||
void Canvas::setClamping(Rect rec) {
|
||||
mClamping = rec;
|
||||
convert2pxls(rec);
|
||||
nvgScissor(NVG, rec.x, rec.y, rec.z, rec.w);
|
||||
}
|
||||
|
||||
void Canvas::setCol1(const Col& col) {
|
||||
mColorPrimary = col;
|
||||
}
|
||||
|
||||
void Canvas::setCol2(const Col& col) {
|
||||
mColorSecondary = col;
|
||||
}
|
||||
|
||||
void Canvas::rect(Rect rec, halnf rounding, halnf borders) {
|
||||
convert2pxls(rec);
|
||||
convert2pxls(rounding);
|
||||
convert2pxls(borders);
|
||||
|
||||
if (borders) {
|
||||
nvgBeginPath(NVG);
|
||||
|
||||
auto borders_rec = rec;
|
||||
rec.pos += borders;
|
||||
rec.size -= borders * 2;
|
||||
|
||||
if (rounding) {
|
||||
nvgRoundedRect(NVG, borders_rec.x, borders_rec.y, borders_rec.z, borders_rec.w, rounding);
|
||||
}
|
||||
else {
|
||||
nvgRect(NVG, borders_rec.x, borders_rec.y, borders_rec.z, borders_rec.w);
|
||||
}
|
||||
|
||||
nvgFillColor(NVG, nvgRGBAf(mColorSecondary.r, mColorSecondary.g, mColorSecondary.b, mColorSecondary.a));
|
||||
nvgFill(NVG);
|
||||
}
|
||||
|
||||
nvgBeginPath(NVG);
|
||||
|
||||
if (rounding) {
|
||||
nvgRoundedRect(NVG, rec.x, rec.y, rec.z, rec.w, rounding);
|
||||
}
|
||||
else {
|
||||
nvgRect(NVG, rec.x, rec.y, rec.z, rec.w);
|
||||
}
|
||||
nvgFillColor(NVG, nvgRGBAf(mColorPrimary.r, mColorPrimary.g, mColorPrimary.b, mColorPrimary.a));
|
||||
nvgFill(NVG);
|
||||
}
|
||||
|
||||
void Canvas::line(Vec2 p1, Vec2 p2, halnf thikness) {
|
||||
convert2pxls(p1);
|
||||
convert2pxls(p2);
|
||||
convert2pxls(thikness);
|
||||
|
||||
nvgBeginPath(NVG);
|
||||
|
||||
nvgMoveTo(NVG, p1.x, p1.y);
|
||||
nvgLineTo(NVG, p2.x, p2.y);
|
||||
|
||||
nvgStrokeColor(NVG, nvgRGBAf(mColorPrimary.r, mColorPrimary.g, mColorPrimary.b, mColorPrimary.a));
|
||||
nvgStrokeWidth(NVG, thikness);
|
||||
nvgStroke(NVG);
|
||||
}
|
||||
|
||||
void Canvas::trig(Vec2 p1, Vec2 p2, Vec2 p3) {
|
||||
convert2pxls(p1);
|
||||
convert2pxls(p2);
|
||||
convert2pxls(p3);
|
||||
|
||||
nvgBeginPath(NVG);
|
||||
|
||||
nvgMoveTo(NVG, p1.x, p1.y);
|
||||
nvgLineTo(NVG, p2.x, p2.y);
|
||||
nvgLineTo(NVG, p3.x, p3.y);
|
||||
|
||||
nvgFillColor(NVG, nvgRGBAf(mColorPrimary.r, mColorPrimary.g, mColorPrimary.b, mColorPrimary.a));
|
||||
nvgFill(NVG);
|
||||
}
|
||||
|
||||
void Canvas::circle(Vec2 rec, halnf radius, halnf borders) {
|
||||
convert2pxls(rec);
|
||||
convert2pxls(radius);
|
||||
convert2pxls(borders);
|
||||
DBG_BREAK(1);
|
||||
}
|
||||
|
||||
void Canvas::text(const char* start, const char* end, Rect rec, halnf size, Align align) {
|
||||
convert2pxls(rec);
|
||||
convert2pxls(size);
|
||||
|
||||
nvgFillColor(NVG, nvgRGBAf(mColorPrimary.r, mColorPrimary.g, mColorPrimary.b, mColorPrimary.a));
|
||||
nvgFontSize(NVG, size);
|
||||
nvgTextAlign(NVG, NVGalign(align));
|
||||
auto y = (align & Align::MIDDLE) ? rec.y + rec.w / 2 : rec.y;
|
||||
auto x = (align & Align::CENTER) ? rec.x + rec.z / 2 : rec.x;
|
||||
nvgText(NVG, x, y, start, end);
|
||||
}
|
||||
|
||||
void Canvas::text(const string text, Rect rec, halnf size, Align align) {
|
||||
convert2pxls(rec);
|
||||
convert2pxls(size);
|
||||
|
||||
nvgFillColor(NVG, nvgRGBAf(mColorPrimary.r, mColorPrimary.g, mColorPrimary.b, mColorPrimary.a));
|
||||
nvgFontSize(NVG, size);
|
||||
nvgTextAlign(NVG, NVGalign(align));
|
||||
|
||||
//nvgTextBounds(NVG, );
|
||||
|
||||
auto t_mid = rec.y + rec.w / 2;
|
||||
auto t_top = rec.y;
|
||||
auto res = bool(align & Align::MIDDLE);
|
||||
auto y = res ? t_mid : t_top;
|
||||
|
||||
auto x_mid = rec.x + rec.z / 2;
|
||||
auto x_left = rec.x;
|
||||
res = bool(align & Align::CENTER);
|
||||
auto x = res ? x_mid : x_left;
|
||||
|
||||
nvgText(NVG, x, y, text.cstr(), text.cstr() + text.size());
|
||||
}
|
||||
|
||||
|
||||
void Canvas::ImageHandle::createFromBuff(glw::fbuffer* buff, Canvas* drawer) {
|
||||
this->~ImageHandle();
|
||||
auto const size = buff->getSize();
|
||||
|
||||
#ifdef ENV_OS_ANDROID
|
||||
mId = nvglCreateImageFromHandleGLES3((NVGcontext*)drawer->mCtx, buff->texId(), size.x, size.y, 0);
|
||||
#else
|
||||
mId = nvglCreateImageFromHandleGL3((NVGcontext*)drawer->mCtx, buff->texId(), (halni) size.x, (halni) size.y, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Canvas::ImageHandle::free(Canvas* drawer) {
|
||||
if (mId && (NVGcontext*)drawer->mCtx) {
|
||||
nvgDeleteImage((NVGcontext*)drawer->mCtx, mId);
|
||||
}
|
||||
}
|
||||
|
||||
Canvas::ImageHandle::~ImageHandle() {}
|
||||
|
||||
void Canvas::drawImage(Rect rec, ImageHandle* image, halnf angle, halnf alpha, halnf rounding) {
|
||||
convert2pxls(rec);
|
||||
convert2pxls(rounding);
|
||||
|
||||
|
||||
auto imgPaint = nvgImagePattern(NVG, rec.x, rec.y, rec.z, rec.w, angle, image->mId, alpha);
|
||||
nvgBeginPath(NVG);
|
||||
nvgRoundedRect(NVG, rec.x, rec.y, rec.z, rec.w, rounding);
|
||||
nvgFillPaint(NVG, imgPaint);
|
||||
nvgFill(NVG);
|
||||
}
|
||||
|
||||
void Canvas::drawColorwheel(Rect rec, const rgb& col) {
|
||||
convert2pxls(rec);
|
||||
|
||||
float const x = rec.x;
|
||||
float const y = rec.y;
|
||||
float const w = rec.z;
|
||||
float const h = rec.w;
|
||||
|
||||
hsv hsv = tp::hsv(col);
|
||||
float const hue = hsv.h / (NVG_PI * 2);
|
||||
|
||||
int i;
|
||||
float r0, r1, ax, ay, bx, by, cx, cy, aeps, r;
|
||||
NVGpaint paint;
|
||||
|
||||
nvgSave(NVG);
|
||||
|
||||
cx = x + w * 0.5f;
|
||||
cy = y + h * 0.5f;
|
||||
r1 = (w < h ? w : h) * 0.5f - as2pxls(1.0f);
|
||||
r0 = r1 - as2pxls(3.0f);
|
||||
aeps = 0.5f / r1; // half a pixel arc length in radians (2pi cancels out).
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
float a0 = (float)i / 6.0f * NVG_PI * 2.0f - aeps;
|
||||
float a1 = (float)(i + 1.0f) / 6.0f * NVG_PI * 2.0f + aeps;
|
||||
nvgBeginPath(NVG);
|
||||
nvgArc(NVG, cx, cy, r0, a0, a1, NVG_CW);
|
||||
nvgArc(NVG, cx, cy, r1, a1, a0, NVG_CCW);
|
||||
nvgClosePath(NVG);
|
||||
ax = cx + cosf(a0) * (r0 + r1) * 0.5f;
|
||||
ay = cy + sinf(a0) * (r0 + r1) * 0.5f;
|
||||
bx = cx + cosf(a1) * (r0 + r1) * 0.5f;
|
||||
by = cy + sinf(a1) * (r0 + r1) * 0.5f;
|
||||
paint = nvgLinearGradient(NVG, ax, ay, bx, by, nvgHSLA(a0 / (NVG_PI * 2), 1.0f, 0.55f, 255), nvgHSLA(a1 / (NVG_PI * 2), 1.0f, 0.55f, 255));
|
||||
nvgFillPaint(NVG, paint);
|
||||
nvgFill(NVG);
|
||||
}
|
||||
|
||||
nvgBeginPath(NVG);
|
||||
nvgCircle(NVG, cx, cy, r0 - 0.5f);
|
||||
nvgCircle(NVG, cx, cy, r1 + 0.5f);
|
||||
nvgStrokeColor(NVG, nvgRGBA(0, 0, 0, 64));
|
||||
nvgStrokeWidth(NVG, 1.0f);
|
||||
nvgStroke(NVG);
|
||||
|
||||
// Selector
|
||||
nvgSave(NVG);
|
||||
nvgTranslate(NVG, cx, cy);
|
||||
nvgRotate(NVG, hue * NVG_PI * 2);
|
||||
|
||||
// Marker on
|
||||
nvgStrokeWidth(NVG, 2.0f);
|
||||
nvgBeginPath(NVG);
|
||||
nvgRect(NVG, r0 - 1, -3, r1 - r0 + 2, 6);
|
||||
nvgStrokeColor(NVG, nvgRGBA(255, 255, 255, 192));
|
||||
nvgStroke(NVG);
|
||||
|
||||
paint = nvgBoxGradient(NVG, r0 - 3, -5, r1 - r0 + 6, 10, 2, 4, nvgRGBA(0, 0, 0, 128), nvgRGBA(0, 0, 0, 0));
|
||||
nvgBeginPath(NVG);
|
||||
nvgRect(NVG, r0 - 2 - 10, -4 - 10, r1 - r0 + 4 + 20, 8 + 20);
|
||||
nvgRect(NVG, r0 - 2, -4, r1 - r0 + 4, 8);
|
||||
nvgPathWinding(NVG, NVG_HOLE);
|
||||
nvgFillPaint(NVG, paint);
|
||||
nvgFill(NVG);
|
||||
|
||||
// Center triangle
|
||||
r = r0 - 6;
|
||||
ax = cosf(120.0f / 180.0f * NVG_PI) * r;
|
||||
ay = sinf(120.0f / 180.0f * NVG_PI) * r;
|
||||
bx = cosf(-120.0f / 180.0f * NVG_PI) * r;
|
||||
by = sinf(-120.0f / 180.0f * NVG_PI) * r;
|
||||
nvgBeginPath(NVG);
|
||||
nvgMoveTo(NVG, r, 0);
|
||||
nvgLineTo(NVG, ax, ay);
|
||||
nvgLineTo(NVG, bx, by);
|
||||
nvgClosePath(NVG);
|
||||
paint = nvgLinearGradient(NVG, r, 0, ax, ay, nvgHSLA(hue, 1.0f, 0.5f, 255), nvgRGBA(255, 255, 255, 255));
|
||||
nvgFillPaint(NVG, paint);
|
||||
nvgFill(NVG);
|
||||
paint = nvgLinearGradient(NVG, (r + ax) * 0.5f, (0 + ay) * 0.5f, bx, by, nvgRGBA(0, 0, 0, 0), nvgRGBA(0, 0, 0, 255));
|
||||
nvgFillPaint(NVG, paint);
|
||||
nvgFill(NVG);
|
||||
nvgStrokeColor(NVG, nvgRGBA(0, 0, 0, 64));
|
||||
nvgStroke(NVG);
|
||||
|
||||
// Select circle on triangle
|
||||
auto inner = as2pxls(3);
|
||||
//auto outter = as2pxls(5);
|
||||
|
||||
float yt = hsv.v * hsv.s;
|
||||
float xt = hsv.v - 0.5f * yt;
|
||||
ay = sinf(120.0f / 180.0f * NVG_PI) * r * (-1.0f + xt * 2.0f);
|
||||
ax = cosf(120.0f / 180.0f * NVG_PI) * r * (1.0f - yt * 3.f);
|
||||
nvgStrokeWidth(NVG, as2pxls(0.6f));
|
||||
nvgBeginPath(NVG);
|
||||
nvgCircle(NVG, ax, ay, inner);
|
||||
nvgStrokeColor(NVG, nvgRGBA(255, 255, 255, 192));
|
||||
nvgStroke(NVG);
|
||||
|
||||
//paint = nvgRadialGradient(NVG, ax, ay, 4, 9, nvgRGBA(0, 0, 0, 64), nvgRGBA(0, 0, 0, 0));
|
||||
//nvgBeginPath(NVG);
|
||||
//nvgRect(NVG, ax - outter, ay - outter, outter * 2, outter * 2);
|
||||
//nvgCircle(NVG, ax, ay, outter);
|
||||
//nvgPathWinding(NVG, NVG_HOLE);
|
||||
//nvgFillPaint(NVG, paint);
|
||||
//nvgFill(NVG);
|
||||
|
||||
nvgRestore(NVG);
|
||||
|
||||
nvgRestore(NVG);
|
||||
}
|
||||
|
||||
|
||||
Canvas::~Canvas() {
|
||||
if (NVG) {
|
||||
#ifdef ENV_OS_ANDROID
|
||||
nvgDeleteGLES3(NVG);
|
||||
#else
|
||||
nvgDeleteGL3(NVG);
|
||||
#endif
|
||||
}
|
||||
mCtx = NULL;
|
||||
}
|
||||
877
.outdated/graphics/src/debugui.cpp
Normal file
877
.outdated/graphics/src/debugui.cpp
Normal file
|
|
@ -0,0 +1,877 @@
|
|||
|
||||
#include "debugui.h"
|
||||
|
||||
#include "typelist.h"
|
||||
#include "stringt.h"
|
||||
#include "stack.h"
|
||||
#include "npple.h"
|
||||
#include "rect.h"
|
||||
#include "map.h"
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_internal.h"
|
||||
#include "implot.h"
|
||||
|
||||
// -------------- Platform Includes ---------------------- //
|
||||
|
||||
#if defined ENV_OS_WINDOWS
|
||||
#include "backends/imgui_impl_opengl3.h"
|
||||
#include "backends/imgui_impl_win32.h"
|
||||
#include <Windows.h>
|
||||
#elif defined ENV_OS_LINUX
|
||||
#include "backends/imgui_impl_opengl3.h"
|
||||
#include "backends/imgui_impl_glfw.h"
|
||||
#elif defined ENV_OS_ANDROID
|
||||
#include "backends/imgui_impl_opengl3.h"
|
||||
#include "backends/imgui_impl_android.h"
|
||||
#include <android/sensor.h>
|
||||
#include <android/log.h>
|
||||
#include <android/input.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
|
||||
#if defined ENV_OS_WINDOWS
|
||||
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
extern HWND windowsPlatformContextGetNativeWindow(tp::glw::PlatformContext* ctx);
|
||||
extern UINT windowsPlatformContextGetMessage(tp::glw::PlatformContext* ctx);
|
||||
extern WPARAM windowsPlatformContextGetWparam(tp::glw::PlatformContext* ctx);
|
||||
extern LRESULT windowsPlatformContextGetLparam(tp::glw::PlatformContext* ctx);
|
||||
|
||||
#elif defined ENV_OS_LINUX
|
||||
#elif defined ENV_OS_ANDROID
|
||||
extern AInputEvent* androidPlatformContextGetEvent(tp::glw::PlatformContext* ctx);
|
||||
extern const char* get_android_abs_path(const char* path, bool second = false);
|
||||
|
||||
const char* AndroidGetImGuiIniPath() {
|
||||
static char imgui_path[512];
|
||||
auto tmp = get_android_abs_path("imgui.ini");
|
||||
memcpy(imgui_path, tmp, strlen(tmp));
|
||||
return imgui_path;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char* getFontPath() {
|
||||
#ifdef ENV_OS_ANDROID
|
||||
return get_android_abs_path("rsc/fonts/CONSOLAB.TTF");
|
||||
#else
|
||||
return "./rsc/fonts/CONSOLAB.TTF";
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace tp {
|
||||
namespace glw {
|
||||
struct DebugUiInternalContext {
|
||||
|
||||
DebugUiDrawCallBack* cb = NULL;
|
||||
void* cd = NULL;
|
||||
|
||||
ImGuiContext* ui_context = NULL;
|
||||
ImGuiContext* vk_context = NULL;
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
bool ui_first_drawn = false;
|
||||
bool vk_first_drawn = false;
|
||||
|
||||
bool ui_context_want_active = true;
|
||||
bool ui_context_want_active_vk = false;
|
||||
bool vk_context_want_active = false;
|
||||
|
||||
tp::halnf dpmm;
|
||||
tp::halnf font_size_mm;
|
||||
tp::halnf ui_scale;
|
||||
|
||||
struct VKState {
|
||||
|
||||
struct InputButton {
|
||||
char val = '?';
|
||||
char shift_val = '?';
|
||||
tp::halnf width = 1;
|
||||
|
||||
void (*action)(InputButton* button, VKState* state) = [](InputButton* button, VKState* state) {
|
||||
if (state->mShifted) {
|
||||
ImGui::GetIO().AddInputCharacter(button->shift_val);
|
||||
}
|
||||
else {
|
||||
ImGui::GetIO().AddInputCharacter(button->val);
|
||||
}
|
||||
};
|
||||
|
||||
const char* display_name = NULL;
|
||||
};
|
||||
|
||||
struct Config {
|
||||
InputButton** rows = NULL;
|
||||
tp::halni nrows = NULL;
|
||||
tp::halnf* rows_widths = NULL;
|
||||
tp::halnf* rows_sizes = NULL;
|
||||
};
|
||||
|
||||
bool mShifted = false;
|
||||
|
||||
static const tp::uhalni mNConfigs = 2;
|
||||
Config mConfigs[mNConfigs];
|
||||
tp::uhalni mActiveConfigIdx = 0;
|
||||
|
||||
InputButton mCommonRow[7];
|
||||
//bool mActive = false;
|
||||
|
||||
VKState() {
|
||||
mCommonRow[0] = { '^', '^', 1 , [](InputButton* button, VKState* state) { state->mShifted = !state->mShifted; } };
|
||||
|
||||
mCommonRow[1] = { ' ', ' ', 1,
|
||||
[](InputButton* button, VKState* state) {
|
||||
state->mActiveConfigIdx++;
|
||||
if (state->mActiveConfigIdx == state->mNConfigs) {
|
||||
state->mActiveConfigIdx = 0;
|
||||
}
|
||||
},
|
||||
"..."
|
||||
};
|
||||
|
||||
mCommonRow[2] = { ' ', ' ', 2 };
|
||||
|
||||
mCommonRow[3] = { '<', '<', 2, [](InputButton* button, VKState* state) {
|
||||
ImGui::GetIO().AddKeyEvent(ImGuiKey_Backspace, true);
|
||||
ImGui::GetIO().AddKeyEvent(ImGuiKey_Backspace, false);
|
||||
} };
|
||||
|
||||
mCommonRow[4] = { '.', '.', 1 };
|
||||
mCommonRow[5] = { '@', '@', 1 };
|
||||
|
||||
mCommonRow[6] = { ' ', ' ', 2, [](InputButton* button, VKState* state) {
|
||||
ImGui::GetIO().AddKeyEvent(ImGuiKey_Enter, true);
|
||||
ImGui::GetIO().AddKeyEvent(ImGuiKey_Enter, false);
|
||||
}, "Entrer" };
|
||||
|
||||
setupMainConfig(mConfigs[0]);
|
||||
setupAdditionalConfig(mConfigs[1]);
|
||||
}
|
||||
|
||||
void setupMainConfig(Config& config) {
|
||||
|
||||
static InputButton row1[] = {
|
||||
{'1', '!'},
|
||||
{'2', '@'},
|
||||
{'3', '#'},
|
||||
{'4', '$'},
|
||||
{'5', '%'},
|
||||
{'6', '^'},
|
||||
{'7', '&'},
|
||||
{'8', '*'},
|
||||
{'9', '('},
|
||||
{'0', ')'},
|
||||
};
|
||||
|
||||
static InputButton row2[] = {
|
||||
{'q', 'Q'},
|
||||
{'w', 'W'},
|
||||
{'e', 'E'},
|
||||
{'r', 'R'},
|
||||
{'t', 'T'},
|
||||
{'y', 'Y'},
|
||||
{'u', 'U'},
|
||||
{'i', 'I'},
|
||||
{'o', 'O'},
|
||||
{'p', 'P'},
|
||||
};
|
||||
|
||||
static InputButton row3[] = {
|
||||
{'a', 'A'},
|
||||
{'s', 'S'},
|
||||
{'d', 'D'},
|
||||
{'f', 'F'},
|
||||
{'g', 'G'},
|
||||
{'h', 'H'},
|
||||
{'j', 'J'},
|
||||
{'k', 'K'},
|
||||
{'l', 'L'},
|
||||
};
|
||||
|
||||
static InputButton row4[] = {
|
||||
{'z', 'Z'},
|
||||
{'x', 'X'},
|
||||
{'c', 'C'},
|
||||
{'v', 'V'},
|
||||
{'b', 'B'},
|
||||
{'n', 'N'},
|
||||
{'m', 'M'},
|
||||
};
|
||||
|
||||
static InputButton* rows[] = {
|
||||
row1,
|
||||
row2,
|
||||
row3,
|
||||
row4,
|
||||
mCommonRow,
|
||||
};
|
||||
|
||||
static tp::halnf rows_sizes[IM_ARRAYSIZE(rows)] = {
|
||||
IM_ARRAYSIZE(row1),
|
||||
IM_ARRAYSIZE(row2),
|
||||
IM_ARRAYSIZE(row3),
|
||||
IM_ARRAYSIZE(row4),
|
||||
IM_ARRAYSIZE(mCommonRow),
|
||||
};
|
||||
|
||||
static tp::halnf rows_widths[IM_ARRAYSIZE(rows)];
|
||||
for (auto row = 0; row < IM_ARRAYSIZE(rows); row++) {
|
||||
for (auto butt = 0; butt < rows_sizes[row]; butt++) {
|
||||
rows_widths[row] += rows[row][butt].width;
|
||||
}
|
||||
}
|
||||
|
||||
config = {
|
||||
rows,
|
||||
IM_ARRAYSIZE(rows),
|
||||
rows_widths,
|
||||
rows_sizes,
|
||||
};
|
||||
}
|
||||
|
||||
void setupAdditionalConfig(Config& config) {
|
||||
static InputButton row1[] = {
|
||||
{'~', '~'},
|
||||
{'`', '`'},
|
||||
{'_', '_'},
|
||||
{'|', '|'},
|
||||
{'\\', '\\'},
|
||||
{'/', '/'},
|
||||
{'"', '"'},
|
||||
{'\'', '\''},
|
||||
};
|
||||
|
||||
static InputButton row2[] = {
|
||||
{';', ';'},
|
||||
{':', ':'},
|
||||
{'?', '?'},
|
||||
{',', ','},
|
||||
{'[', '['},
|
||||
{']', ']'},
|
||||
{'{', '{'},
|
||||
{'}', '}'},
|
||||
{'(', '('},
|
||||
{')', ')'},
|
||||
};
|
||||
|
||||
static InputButton row3[] = {
|
||||
{'-', '-'},
|
||||
{'=', '='},
|
||||
{'*', '*'},
|
||||
{'+', '+'},
|
||||
{'<', '<'},
|
||||
{'>', '>'},
|
||||
};
|
||||
|
||||
static InputButton row4[] = {
|
||||
{' ', ' ', 1, [](InputButton* butt, VKState* state) {
|
||||
ImGui::GetIO().AddKeyEvent(ImGuiKey_UpArrow, true);
|
||||
ImGui::GetIO().AddKeyEvent(ImGuiKey_UpArrow, false);
|
||||
}, "up" },
|
||||
{' ', ' ', 1, [](InputButton* butt, VKState* state) {
|
||||
ImGui::GetIO().AddKeyEvent(ImGuiKey_DownArrow, true);
|
||||
ImGui::GetIO().AddKeyEvent(ImGuiKey_DownArrow, false);
|
||||
}, "down"},
|
||||
{' ', ' ', 1, [](InputButton* butt, VKState* state) {
|
||||
ImGui::GetIO().AddKeyEvent(ImGuiKey_LeftArrow, true);
|
||||
ImGui::GetIO().AddKeyEvent(ImGuiKey_LeftArrow, false);
|
||||
}, "left"},
|
||||
{' ', ' ', 1, [](InputButton* butt, VKState* state) {
|
||||
ImGui::GetIO().AddKeyEvent(ImGuiKey_RightArrow, true);
|
||||
ImGui::GetIO().AddKeyEvent(ImGuiKey_RightArrow, false);
|
||||
}, "right"},
|
||||
};
|
||||
|
||||
static InputButton* rows[] = {
|
||||
row1,
|
||||
row2,
|
||||
row3,
|
||||
row4,
|
||||
mCommonRow,
|
||||
};
|
||||
|
||||
static tp::halnf rows_sizes[IM_ARRAYSIZE(rows)] = {
|
||||
IM_ARRAYSIZE(row1),
|
||||
IM_ARRAYSIZE(row2),
|
||||
IM_ARRAYSIZE(row3),
|
||||
IM_ARRAYSIZE(row4),
|
||||
IM_ARRAYSIZE(mCommonRow),
|
||||
};
|
||||
|
||||
static tp::halnf rows_widths[IM_ARRAYSIZE(rows)];
|
||||
for (auto row = 0; row < IM_ARRAYSIZE(rows); row++) {
|
||||
for (auto butt = 0; butt < rows_sizes[row]; butt++) {
|
||||
rows_widths[row] += rows[row][butt].width;
|
||||
}
|
||||
}
|
||||
|
||||
config = {
|
||||
rows,
|
||||
IM_ARRAYSIZE(rows),
|
||||
rows_widths,
|
||||
rows_sizes,
|
||||
};
|
||||
}
|
||||
|
||||
} mVKState;
|
||||
|
||||
DebugUiInternalContext(Window& window, DebugUiDrawCallBack* acb, void* acd) {
|
||||
|
||||
cb = acb;
|
||||
cd = acd;
|
||||
|
||||
ui_context = ImGui::CreateContext();
|
||||
ImGui::SetCurrentContext(ui_context);
|
||||
ImGuiContextInit(window);
|
||||
|
||||
vk_context = ImGui::CreateContext();
|
||||
ImGui::SetCurrentContext(vk_context);
|
||||
ImGuiContextInit(window);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void drawDebugUI(tp::halnf a_dpmm, tp::halnf a_font_size_mm, tp::halnf a_ui_scale) {
|
||||
dpmm = a_dpmm;
|
||||
font_size_mm = a_font_size_mm;
|
||||
ui_scale = a_ui_scale;
|
||||
|
||||
if (!initialized) return;
|
||||
|
||||
ImGui::SetCurrentContext(ui_context);
|
||||
ImGui::ApplyStyle(dpmm, font_size_mm, ui_scale);
|
||||
ImGuiContextBeginFrame();
|
||||
cb(cd);
|
||||
ImGuiContextEndFrame();
|
||||
ImGui::SetCurrentContext(NULL);
|
||||
ui_first_drawn = true;
|
||||
|
||||
if (ui_context_want_active_vk || vk_context_want_active) {
|
||||
ImGui::SetCurrentContext(vk_context);
|
||||
ImGui::ApplyStyle(dpmm, font_size_mm, ui_scale);
|
||||
ImGuiContextBeginFrame();
|
||||
VirtualKeyboard(dpmm, font_size_mm, ui_scale);
|
||||
ImGuiContextEndFrame();
|
||||
ImGui::SetCurrentContext(NULL);
|
||||
|
||||
vk_first_drawn = true;
|
||||
}
|
||||
}
|
||||
|
||||
~DebugUiInternalContext() {
|
||||
if (!initialized) return;
|
||||
|
||||
ImGui::SetCurrentContext(ui_context);
|
||||
ImGuiContextDeinit();
|
||||
ImGui::DestroyContext(ui_context);
|
||||
|
||||
ImGui::SetCurrentContext(vk_context);
|
||||
ImGuiContextDeinit();
|
||||
ImGui::DestroyContext(vk_context);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void ImGuiContextInit(Window& window) {
|
||||
#if defined ENV_OS_WINDOWS
|
||||
ImGui_ImplOpenGL3_Init();
|
||||
ImGui_ImplWin32_Init(window.platform_window());
|
||||
window.mNativeEventListeners.put("imgui", {
|
||||
nativeWindowEventListenerWrapBegin,
|
||||
nativeWindowEventListenerWrap,
|
||||
nativeWindowEventListenerWrapEnd,
|
||||
this
|
||||
});
|
||||
#elif defined ENV_OS_LINUX
|
||||
ImGui_ImplOpenGL3_Init();
|
||||
ImGui_ImplGlfw_InitForOpenGL((GLFWwindow*)window.platform_window(), true);
|
||||
#elif defined ENV_OS_ANDROID
|
||||
ImGui_ImplOpenGL3_Init("#version 300 es");
|
||||
ImGui_ImplAndroid_Init((ANativeWindow*)window.platform_window());
|
||||
ImGui::GetIO().IniFilename = AndroidGetImGuiIniPath();
|
||||
window.mNativeEventListeners.put("imgui", {
|
||||
nativeWindowEventListenerWrapBegin,
|
||||
nativeWindowEventListenerWrap,
|
||||
nativeWindowEventListenerWrapEnd,
|
||||
this
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void ImGuiContextBeginFrame() {
|
||||
#if defined ENV_OS_WINDOWS
|
||||
ImGui_ImplWin32_NewFrame();
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
#elif defined ENV_OS_LINUX
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
#elif defined ENV_OS_ANDROID
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplAndroid_NewFrame();
|
||||
#endif
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
void ImGuiContextEndFrame() {
|
||||
ImGui::Render();
|
||||
|
||||
#if defined ENV_OS_WINDOWS
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
#elif defined ENV_OS_LINUX
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
#elif defined ENV_OS_ANDROID
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
#endif
|
||||
}
|
||||
|
||||
void ImGuiContextDeinit() {
|
||||
#if defined ENV_OS_WINDOWS
|
||||
ImGui_ImplWin32_Shutdown();
|
||||
#elif defined ENV_OS_LINUX
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
#elif defined ENV_OS_ANDROID
|
||||
ImGui_ImplAndroid_Shutdown();
|
||||
#endif
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
}
|
||||
|
||||
void nativeWindowEventListenerPlatform(tp::glw::PlatformContext* ctx) {
|
||||
#if defined ENV_OS_WINDOWS
|
||||
auto native_window = windowsPlatformContextGetNativeWindow(ctx);
|
||||
auto message = windowsPlatformContextGetMessage(ctx);
|
||||
auto w_param = windowsPlatformContextGetWparam(ctx);
|
||||
auto l_param = windowsPlatformContextGetLparam(ctx);
|
||||
// IMGUI : needs to be commented out
|
||||
//if (bd->MouseButtonsDown == 0 && ::GetCapture() == nullptr)
|
||||
// ::SetCapture(hwnd);
|
||||
ImGui_ImplWin32_WndProcHandler(native_window, message, w_param, l_param);
|
||||
#elif defined ENV_OS_LINUX
|
||||
#elif defined ENV_OS_ANDROID
|
||||
|
||||
auto aev = androidPlatformContextGetEvent(ctx);
|
||||
|
||||
int32_t event_type = AInputEvent_getType(aev);
|
||||
|
||||
ImGui_ImplAndroid_HandleInputEvent(aev);
|
||||
|
||||
auto& io = ImGui::GetIO();
|
||||
|
||||
if (event_type == AINPUT_EVENT_TYPE_MOTION); {
|
||||
int32_t event_action = AMotionEvent_getAction(aev);
|
||||
int32_t event_pointer_index = (event_action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
||||
event_action &= AMOTION_EVENT_ACTION_MASK;
|
||||
|
||||
if ((AMotionEvent_getToolType(aev, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_FINGER)
|
||||
|| (AMotionEvent_getToolType(aev, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_UNKNOWN)) {
|
||||
|
||||
if (event_action == AMOTION_EVENT_ACTION_DOWN) {
|
||||
io.AddMousePosEvent(AMotionEvent_getX(aev, event_pointer_index), AMotionEvent_getY(aev, event_pointer_index));
|
||||
}
|
||||
else if (event_action == AMOTION_EVENT_ACTION_UP) {
|
||||
io.AddMousePosEvent(AMotionEvent_getX(aev, event_pointer_index), AMotionEvent_getY(aev, event_pointer_index));
|
||||
if (!ui_context_want_active_vk || vk_context_want_active) {
|
||||
io.AddMousePosEvent(-1, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void nativeWindowEventListenerBegin(tp::glw::PlatformContext* ctx) {
|
||||
vk_context_want_active = vk_context->IO.WantCaptureMouse || vk_context->IO.WantSetMousePos;
|
||||
|
||||
ui_context_want_active_vk = ui_context->IO.WantTextInput;
|
||||
ui_context_want_active = ui_context->IO.WantCaptureKeyboard || ui_context->IO.WantCaptureMouse || ui_context->IO.WantSetMousePos;
|
||||
}
|
||||
|
||||
void nativeWindowEventListener(tp::glw::PlatformContext* ctx) {
|
||||
|
||||
// proc vk
|
||||
if ((ui_context_want_active_vk || vk_context_want_active) && vk_first_drawn) {
|
||||
ImGui::SetCurrentContext(vk_context);
|
||||
nativeWindowEventListenerPlatform(ctx);
|
||||
|
||||
while (vk_context->InputEventsQueue.Size) {
|
||||
ImGui::ApplyStyle(dpmm, font_size_mm, ui_scale);
|
||||
ImGui::NewFrame();
|
||||
VirtualKeyboard(dpmm, font_size_mm, ui_scale);
|
||||
ImGui::Render();
|
||||
|
||||
vk_context_want_active |= vk_context->IO.WantCaptureMouse || vk_context->IO.WantSetMousePos;
|
||||
}
|
||||
|
||||
vk_context_want_active |= vk_context->IO.WantCaptureMouse || vk_context->IO.WantSetMousePos;
|
||||
|
||||
ImGui::SetCurrentContext(NULL);
|
||||
}
|
||||
|
||||
// proc ui
|
||||
if (!vk_context_want_active && ui_first_drawn) {
|
||||
ImGui::SetCurrentContext(ui_context);
|
||||
nativeWindowEventListenerPlatform(ctx);
|
||||
|
||||
while (ui_context->InputEventsQueue.Size) {
|
||||
ImGui::ApplyStyle(dpmm, font_size_mm, ui_scale);
|
||||
ImGui::NewFrame();
|
||||
cb(cd);
|
||||
ImGui::Render();
|
||||
|
||||
ui_context_want_active_vk |= ui_context->IO.WantTextInput;
|
||||
ui_context_want_active |= ui_context->IO.WantCaptureKeyboard || ui_context->IO.WantCaptureMouse || ui_context->IO.WantSetMousePos;
|
||||
}
|
||||
|
||||
ImGui::SetCurrentContext(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void nativeWindowEventListenerEnd(tp::glw::PlatformContext* ctx) {}
|
||||
|
||||
static void nativeWindowEventListenerWrapBegin(tp::glw::PlatformContext* ctx, void* cd) { ((DebugUiInternalContext*)cd)->nativeWindowEventListenerBegin(ctx); }
|
||||
static void nativeWindowEventListenerWrap(tp::glw::PlatformContext* ctx, void* cd) { ((DebugUiInternalContext*)cd)->nativeWindowEventListener(ctx); }
|
||||
static void nativeWindowEventListenerWrapEnd(tp::glw::PlatformContext* ctx, void* cd) { ((DebugUiInternalContext*)cd)->nativeWindowEventListenerEnd(ctx); }
|
||||
|
||||
void VirtualKeyboard(tp::halnf dpmm, tp::halnf font_size_mm, tp::halnf ui_scale) {
|
||||
auto& config = mVKState.mConfigs[mVKState.mActiveConfigIdx];
|
||||
|
||||
ImGuiID dockspace_id = ImGui::DockSpaceOverViewport(0, ImGuiDockNodeFlags_PassthruCentralNode);
|
||||
|
||||
ImGuiDockNode* node = ImGui::DockContextFindNodeByID(ImGui::GetCurrentContext(), dockspace_id);
|
||||
|
||||
if (!node->IsSplitNode()) {
|
||||
node->MergedFlags |= ImGuiDockNodeFlags_HiddenTabBar;
|
||||
ImGuiID dock_id = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Down, 0.33f, nullptr, &dockspace_id);
|
||||
ImGui::DockBuilderDockWindow("VK", dock_id);
|
||||
}
|
||||
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0.f, 0.f });
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, { 50 * dpmm, 30 * dpmm });
|
||||
ImGui::Begin("VK");
|
||||
ImGui::PopStyleVar(3);
|
||||
|
||||
auto pos = ImGui::GetCursorPos();
|
||||
|
||||
auto width = ImGui::GetWindowWidth();
|
||||
auto height = ImGui::GetWindowHeight() - pos.y;
|
||||
//auto scale = dpmm * ui_scale;
|
||||
auto padding = dpmm * 2 * ui_scale;
|
||||
auto button_sizey = (tp::halnf)(height - (config.nrows + 1) * padding) / config.nrows;
|
||||
|
||||
tp::vec2f crs = { pos.x + padding, pos.y + padding };
|
||||
|
||||
for (auto row = 0; row < config.nrows; row++) {
|
||||
tp::halnf butt_scalex = (width - (config.rows_sizes[row] + 1) * padding) / config.rows_widths[row];
|
||||
|
||||
crs.x = pos.x + padding;
|
||||
|
||||
for (auto butt = 0; butt < config.rows_sizes[row]; butt++) {
|
||||
auto& button = config.rows[row][butt];
|
||||
|
||||
ImGui::SetCursorPos({ crs.x, crs.y });
|
||||
|
||||
char name[2] = { mVKState.mShifted ? button.shift_val : button.val, 0 };
|
||||
|
||||
ImGui::PushID(&button);
|
||||
if (!ImGui::Button(button.display_name ? button.display_name: name, { butt_scalex * button.width, button_sizey })) {
|
||||
crs.x += butt_scalex * button.width + padding;
|
||||
ImGui::PopID();
|
||||
continue;
|
||||
}
|
||||
|
||||
ImGui::SetCurrentContext(ui_context);
|
||||
button.action(&button, &mVKState);
|
||||
ImGui::SetCurrentContext(vk_context);
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
crs.y += button_sizey + padding;
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
tp::glw::DebugUI::DebugUI(Window& window, DebugUiDrawCallBack* acb, void* acd) {
|
||||
mDPMM = window.mDevice.mDPMM;
|
||||
|
||||
// map device size to font and ui size
|
||||
{
|
||||
auto device_max = 600.f;
|
||||
auto device_min = 50.f;
|
||||
auto device = tp::clamp(window.mDevice.Size.x / mDPMM, device_min, device_max);
|
||||
auto device_factor = (device - device_min) / (device_max - device_min);
|
||||
|
||||
auto font_min = 2.f;
|
||||
auto font_max = 3.5f;
|
||||
mFontSizeMM = (font_max - font_min) * device_factor + font_min;
|
||||
|
||||
auto ui_max = 1.f;
|
||||
auto ui_min = 0.45f;
|
||||
mUIScale = (ui_max - ui_min) * device_factor + ui_min;
|
||||
}
|
||||
|
||||
mCtx = new DebugUiInternalContext(window, acb, acd);
|
||||
}
|
||||
|
||||
void tp::glw::DebugUI::drawDebugUI(tp::halnf dpmm) {
|
||||
mDPMM = dpmm;
|
||||
mCtx->drawDebugUI(mDPMM, mFontSizeMM, mUIScale);
|
||||
}
|
||||
|
||||
tp::glw::DebugUI::~DebugUI() {
|
||||
delete mCtx;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------ //
|
||||
|
||||
static const int sWindowFrameFlags = (ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoDecoration);
|
||||
|
||||
bool ImGui::SubMenuBegin(const char* desc, int level) {
|
||||
if (level == 1) {
|
||||
ImGui::Separator();
|
||||
}
|
||||
if (ImGui::TreeNode(desc)) {
|
||||
GImGui->Style.IndentSpacing = 6;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImGui::SubMenuEnd(int level) {
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
void ImGui::ToolTip(const char* desc) {
|
||||
ImGui::SameLine();
|
||||
ImGui::TextDisabled("*");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
||||
ImGui::TextUnformatted(desc);
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::PopupData ImGui::HoverPopupBeginButton(const char* id, tp::vec2f butsize, tp::vec2f popupsize) {
|
||||
ImVec2 curs = ImGui::GetCursorScreenPos();
|
||||
tp::vec2f popup_pos = tp::vec2f(curs.x + butsize.x / 2.f - popupsize.x / 2.f, (curs.y + butsize.y + 7));
|
||||
ImGui::Button(id, ImVec2(butsize.x, butsize.y)); ImGui::SameLine();
|
||||
return HoverPopupBegin(id, popupsize, popup_pos);
|
||||
}
|
||||
|
||||
ImGui::PopupData ImGui::HoverPopupBegin(const char* str_id, tp::vec2f size, tp::vec2f pos_p, ImGuiPopupFlags popup_flags) {
|
||||
ImGui::PopupData out;
|
||||
out.ishovered = ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
|
||||
|
||||
if (out.ishovered) {
|
||||
ImVec2 pos;
|
||||
|
||||
if (pos_p == tp::vec2f(-1)) {
|
||||
pos = GImGui->CurrentWindow->DC.CursorPos;
|
||||
}
|
||||
else {
|
||||
pos.x = pos_p.x;
|
||||
pos.y = pos_p.y;
|
||||
}
|
||||
|
||||
ImGui::SetNextWindowPos(pos);
|
||||
out.p1 = { pos.x, pos.y };
|
||||
|
||||
ImGui::OpenPopup(str_id);
|
||||
|
||||
out.p2 = out.p1;
|
||||
out.p2.x += ImGui::GetWindowWidth();
|
||||
}
|
||||
|
||||
if (BeginPopup(str_id, ImGuiWindowFlags_NoMove)) {
|
||||
out.opened = true;
|
||||
|
||||
auto pos = GetWindowPos();
|
||||
out.p1 = { pos.x, pos.y };
|
||||
out.p2 = out.p1;
|
||||
out.p2.x += ImGui::GetWindowWidth();
|
||||
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void ImGui::HoverPopupEnd(ImGui::PopupData& in) {
|
||||
|
||||
if (!in.opened) {
|
||||
return;
|
||||
}
|
||||
|
||||
in.ishovered |= IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_ChildWindows);
|
||||
|
||||
tp::vec2f mousepos = { ImGui::GetMousePos().x, ImGui::GetMousePos().y };
|
||||
tp::halnf tollerance = 10;
|
||||
tp::rectf tollerace_rect = tp::rectf(tp::vec2f(in.p1.x, in.p1.y - tollerance), tp::vec2f(in.p2.x - in.p1.x, tollerance * 2.f));
|
||||
bool is_tollerance = tollerace_rect.inside(mousepos);
|
||||
|
||||
if (!(in.ishovered || is_tollerance)) {
|
||||
CloseCurrentPopup();
|
||||
}
|
||||
|
||||
EndPopup();
|
||||
}
|
||||
|
||||
#define VAL(val) (val * dpmm / 3 * ui_scale)
|
||||
#define VEC(x, y) ImVec2(x * dpmm / 3, y * dpmm / 3 * ui_scale)
|
||||
|
||||
void ImGui::ApplyStyle(tp::halnf dpmm, float font_size_mm, float ui_scale) {
|
||||
|
||||
ImGuiStyle* style = &ImGui::GetStyle();
|
||||
auto& io = ImGui::GetIO();
|
||||
bool first_init = io.Fonts->Fonts.Size == 0;
|
||||
auto font_path = getFontPath();
|
||||
|
||||
// supports PDMM from 0.3 to 10
|
||||
const float min_dpmm = 0.3f;
|
||||
const float max_dpmm = 20.f;
|
||||
dpmm = tp::clamp(dpmm, min_dpmm, max_dpmm);
|
||||
|
||||
// calc font
|
||||
const float font_size_mm_max = 10;
|
||||
const float font_size_pixels_min = 9;
|
||||
float font_size_mm_min = font_size_pixels_min / dpmm;
|
||||
const int font_quality_steps = 3;
|
||||
font_size_mm = tp::clamp(font_size_mm, font_size_mm_min, font_size_mm_max);
|
||||
|
||||
float font_sizes[font_quality_steps];
|
||||
for (auto i = 0; i < font_quality_steps; i++) {
|
||||
auto mm = font_size_mm_min + (font_size_mm_max - font_size_mm_min) * tp::pow(((tp::halnf) (i + 1) / font_quality_steps), 3);
|
||||
font_sizes[i] = dpmm * mm;
|
||||
}
|
||||
|
||||
if (first_init) {
|
||||
for (auto i = 0; i < font_quality_steps; i++) {
|
||||
io.Fonts->AddFontFromFileTTF(font_path, font_sizes[i] * 1);
|
||||
}
|
||||
}
|
||||
|
||||
// select fonts
|
||||
auto const pixels_required = dpmm * font_size_mm;
|
||||
auto idx = -1;
|
||||
for (auto i = 0; i < font_quality_steps; i++) {
|
||||
idx = i;
|
||||
if (pixels_required <= font_sizes[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
DBG_BREAK(idx == -1);
|
||||
io.FontDefault = io.Fonts->Fonts[idx];
|
||||
io.FontGlobalScale = font_size_mm / (font_size_mm_min + ((font_size_mm_max - font_size_mm_min) / font_quality_steps) * (idx + 1));
|
||||
io.FontGlobalScale = pixels_required / font_sizes[idx];
|
||||
|
||||
auto rounding = VAL(5);
|
||||
auto pudding = VEC(7, 7);
|
||||
|
||||
style->WindowPadding = pudding;
|
||||
style->WindowRounding = rounding;
|
||||
//style->WindowMinSize = VEC(11, 11);
|
||||
style->ChildRounding = rounding;
|
||||
style->PopupRounding = rounding;
|
||||
style->FramePadding = pudding;
|
||||
style->FrameRounding = rounding;
|
||||
style->ItemSpacing = VEC(4, 11);
|
||||
style->ItemInnerSpacing = VEC(9, 4);
|
||||
style->CellPadding = pudding;
|
||||
style->TouchExtraPadding = pudding;
|
||||
style->IndentSpacing = VAL(25);
|
||||
style->ColumnsMinSpacing = VAL(5);
|
||||
style->ScrollbarSize = VAL(16);
|
||||
style->ScrollbarRounding = rounding;
|
||||
style->GrabMinSize = VAL(2);
|
||||
style->GrabRounding = rounding;
|
||||
style->LogSliderDeadzone = VAL(2);
|
||||
style->TabRounding = rounding;
|
||||
style->TabMinWidthForCloseButton = VAL(5);
|
||||
style->DisplayWindowPadding = pudding;
|
||||
style->DisplaySafeAreaPadding = pudding;
|
||||
style->MouseCursorScale = VAL(5);
|
||||
|
||||
style->FrameBorderSize = VAL(0);
|
||||
style->WindowBorderSize = VAL(1.5f);
|
||||
style->ChildBorderSize = VAL(2);
|
||||
|
||||
style->WindowTitleAlign = VEC(0.5f, 0.6f);
|
||||
style->WindowMenuButtonPosition = ImGuiDir_Right;
|
||||
|
||||
if (!first_init)
|
||||
return;
|
||||
|
||||
ImVec4* colors = ImGui::GetStyle().Colors;
|
||||
colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
|
||||
colors[ImGuiCol_TextDisabled] = ImVec4(0.86f, 0.86f, 0.86f, 1.00f);
|
||||
colors[ImGuiCol_WindowBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_ChildBg] = ImVec4(0.09f, 0.09f, 0.10f, 1.00f);
|
||||
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.10f, 1.00f);
|
||||
colors[ImGuiCol_Border] = ImVec4(0.06f, 0.06f, 0.06f, 1.00f);
|
||||
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||
colors[ImGuiCol_FrameBg] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.27f, 0.27f, 0.33f, 1.00f);
|
||||
colors[ImGuiCol_FrameBgActive] = ImVec4(0.43f, 0.43f, 0.53f, 1.00f);
|
||||
colors[ImGuiCol_TitleBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_TitleBgActive] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_MenuBarBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.09f, 0.09f, 0.10f, 0.00f);
|
||||
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.15f, 0.15f, 0.19f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.21f, 0.20f, 0.25f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.30f, 0.29f, 0.35f, 1.00f);
|
||||
colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.48f, 0.50f, 1.00f);
|
||||
colors[ImGuiCol_SliderGrab] = ImVec4(0.53f, 0.57f, 0.64f, 1.00f);
|
||||
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.69f, 0.74f, 0.83f, 1.00f);
|
||||
colors[ImGuiCol_Button] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_ButtonHovered] = ImVec4(0.27f, 0.27f, 0.33f, 1.00f);
|
||||
colors[ImGuiCol_ButtonActive] = ImVec4(0.43f, 0.43f, 0.53f, 1.00f);
|
||||
colors[ImGuiCol_Header] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_HeaderHovered] = ImVec4(0.27f, 0.27f, 0.33f, 1.00f);
|
||||
colors[ImGuiCol_HeaderActive] = ImVec4(0.33f, 0.33f, 0.40f, 1.00f);
|
||||
colors[ImGuiCol_Separator] = ImVec4(0.37f, 0.37f, 0.40f, 1.00f);
|
||||
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.33f, 0.35f, 0.38f, 1.00f);
|
||||
colors[ImGuiCol_SeparatorActive] = ImVec4(0.37f, 0.39f, 0.42f, 1.00f);
|
||||
colors[ImGuiCol_ResizeGrip] = ImVec4(0.16f, 0.17f, 0.19f, 1.00f);
|
||||
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.33f, 0.35f, 0.38f, 1.00f);
|
||||
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.28f, 0.34f, 0.42f, 1.00f);
|
||||
colors[ImGuiCol_Tab] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_TabHovered] = ImVec4(0.23f, 0.23f, 0.28f, 1.00f);
|
||||
colors[ImGuiCol_TabActive] = ImVec4(0.23f, 0.23f, 0.28f, 1.00f);
|
||||
colors[ImGuiCol_TabUnfocused] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.43f, 0.45f, 0.48f, 1.00f);
|
||||
colors[ImGuiCol_DockingPreview] = ImVec4(0.81f, 0.81f, 0.81f, 0.18f);
|
||||
colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
|
||||
colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.33f, 0.35f, 0.38f, 1.00f);
|
||||
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
||||
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(0.49f, 0.51f, 0.54f, 1.00f);
|
||||
colors[ImGuiCol_TableHeaderBg] = ImVec4(0.13f, 0.13f, 0.20f, 1.00f);
|
||||
colors[ImGuiCol_TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.35f, 1.00f);
|
||||
colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 1.00f);
|
||||
colors[ImGuiCol_TableRowBg] = ImVec4(0.23f, 0.20f, 0.20f, 0.00f);
|
||||
colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
|
||||
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
|
||||
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
|
||||
colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
|
||||
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.38f, 0.22f, 0.22f, 0.20f);
|
||||
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
|
||||
|
||||
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.10f, 1.00f);
|
||||
colors[ImGuiCol_DockingPreview] = ImVec4(0.64f, 0.75f, 0.83f, 0.18f);
|
||||
colors[ImGuiCol_TabHovered] = ImVec4(0.39f, 0.39f, 0.47f, 1.00f);
|
||||
colors[ImGuiCol_TabActive] = ImVec4(0.27f, 0.27f, 0.33f, 1.00f);
|
||||
colors[ImGuiCol_TabUnfocused] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.24f, 0.24f, 0.29f, 1.00f);
|
||||
colors[ImGuiCol_Border] = ImVec4(0.65f, 0.65f, 0.65f, 0.70f);
|
||||
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
}
|
||||
116
.outdated/graphics/src/fbuffer.cpp
Normal file
116
.outdated/graphics/src/fbuffer.cpp
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
|
||||
#include "fbuffer.h"
|
||||
|
||||
#include "GraphicsLibApi.h"
|
||||
|
||||
void glerr(GLenum type);
|
||||
#define AssertGL(x) { x; GLenum __gle = glGetError(); if (__gle != GL_NO_ERROR) glerr(__gle); }
|
||||
|
||||
namespace tp {
|
||||
|
||||
using namespace glw;
|
||||
|
||||
fbuffer::fbuffer(const vec2f& size) : mSize(size) {
|
||||
mDrawBuffers[0] = {GL_COLOR_ATTACHMENT0};
|
||||
|
||||
// --------- texture ---------
|
||||
AssertGL(glGenTextures(1, &mTextureId));
|
||||
AssertGL(glBindTexture(GL_TEXTURE_2D, mTextureId));
|
||||
// Give an empty image to OpenGL ( the last "0" )
|
||||
AssertGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)size.x, (GLsizei)size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
|
||||
// Poor filtering. Needed
|
||||
AssertGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||
AssertGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||
|
||||
// --------- depth ---------
|
||||
AssertGL(glGenRenderbuffers(1, &mDepthBufferID));
|
||||
AssertGL(glBindRenderbuffer(GL_RENDERBUFFER, mDepthBufferID));
|
||||
AssertGL(glRenderbufferStorage(GL_RENDERBUFFER, GLW_CONTEXT_DEPTH_COMPONENT, (GLsizei)size.x, (GLsizei)size.y));
|
||||
|
||||
// ------------ framebuffer ------------
|
||||
AssertGL(glGenFramebuffers(1, &mFrameBufferID));
|
||||
AssertGL(glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferID));
|
||||
AssertGL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthBufferID));
|
||||
// Set "renderedTexture" as our colour attachement #0
|
||||
AssertGL(glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextureId, 0));
|
||||
// Set the list of draw buffers.
|
||||
AssertGL(glDrawBuffers(1, mDrawBuffers)); // "1" is the size of DrawBuffers
|
||||
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
fbuffer::fbuffer(const vec2f& size, tp::uint1 samples) : mSize(size) {
|
||||
mDrawBuffers[0] = { GL_COLOR_ATTACHMENT0 };
|
||||
|
||||
// ------- texture ---------
|
||||
AssertGL(glGenTextures(1, &mTextureId));
|
||||
AssertGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextureId));
|
||||
#ifdef ENV_OS_ANDROID
|
||||
AssertGL(glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, (GLsizei)size.x, (GLsizei)size.y, GL_TRUE));
|
||||
#else
|
||||
AssertGL(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, (GLsizei)size.x, (GLsizei)size.y, GL_TRUE));
|
||||
#endif
|
||||
// !?
|
||||
//AssertGL(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||
//AssertGL(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||
|
||||
// ------- depth -------
|
||||
AssertGL(glGenRenderbuffers(1, &mDepthBufferID));
|
||||
AssertGL(glBindRenderbuffer(GL_RENDERBUFFER, mDepthBufferID));
|
||||
AssertGL(glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GLW_CONTEXT_DEPTH_COMPONENT, (GLsizei)size.x, (GLsizei)size.y));
|
||||
|
||||
// ------- fbuff -------
|
||||
AssertGL(glGenFramebuffers(1, &mFrameBufferID));
|
||||
AssertGL(glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferID));
|
||||
AssertGL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, mTextureId, 0));
|
||||
AssertGL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthBufferID));
|
||||
AssertGL(glDrawBuffers(1, mDrawBuffers));
|
||||
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
tp::uint4 fbuffer::buffId() const {
|
||||
return mFrameBufferID;
|
||||
}
|
||||
|
||||
void fbuffer::beginDraw() {
|
||||
AssertGL(glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferID));
|
||||
setViewport({ 0.f, 0.f, mSize.x, mSize.y });
|
||||
}
|
||||
|
||||
void fbuffer::setViewport(const rectf& viewport) {
|
||||
AssertGL(glViewport((GLsizei)viewport.x, (GLsizei)viewport.y, (GLsizei)viewport.z, (GLsizei)viewport.w));
|
||||
}
|
||||
|
||||
void fbuffer::clear() {
|
||||
AssertGL(glClearColor(mClearCol.r, mClearCol.g, mClearCol.b, mClearCol.a));
|
||||
AssertGL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
|
||||
}
|
||||
|
||||
void fbuffer::endDraw() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
fbuffer::~fbuffer() {
|
||||
glDeleteFramebuffers(1, &mFrameBufferID);
|
||||
glDeleteTextures(1, &mTextureId);
|
||||
glDeleteRenderbuffers(1, &mDepthBufferID);
|
||||
}
|
||||
|
||||
uhalni glw::fbuffer::sizeAllocatedMem() const {
|
||||
return uhalni(sizeof(GLenum) * 4 + mSize.sizeAllocatedMem() + (sizeof(mClearCol) + 1) * (alni) mSize.x * (alni) mSize.y);
|
||||
}
|
||||
|
||||
uhalni glw::fbuffer::sizeUsedMem() const {
|
||||
return sizeAllocatedMem();
|
||||
}
|
||||
|
||||
uint4 glw::fbuffer::texId() const {
|
||||
return mTextureId;
|
||||
}
|
||||
|
||||
const vec2f& fbuffer::getSize() const { return mSize; }
|
||||
|
||||
};
|
||||
282
.outdated/graphics/src/linux_window.cpp
Normal file
282
.outdated/graphics/src/linux_window.cpp
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
|
||||
#include "window.h"
|
||||
|
||||
#include "GL/glew.h"
|
||||
#include "GLFW/glfw3.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
|
||||
tp::glw::Window::Device tp::glw::Window::mDevice;
|
||||
|
||||
static void glfw_error_callback(int error, const char* description) {
|
||||
std::cout << stderr << "Glfw Error" << error << " " << description << "\n";
|
||||
}
|
||||
|
||||
void tp::glw::Window::init() {
|
||||
tp::glw::Window::mDevice.Size;
|
||||
tp::glw::Window::mDevice.FrameRate;
|
||||
|
||||
// Setup window
|
||||
|
||||
setenv("DISPLAY", ":0.0", 0); // does overwrite
|
||||
|
||||
glfwSetErrorCallback(glfw_error_callback);
|
||||
RelAssert(glfwInit());
|
||||
|
||||
|
||||
// GL 3.0 + GLSL 130
|
||||
const char* glsl_version = "#version 130";
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 3.0+ only
|
||||
|
||||
glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
|
||||
|
||||
GLFWmonitor* primary = glfwGetPrimaryMonitor();
|
||||
auto mode = glfwGetVideoMode(primary);
|
||||
|
||||
tp::glw::Window::mDevice.Size = { mode->width, mode->height };
|
||||
tp::glw::Window::mDevice.FrameRate = mode->refreshRate;
|
||||
}
|
||||
|
||||
#define MAP_EV(SYSKEY, code) case SYSKEY: { self->mEvents.mKeysQueue.push(tp::KeyEvent{ code, state }); break; }
|
||||
|
||||
namespace tp {
|
||||
namespace glw {
|
||||
struct PlatformContext {
|
||||
|
||||
GLFWwindow* window;
|
||||
tp::glw::Window* window_ctx = NULL;
|
||||
|
||||
PlatformContext(tp::glw::Window* a_window_ctx) {
|
||||
|
||||
window_ctx = a_window_ctx;
|
||||
|
||||
// Create window with graphics context
|
||||
window = glfwCreateWindow(300, 300, " ", NULL, NULL);
|
||||
RelAssert(window);
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
GLenum err = glewInit();
|
||||
if (GLEW_OK != err)
|
||||
{
|
||||
std::cout << stderr << "Error:" << glewGetErrorString(err);
|
||||
RelAssert(0);
|
||||
}
|
||||
|
||||
glfwSwapInterval(1); // Enable vsync
|
||||
|
||||
glfwSetWindowUserPointer(window, window_ctx);
|
||||
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetMouseButtonCallback(window, mouse_button_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
}
|
||||
|
||||
void applyAppearance(tp::glw::Window::Appearence& appear, tp::glw::Window::Appearence& prev, tp::glw::Window* win_ctx) {
|
||||
|
||||
if (!(appear.mSize == prev.mSize)) {
|
||||
glfwSetWindowSize(window, appear.mSize.x, appear.mSize.y);
|
||||
prev.mSize = appear.mSize;
|
||||
}
|
||||
|
||||
if (!(appear.mPos == prev.mPos)) {
|
||||
//glfwSetWindowPos(window, appear.mPos.x, appear.mPos.y);
|
||||
|
||||
win_ctx->mEvents.mCursor -= appear.mPos - prev.mPos;
|
||||
//win_ctx->mEvents.mCursorPrev -= appear.mPos - prev.mPos;
|
||||
prev.mPos = appear.mPos;
|
||||
}
|
||||
|
||||
if (!(appear.mSizeMax == prev.mSizeMax && appear.mSizeMin == prev.mSizeMin)) {
|
||||
glfwSetWindowSizeLimits(window, appear.mSizeMin.x, appear.mSizeMin.y, appear.mSizeMax.x, appear.mSizeMax.y);
|
||||
prev.mSizeMax = appear.mSizeMax;
|
||||
prev.mSizeMin = appear.mSizeMin;
|
||||
}
|
||||
|
||||
if (!(appear.mMaximized == prev.mMaximized)) {
|
||||
DBG_BREAK(1);
|
||||
}
|
||||
|
||||
if (!(appear.mMinimized == prev.mMinimized)) {
|
||||
DBG_BREAK(1);
|
||||
}
|
||||
|
||||
int width, height;
|
||||
glfwGetWindowSize(window, &width, &height);
|
||||
appear.mSize = { width, height };
|
||||
prev.mSize = appear.mSize;
|
||||
|
||||
glfwGetWindowPos(window, &width, &height);
|
||||
appear.mPos = { width, height };
|
||||
prev.mPos = appear.mPos;
|
||||
}
|
||||
|
||||
void beginDraw() {
|
||||
//int display_w, display_h;
|
||||
//glfwGetFramebufferSize(window, &display_w, &display_h);
|
||||
//glViewport(0, 0, display_w, display_h);
|
||||
//glClearColor(0, 0, 0, 0);
|
||||
//glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void endDraw() {
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
void pollEvents() {
|
||||
|
||||
glfwPollEvents();
|
||||
|
||||
double xpos, ypos;
|
||||
glfwGetCursorPos(window, &xpos, &ypos);
|
||||
|
||||
window_ctx->mEvents.mCursorPrev = window_ctx->mEvents.mCursor;
|
||||
window_ctx->mEvents.mCursor = { xpos, ypos };
|
||||
}
|
||||
|
||||
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
|
||||
auto self = (tp::glw::Window*) glfwGetWindowUserPointer(window);
|
||||
|
||||
if (action != GLFW_PRESS && action != GLFW_RELEASE) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto state = (action == GLFW_RELEASE) ? tp::KeyEvent::EventState::RELEASED : tp::KeyEvent::EventState::PRESSED;
|
||||
|
||||
//* VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39)
|
||||
if (key >= GLFW_KEY_0 && key <= GLFW_KEY_9) {
|
||||
self->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode(key), state });
|
||||
return;
|
||||
}
|
||||
|
||||
//* VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A)
|
||||
else if (key >= GLFW_KEY_A && key <= GLFW_KEY_Z) {
|
||||
self->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode(key), state });
|
||||
return;
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
MAP_EV(GLFW_KEY_LEFT_SHIFT, tp::Keycode::LEFT_SHIFT);
|
||||
MAP_EV(GLFW_KEY_LEFT, tp::Keycode::LEFT);
|
||||
MAP_EV(GLFW_KEY_RIGHT, tp::Keycode::RIGHT);
|
||||
MAP_EV(GLFW_KEY_UP, tp::Keycode::UP);
|
||||
MAP_EV(GLFW_KEY_DOWN, tp::Keycode::DOWN);
|
||||
MAP_EV(GLFW_KEY_BACKSPACE, tp::Keycode::BACKSPACE);
|
||||
MAP_EV(GLFW_KEY_LEFT_CONTROL, tp::Keycode::LEFT_CONTROL);
|
||||
MAP_EV(GLFW_KEY_MENU, tp::Keycode::LEFT_ALT);
|
||||
MAP_EV(GLFW_KEY_ENTER, tp::Keycode::ENTER);
|
||||
MAP_EV(GLFW_KEY_SPACE, tp::Keycode::SPACE);
|
||||
MAP_EV(GLFW_KEY_COMMA, tp::Keycode::COMMA);
|
||||
MAP_EV(GLFW_KEY_PERIOD, tp::Keycode::PERIOD);
|
||||
MAP_EV(GLFW_KEY_TAB, tp::Keycode::TAB);
|
||||
MAP_EV(GLFW_KEY_EQUAL, tp::Keycode::EQUAL);
|
||||
MAP_EV(GLFW_KEY_MINUS, tp::Keycode::MINUS);
|
||||
MAP_EV(GLFW_KEY_3, tp::Keycode::TILDA);
|
||||
MAP_EV(GLFW_KEY_4, tp::Keycode::BRA);
|
||||
MAP_EV(GLFW_KEY_5, tp::Keycode::SLASH);
|
||||
MAP_EV(GLFW_KEY_6, tp::Keycode::KET);
|
||||
MAP_EV(GLFW_KEY_1, tp::Keycode::DOUBLE_DOT);
|
||||
MAP_EV(GLFW_KEY_7, tp::Keycode::QUOTES);
|
||||
MAP_EV(GLFW_KEY_2, tp::Keycode::INV_SLASH);
|
||||
MAP_EV(GLFW_KEY_ESCAPE, tp::Keycode::ESCAPE);
|
||||
}
|
||||
}
|
||||
|
||||
static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
|
||||
auto self = (tp::glw::Window*)glfwGetWindowUserPointer(window);
|
||||
|
||||
if (action != GLFW_PRESS && action != GLFW_RELEASE) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto state = (action == GLFW_RELEASE) ? tp::KeyEvent::EventState::RELEASED : tp::KeyEvent::EventState::PRESSED;
|
||||
|
||||
|
||||
switch (button) {
|
||||
case GLFW_MOUSE_BUTTON_RIGHT: {
|
||||
self->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode::MOUSE2, state });
|
||||
} break;
|
||||
case GLFW_MOUSE_BUTTON_LEFT: {
|
||||
self->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode::MOUSE1, state });
|
||||
} break;
|
||||
case GLFW_MOUSE_BUTTON_MIDDLE: {
|
||||
self->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode::MOUSE3, state });
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
static void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
|
||||
}
|
||||
|
||||
~PlatformContext() {
|
||||
glfwDestroyWindow(window);
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
void tp::glw::Window::deinit() {}
|
||||
|
||||
tp::glw::Window::Window() {
|
||||
initialize();
|
||||
|
||||
mAppearence.mSize = tp::glw::Window::mDevice.Size / 1.5f;
|
||||
mAppearence.mPos = (tp::glw::Window::mDevice.Size - mAppearence.mSize) / 2.f;
|
||||
mAppearence.mSizeMax = tp::glw::Window::mDevice.Size;
|
||||
|
||||
applyAppearance();
|
||||
}
|
||||
|
||||
tp::glw::Window::Window(const Appearence& aAppearence) {
|
||||
mAppearence = aAppearence;
|
||||
initialize();
|
||||
}
|
||||
|
||||
void tp::glw::Window::initialize() {
|
||||
mPlatformCtx = new PlatformContext(this);
|
||||
applyAppearance();
|
||||
}
|
||||
|
||||
void tp::glw::Window::applyAppearance() {
|
||||
mPlatformCtx->applyAppearance(mAppearence, this->mCache.mAppearencePrev, this);
|
||||
}
|
||||
|
||||
void tp::glw::Window::pollEvents() {
|
||||
applyAppearance();
|
||||
mPlatformCtx->pollEvents();
|
||||
|
||||
mEvents.mRedraw |= (mEvents.mCursorPrev - mEvents.mCursor) != 0;
|
||||
mEvents.mRedraw |= mEvents.mKeysQueue.length;
|
||||
}
|
||||
|
||||
void tp::glw::Window::platformCallback() {}
|
||||
|
||||
void tp::glw::Window::beginDraw() {
|
||||
mPlatformCtx->beginDraw();
|
||||
}
|
||||
|
||||
void tp::glw::Window::endDraw() {
|
||||
mPlatformCtx->endDraw();
|
||||
if (mEvents.mRedraw-- < 0) mEvents.mRedraw = 0;
|
||||
}
|
||||
|
||||
void* tp::glw::Window::platform_window() const {
|
||||
return mPlatformCtx->window;
|
||||
}
|
||||
|
||||
tp::alni tp::glw::Window::sizeAllocatedMem() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tp::alni tp::glw::Window::sizeUsedMem() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tp::glw::Window::~Window() {
|
||||
delete mPlatformCtx;
|
||||
}
|
||||
170
.outdated/graphics/src/shader.cpp
Normal file
170
.outdated/graphics/src/shader.cpp
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
|
||||
|
||||
#include "stringt.h"
|
||||
|
||||
#include "array.h"
|
||||
|
||||
#include "array.h"
|
||||
#include "filesystem.h"
|
||||
#include "shader.h"
|
||||
|
||||
#include "new.h"
|
||||
|
||||
#include "GraphicsLibApi.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace tp {
|
||||
|
||||
using namespace glw;
|
||||
|
||||
//string shader_path = "../rsc/shaders/";
|
||||
|
||||
shader::shader() {
|
||||
programm = 0;
|
||||
VertexShaderID = 0;
|
||||
FragmentShaderID = 0;
|
||||
GeometryShaderID = 0;
|
||||
}
|
||||
|
||||
void shader::vert_bind_source(const char* vert_src) {
|
||||
VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
|
||||
compile_shader(vert_src, VertexShaderID);
|
||||
}
|
||||
|
||||
void shader::frag_bind_source(const char* frag_src) {
|
||||
FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
compile_shader(frag_src, FragmentShaderID);
|
||||
}
|
||||
|
||||
void shader::geom_bind_source(const char* geom_src) {
|
||||
GeometryShaderID = glCreateShader(GL_GEOMETRY_SHADER);
|
||||
compile_shader(geom_src, GeometryShaderID);
|
||||
}
|
||||
|
||||
void shader::compile() {
|
||||
GLint Result = GL_FALSE;
|
||||
int InfoLogLength;
|
||||
|
||||
programm = glCreateProgram();
|
||||
glAttachShader(programm, VertexShaderID);
|
||||
if (GeometryShaderID) glAttachShader(programm, GeometryShaderID);
|
||||
glAttachShader(programm, FragmentShaderID);
|
||||
glLinkProgram(programm);
|
||||
|
||||
// Check the program
|
||||
glGetProgramiv(programm, GL_LINK_STATUS, &Result);
|
||||
glGetProgramiv(programm, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
||||
|
||||
if (InfoLogLength > 0) {
|
||||
Array<char> ProgramErrorMessage(InfoLogLength + 1);
|
||||
glGetProgramInfoLog(programm, InfoLogLength, NULL, &ProgramErrorMessage[0]);
|
||||
printf("%s\n", &ProgramErrorMessage[0]);
|
||||
}
|
||||
|
||||
glDetachShader(programm, VertexShaderID);
|
||||
glDetachShader(programm, FragmentShaderID);
|
||||
if (GeometryShaderID) glDetachShader(programm, GeometryShaderID);
|
||||
|
||||
glDeleteShader(VertexShaderID);
|
||||
glDeleteShader(FragmentShaderID);
|
||||
if (GeometryShaderID) glDeleteShader(GeometryShaderID);
|
||||
}
|
||||
|
||||
bool shader::compile_shader(const char* ShaderCode, uint4 ShaderID) {
|
||||
GLint Result = GL_FALSE;
|
||||
int InfoLogLength;
|
||||
|
||||
char const* SourcePointer = ShaderCode;
|
||||
glShaderSource(ShaderID, 1, &SourcePointer, NULL);
|
||||
glCompileShader(ShaderID);
|
||||
|
||||
// Check Shader
|
||||
glGetShaderiv(ShaderID, GL_COMPILE_STATUS, &Result);
|
||||
glGetShaderiv(ShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
||||
|
||||
if (InfoLogLength > 0) {
|
||||
Array<char> VertexShaderErrorMessage(InfoLogLength + 1);
|
||||
glGetShaderInfoLog(ShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
|
||||
printf("%s\n", &VertexShaderErrorMessage[0]);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
void shader::load(const char* pvert, const char* pgeom, const char* pfrag, bool paths) {
|
||||
|
||||
// Create the shaders
|
||||
VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
|
||||
FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
if (pgeom) GeometryShaderID = glCreateShader(GL_GEOMETRY_SHADER);
|
||||
else GeometryShaderID = 0;
|
||||
|
||||
GLint Result = GL_FALSE;
|
||||
int InfoLogLength = 0;
|
||||
|
||||
if (paths) {
|
||||
string vert = sfmt("%c.vert", pvert);
|
||||
string geom = pgeom ? sfmt("%c.geom", pgeom) : " ";
|
||||
string frag = sfmt("%c.frag", pfrag);
|
||||
|
||||
tp::string content;
|
||||
|
||||
printf("Compiling shader : %s\n", vert.cstr());
|
||||
if (content.loadFile(vert)) {
|
||||
compile_shader(content.cstr(), VertexShaderID);
|
||||
}
|
||||
|
||||
if (GeometryShaderID) {
|
||||
printf("Compiling shader : %s\n", geom.cstr());
|
||||
if (content.loadFile(geom)) {
|
||||
compile_shader(content.cstr(), GeometryShaderID);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Compiling shader : %s\n", frag.cstr());
|
||||
if (content.loadFile(frag)) {
|
||||
compile_shader(content.cstr(), FragmentShaderID);
|
||||
}
|
||||
}
|
||||
else {
|
||||
compile_shader(pvert, VertexShaderID);
|
||||
if (GeometryShaderID) {
|
||||
compile_shader(pgeom, GeometryShaderID);
|
||||
}
|
||||
compile_shader(pfrag, FragmentShaderID);
|
||||
}
|
||||
|
||||
compile();
|
||||
}
|
||||
|
||||
shader::shader(const char* vert, const char* geom, const char* frag, bool paths) {
|
||||
load(vert, geom, frag, paths);
|
||||
}
|
||||
|
||||
void shader::bind() {
|
||||
glUseProgram(programm);
|
||||
}
|
||||
|
||||
GLuint glw::shader::getu(const char* uid) {
|
||||
return glGetUniformLocation(programm, uid);
|
||||
}
|
||||
|
||||
void shader::unbind() {
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
shader::~shader() {
|
||||
glDeleteProgram(programm);
|
||||
}
|
||||
|
||||
alni glw::shader::sizeAllocatedMem() {
|
||||
return sizeof(GLuint) * 4;
|
||||
}
|
||||
|
||||
alni glw::shader::sizeUsedMem() {
|
||||
return sizeof(GLuint) * 4;
|
||||
}
|
||||
|
||||
};
|
||||
164
.outdated/graphics/src/simplegui.cpp
Normal file
164
.outdated/graphics/src/simplegui.cpp
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
#pragma once
|
||||
|
||||
#include "simplegui.h"
|
||||
|
||||
using namespace tp;
|
||||
using namespace glw;
|
||||
|
||||
void WindowSimpleInputs::update(const glw::Window& window, halnf uiscale) {
|
||||
mScaleVal = (window.mDevice.mDPMM * uiscale);
|
||||
mWindowSizeMM = window.mAppearence.mSize / mScaleVal;
|
||||
mCrs = window.mEvents.mCursor / mScaleVal;
|
||||
mCrsPrev = window.mEvents.mCursorPrev / mScaleVal;
|
||||
mCrsmDelta = mCrs - mCrsPrev;
|
||||
|
||||
if (mMouse == Mouse::PRESSED) {
|
||||
mMouse = Mouse::HOLD;
|
||||
}
|
||||
else if (mMouse == Mouse::RELEASED) {
|
||||
mMouse = Mouse::NONE;
|
||||
}
|
||||
mMove = Move::NONE;
|
||||
|
||||
for (auto event : window.mEvents.mKeysQueue) {
|
||||
bool press = event.data().event_state == KeyEvent::EventState::PRESSED;
|
||||
if (press) {
|
||||
switch (event.data().code) {
|
||||
case Keycode::UP: mMove = Move::UP; break;
|
||||
case Keycode::DOWN: mMove = Move::DOWN; break;
|
||||
case Keycode::LEFT: mMove = Move::LEFT; break;
|
||||
case Keycode::RIGHT: mMove = Move::RIGHT; break;
|
||||
}
|
||||
}
|
||||
if (event.data().code == Keycode::MOUSE1) {
|
||||
if (press) {
|
||||
mMouse = Mouse::PRESSED;
|
||||
}
|
||||
else {
|
||||
mMouse = Mouse::RELEASED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowSimpleInputs::Activated() { return mMouse == Mouse::PRESSED; }
|
||||
bool WindowSimpleInputs::Anticipating() { return mMouse == Mouse::HOLD; }
|
||||
bool WindowSimpleInputs::Selected() { return mMouse == Mouse::RELEASED; }
|
||||
bool WindowSimpleInputs::MoveLeft() { return mMove == Move::LEFT; }
|
||||
bool WindowSimpleInputs::MoveRight() { return mMove == Move::RIGHT; }
|
||||
bool WindowSimpleInputs::MoveUp() { return mMove == Move::UP; }
|
||||
bool WindowSimpleInputs::MoveDown() { return mMove == Move::DOWN; }
|
||||
bool WindowSimpleInputs::Drag() { return mCrsmDelta != 0; }
|
||||
|
||||
void ButtonWidget::draw(glw::Canvas& canvas) {
|
||||
canvas.setCol1(mCol);
|
||||
canvas.rect(mAnimRec.get(), 1.f);
|
||||
}
|
||||
|
||||
void ButtonWidget::proc(glw::WindowSimpleInputs& inputs) {
|
||||
auto rec = mAnimRec.get();
|
||||
mPressed = false;
|
||||
|
||||
mAnimRec.setAnimTime(100);
|
||||
|
||||
if (rec.inside(inputs.mCrs)) {
|
||||
if (inputs.Anticipating()) {
|
||||
auto new_rec = mRect;
|
||||
new_rec.scale_from_center(0.3f, true);
|
||||
mAnimRec.setNoTransition(new_rec);
|
||||
}
|
||||
else {
|
||||
mAnimRec.set(mRect);
|
||||
}
|
||||
|
||||
if (inputs.Selected()) {
|
||||
mPressed = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto new_rec = mRect;
|
||||
new_rec.scale_from_center(0.3f, true);
|
||||
mAnimRec.set(new_rec);
|
||||
}
|
||||
}
|
||||
|
||||
void CheckBoxWidget::draw(glw::Canvas& canvas) {
|
||||
canvas.setCol1(mAnimCol.get());
|
||||
canvas.rect(mAnimRec.get(), 1.f);
|
||||
}
|
||||
|
||||
void CheckBoxWidget::proc(glw::WindowSimpleInputs& inputs) {
|
||||
auto rec = mAnimRec.get();
|
||||
|
||||
mAnimRec.setAnimTime(100);
|
||||
|
||||
if (rec.inside(inputs.mCrs)) {
|
||||
if (inputs.Anticipating()) {
|
||||
auto new_rec = mRect;
|
||||
new_rec.scale_from_center(0.3f, true);
|
||||
mAnimRec.setNoTransition(new_rec);
|
||||
}
|
||||
else {
|
||||
mAnimRec.set(mRect);
|
||||
}
|
||||
|
||||
if (inputs.Selected()) {
|
||||
mValue = !mValue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto new_rec = mRect;
|
||||
new_rec.scale_from_center(0.3f, true);
|
||||
mAnimRec.set(new_rec);
|
||||
}
|
||||
|
||||
if (mValue) {
|
||||
mAnimCol.set(mColActive);
|
||||
}
|
||||
else {
|
||||
mAnimCol.set(mCol);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsHeaderWidget::updRecs() {
|
||||
auto padding = 0.7f;
|
||||
auto butt_size = header_rec.w - padding * 2.f;
|
||||
grab_rec = { header_rec.pos, { header_rec.z - header_rec.w * 4, header_rec.w } };
|
||||
mPinButton.mRect = { { grab_rec.pos.x + grab_rec.size.x + padding, grab_rec.y + padding }, butt_size };
|
||||
mMinButton.mRect = { { mPinButton.mRect.pos.x + mPinButton.mRect.size.x + padding * 2, mPinButton.mRect.y }, butt_size };
|
||||
mMaxButton.mRect = { { mMinButton.mRect.pos.x + mMinButton.mRect.size.x + padding * 2, mPinButton.mRect.y }, butt_size };
|
||||
mExitButton.mRect = { { mMaxButton.mRect.pos.x + mMaxButton.mRect.size.x + padding * 2, mPinButton.mRect.y }, butt_size };
|
||||
|
||||
mPinButton.mCol = { 0.3f, 0.3f, 0.3f, 0.9f};
|
||||
mMinButton.mCol = { 0.3f, 0.3f, 0.8f, 0.9f };
|
||||
mMaxButton.mCol = { 0.3f, 0.8f, 0.3f, 0.9f };
|
||||
mExitButton.mCol = { 0.8f, 0.3f, 0.3f, 0.9f };
|
||||
}
|
||||
|
||||
void WindowsHeaderWidget::draw(glw::Canvas& canvas) {
|
||||
updRecs();
|
||||
canvas.setCol1(col);
|
||||
canvas.rect(header_rec, 1.f);
|
||||
canvas.setCol1(1.f);
|
||||
canvas.text("MemLeaks", grab_rec, 4.f);
|
||||
|
||||
mExitButton.draw(canvas);
|
||||
mMaxButton.draw(canvas);
|
||||
mMinButton.draw(canvas);
|
||||
mPinButton.draw(canvas);
|
||||
}
|
||||
|
||||
void WindowsHeaderWidget::proc(glw::Window& window, glw::WindowSimpleInputs& inputs) {
|
||||
get_time();
|
||||
|
||||
mExitButton.proc(inputs);
|
||||
mMaxButton.proc(inputs);
|
||||
mMinButton.proc(inputs);
|
||||
mPinButton.proc(inputs);
|
||||
|
||||
window.mAppearence.mMinMaxBox = mMaxButton.mRect * inputs.mScaleVal;
|
||||
window.mAppearence.mCaptionsAddArea = { grab_rec * inputs.mScaleVal };
|
||||
window.mAppearence.mMinimized = mMinButton.mPressed;
|
||||
window.mEvents.mClose = mExitButton.mPressed;
|
||||
window.mAppearence.mTopZ = mPinButton.mValue;
|
||||
}
|
||||
216
.outdated/graphics/src/texture.cpp
Normal file
216
.outdated/graphics/src/texture.cpp
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
|
||||
#include "texture.h"
|
||||
|
||||
#include "map.h"
|
||||
|
||||
#include "stringt.h"
|
||||
|
||||
#include "shader.h"
|
||||
|
||||
#include "GraphicsLibApi.h"
|
||||
|
||||
const char* texture_vertex =
|
||||
#ifdef ENV_OS_ANDROID
|
||||
"#version 300 es\n"
|
||||
"precision mediump float;\n"
|
||||
#else
|
||||
"#version 330 core\n"
|
||||
#endif
|
||||
"layout(location = 0) in vec3 vPos;\n"
|
||||
"out vec2 UV;\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = vec4(vPos, 1);\n"
|
||||
" UV = (vPos.xy + vec2(1, 1)) / 2.0;\n"
|
||||
"}\n";
|
||||
|
||||
const char* texture_fragment =
|
||||
#ifdef ENV_OS_ANDROID
|
||||
"#version 300 es\n"
|
||||
"precision mediump float;\n"
|
||||
#else
|
||||
"#version 330 core\n"
|
||||
#endif
|
||||
"in vec2 UV;\n"
|
||||
"out vec4 color;\n"
|
||||
"uniform sampler2D renderedTexture;\n"
|
||||
"uniform float time;\n"
|
||||
"void main() {\n"
|
||||
" vec4 texColor = texture(renderedTexture, UV);\n"
|
||||
" if (texColor.a < 0.2)\n"
|
||||
" discard;\n"
|
||||
" color = texColor;\n"
|
||||
"}\n";
|
||||
|
||||
namespace tp {
|
||||
|
||||
using namespace glw;
|
||||
|
||||
GLuint texture::getid() { return id; }
|
||||
|
||||
texture::texture() {
|
||||
glGenTextures(1, &id);
|
||||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
texture::~texture() { glDeleteTextures(1, &id); }
|
||||
|
||||
alni texture::sizeAllocatedMem() {
|
||||
return sizeof(GLuint);
|
||||
}
|
||||
|
||||
alni texture::sizeUsedMem() {
|
||||
return sizeof(GLuint);
|
||||
}
|
||||
|
||||
|
||||
void texture::update(const Array2D<rgba>& buff) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)buff.size().x, (GLsizei)buff.size().y, 0, GL_RGBA, GL_FLOAT, buff.buff());
|
||||
}
|
||||
|
||||
void texture::draw(const GLuint& out) {
|
||||
draw_texture(out, id);
|
||||
}
|
||||
|
||||
|
||||
struct texture_drawer_data {
|
||||
|
||||
HashMap<GLuint, string> textures;
|
||||
|
||||
GLuint quad_VertexArrayID;
|
||||
GLuint quad_vertexbuffer;
|
||||
GLuint texID;
|
||||
glw::shader shader;
|
||||
|
||||
const GLfloat g_quad_vertex_buffer_data[18] = {
|
||||
-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f,
|
||||
-1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
|
||||
};
|
||||
|
||||
texture_drawer_data() : shader(texture_vertex, NULL, texture_fragment, false) {
|
||||
// The fullscreen quad's FBO
|
||||
glGenVertexArrays(1, &quad_VertexArrayID);
|
||||
glBindVertexArray(quad_VertexArrayID);
|
||||
|
||||
glGenBuffers(1, &quad_vertexbuffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data),
|
||||
g_quad_vertex_buffer_data, GL_STATIC_DRAW);
|
||||
|
||||
texID = shader.getu("renderedTexture");
|
||||
}
|
||||
|
||||
~texture_drawer_data() {
|
||||
glDeleteBuffers(1, &quad_vertexbuffer);
|
||||
glDeleteVertexArrays(1, &quad_VertexArrayID);
|
||||
|
||||
for (auto tex : textures) {
|
||||
glDeleteTextures(1, &tex->val);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
texture_drawer_data* texdd = NULL;
|
||||
|
||||
void texture::init() {
|
||||
if (!texdd) texdd = new texture_drawer_data();
|
||||
}
|
||||
|
||||
void texture::deinit() {
|
||||
if (texdd) delete texdd;
|
||||
texdd = NULL;
|
||||
}
|
||||
|
||||
void texture::draw_texture(uint4 out, uint4 in) {
|
||||
assert(in);
|
||||
|
||||
// Render to the screen
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, out);
|
||||
|
||||
// Use our shader
|
||||
texdd->shader.bind();
|
||||
|
||||
// Bind our texture in Texture Unit 0
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, in);
|
||||
// Set our "renderedTexture" sampler to use Texture Unit 0
|
||||
glUniform1i(texdd->texID, 0);
|
||||
|
||||
// glUniformMatrix4fv(texdd->rect_mat, 1, GL_FALSE, &tmat[0][0]);
|
||||
|
||||
// 1rst attribute buffer : vertices
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, texdd->quad_vertexbuffer);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
|
||||
|
||||
// Draw the triangles. 2*3 indices starting at 0 -> 2 triangles
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
glDisableVertexAttribArray(0);
|
||||
|
||||
texdd->shader.unbind();
|
||||
}
|
||||
|
||||
GLuint load_texture(string name) {
|
||||
GLuint tex_2d = 0;
|
||||
RelAssert(0 && "incomplete compilation - no SOIL support added");
|
||||
|
||||
if (0) {
|
||||
//auto document = lunasvg::Document::loadFromFile("tiger.svg");
|
||||
//auto bitmap = document->renderToBitmap();
|
||||
}
|
||||
else {
|
||||
/*
|
||||
tex_2d = SOIL_load_OGL_texture(
|
||||
name.cstr(), SOIL_LOAD_RGBA, SOIL_CREATE_NEW_ID,
|
||||
SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB |
|
||||
SOIL_FLAG_COMPRESS_TO_DXT);
|
||||
|
||||
if (0 == tex_2d) {
|
||||
printf("SOIL loading error: '%s'\n", SOIL_last_result());
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
return tex_2d;
|
||||
}
|
||||
|
||||
GLuint texture::get_tex(const char* TexId) {
|
||||
GLuint out = 0;
|
||||
alni idx = texdd->textures.presents(TexId);
|
||||
if (idx != -1) {
|
||||
out = texdd->textures.get(TexId);
|
||||
}
|
||||
else {
|
||||
out = load_texture(TexId);
|
||||
texdd->textures.put(TexId, out);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void texture::drawCurcle(vec2f pos, double radius, rgba col) {
|
||||
#ifndef ENV_OS_ANDROID
|
||||
static alni precision = 40;
|
||||
|
||||
glColor4f(col.r, col.g, col.b, col.a);
|
||||
|
||||
double twicePi = 2.0 * 3.142;
|
||||
|
||||
glBegin(GL_TRIANGLE_FAN); // BEGIN CIRCLE
|
||||
glVertex2f(pos.x, pos.y); // center of circle
|
||||
|
||||
for (alni i = 0; i <= precision; i++) {
|
||||
glVertex2f((GLfloat)(pos.x + (radius * cos(i * twicePi / precision))),
|
||||
(GLfloat)(pos.y + (radius * sin(i * twicePi / precision))));
|
||||
}
|
||||
glEnd(); // END
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
BIN
.outdated/graphics/src/windows_window.cpp
Normal file
BIN
.outdated/graphics/src/windows_window.cpp
Normal file
Binary file not shown.
107
.outdated/graphics/tests/tests.cpp
Normal file
107
.outdated/graphics/tests/tests.cpp
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
|
||||
#include "SimpleGui.h"
|
||||
#include "debugui.h"
|
||||
#include "texture.h"
|
||||
#include "timer.h"
|
||||
#include "imgui.h"
|
||||
|
||||
struct CollorWheelWidget {
|
||||
tp::rgba col = { 0.3f, 0.3f, 0.3f, 0.9f };
|
||||
tp::rectf rec = { 10, 30, 40, 40 };
|
||||
|
||||
void draw(tp::glw::Canvas& canvas) {
|
||||
canvas.setCol1(col);
|
||||
canvas.rect(rec, 3.f);
|
||||
canvas.drawColorwheel(rec, col.rgbs);
|
||||
}
|
||||
};
|
||||
|
||||
struct Test {
|
||||
|
||||
tp::glw::Window window;
|
||||
tp::glw::DebugUI ui;
|
||||
tp::glw::Canvas canvas;
|
||||
tp::glw::WindowsHeaderWidget header;
|
||||
tp::glw::WindowSimpleInputs inputs;
|
||||
tp::halnf mHeaderHeight = 6.5f;
|
||||
|
||||
CollorWheelWidget colorwheel;
|
||||
tp::halnf uiscale = 1.f;
|
||||
tp::Timer time;
|
||||
tp::halni frames = 0;
|
||||
tp::halni fps = 0;
|
||||
|
||||
Test() : window(), ui(window, debuguiCallBack, this), time(1000) {
|
||||
tp::glw::texture::init();
|
||||
canvas.setCol1({ 0.5f, 0.5f, 0.5f, 0.5f });
|
||||
window.mAppearence.mHiden = false;
|
||||
}
|
||||
|
||||
void proc() {
|
||||
window.pollEvents();
|
||||
inputs.update(window, uiscale);
|
||||
|
||||
header.header_rec = { (inputs.mWindowSizeMM.x - 60.f) / 2.f, 3.f, 60.f, mHeaderHeight };
|
||||
header.proc(window, inputs);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
// window frame
|
||||
window.beginDraw(); {
|
||||
// canvas draw
|
||||
canvas.beginDraw({ { 0, 0 }, inputs.mWindowSizeMM }, window.mDevice.mDPMM, uiscale); {
|
||||
canvas.clear();
|
||||
header.draw(canvas);
|
||||
colorwheel.draw(canvas);
|
||||
} canvas.endDraw();
|
||||
// debug draw
|
||||
ui.drawDebugUI(window.mDevice.mDPMM);
|
||||
} window.endDraw();
|
||||
}
|
||||
|
||||
void run() {
|
||||
while (!window.mEvents.mClose) {
|
||||
proc();
|
||||
if (window.mEvents.mRedraw || tp::glw::gInTransition) {
|
||||
draw();
|
||||
}
|
||||
if (time.isTimeout()) {
|
||||
fps = frames;
|
||||
frames = 0;
|
||||
time.reset();
|
||||
}
|
||||
frames++;
|
||||
}
|
||||
}
|
||||
|
||||
void debugui() {
|
||||
static char buff[100];
|
||||
ImGui::DragFloat("UI SCale", &uiscale, 0.02);
|
||||
ImGui::Text("Fps: %i", fps);
|
||||
ImGui::InputText("Fps: %i", buff, 100);
|
||||
}
|
||||
|
||||
static void debuguiCallBack(void* self) {
|
||||
((Test*)self)->debugui();
|
||||
}
|
||||
|
||||
~Test() {
|
||||
tp::glw::texture::deinit();
|
||||
}
|
||||
};
|
||||
|
||||
CROSSPLATFORM_MAIN
|
||||
int main() {
|
||||
tp::ModuleManifest* ModuleDependencies[] = { &tp::gModuleGlw, NULL };
|
||||
tp::ModuleManifest TestModule("Test", NULL, NULL, ModuleDependencies);
|
||||
if (!TestModule.initialize()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
Test test;
|
||||
test.run();
|
||||
}
|
||||
|
||||
TestModule.deinitialize();
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.2)
|
|||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
project(Allocator)
|
||||
project(Allocators)
|
||||
|
||||
### ---------------------- Static Library --------------------- ###
|
||||
file(GLOB SOURCES "./private/*.cpp")
|
||||
|
|
|
|||
|
|
@ -3,8 +3,12 @@
|
|||
|
||||
#include <cstdlib>
|
||||
|
||||
static tp::ModuleManifest* sModuleDependencies[] = { &tp::gModuleBase, nullptr };
|
||||
tp::ModuleManifest tp::gModuleAllocators = ModuleManifest("Allocators", nullptr, nullptr, sModuleDependencies);
|
||||
static void deinit(const tp::ModuleManifest* self) {
|
||||
tp::HeapAllocGlobal::checkLeaks();
|
||||
}
|
||||
|
||||
static tp::ModuleManifest* sModuleDependencies[] = { &tp::gModuleUtils, nullptr };
|
||||
tp::ModuleManifest tp::gModuleAllocators = ModuleManifest("Allocators", nullptr, deinit, sModuleDependencies);
|
||||
|
||||
|
||||
void* operator new(size_t aSize) { return tp::HeapAllocGlobal::allocate(aSize); }
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "Utils.hpp"
|
||||
#include "Debugging.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
using namespace tp;
|
||||
|
|
@ -22,6 +23,8 @@ HeapAllocGlobal::~HeapAllocGlobal() = default;
|
|||
|
||||
tp::MemHead* tp::HeapAllocGlobal::mEntry = nullptr;
|
||||
tp::ualni tp::HeapAllocGlobal::mNumAllocations = 0;
|
||||
tp::Mutex tp::HeapAllocGlobal::mMutex;
|
||||
bool tp::HeapAllocGlobal::mIgnore;
|
||||
|
||||
// ----------------------- Debug Implementation ---------------------------- //
|
||||
// |----------------|
|
||||
|
|
@ -38,7 +41,8 @@ namespace tp {
|
|||
struct MemHead {
|
||||
MemHead* mPrev;
|
||||
MemHead* mNext;
|
||||
ualni mBlockSize;
|
||||
uhalni mBlockSize;
|
||||
uhalni mIgnored;
|
||||
#ifdef MEM_STACK_TRACE
|
||||
const CallStackCapture::CallStack* mCallStack;
|
||||
#endif
|
||||
|
|
@ -63,18 +67,25 @@ void* HeapAllocGlobal::allocate(ualni aBlockSize) {
|
|||
}
|
||||
|
||||
// 1) Allocate the block
|
||||
ALLOCATE:
|
||||
auto head = (MemHead*)malloc(aBlockSize + WRAP_SIZE * 2 + HEAD_SIZE);
|
||||
if (!head) {
|
||||
printf("WARNING : Cant allocate memory. Trying again\n");
|
||||
goto ALLOCATE; // Just freeze if no memory is available
|
||||
}
|
||||
|
||||
auto wrap_top = (int1*)(head + 1);
|
||||
auto data = wrap_top + WRAP_SIZE;
|
||||
auto wrap_bottom = data + aBlockSize;
|
||||
|
||||
if (!head) { return nullptr; }
|
||||
head->mBlockSize = aBlockSize;
|
||||
head->mIgnored = mIgnore;
|
||||
|
||||
// 2) Link with existing blocks
|
||||
mMutex.lock();
|
||||
mNumAllocations++;
|
||||
if (mEntry) {
|
||||
DEBUG_ASSERT(!mEntry->mNext)
|
||||
DEBUG_ASSERT(mEntry->mNext == nullptr)
|
||||
head->mNext = nullptr;
|
||||
head->mPrev = mEntry;
|
||||
mEntry->mNext = head;
|
||||
|
|
@ -84,15 +95,18 @@ void* HeapAllocGlobal::allocate(ualni aBlockSize) {
|
|||
}
|
||||
mEntry = head;
|
||||
|
||||
// 3) Wrap fill
|
||||
memSetVal(wrap_top, WRAP_SIZE, WRAP_VAL);
|
||||
memSetVal(wrap_bottom, WRAP_SIZE, WRAP_VAL);
|
||||
|
||||
// 4) Trace the stack
|
||||
// 3) Trace the stack
|
||||
#ifdef MEM_STACK_TRACE
|
||||
head->mCallStack = gCSCapture->getSnapshot();
|
||||
#endif
|
||||
|
||||
mMutex.unlock();
|
||||
|
||||
// 4) Wrap fill
|
||||
memSetVal(wrap_top, WRAP_SIZE, WRAP_VAL);
|
||||
memSetVal(wrap_bottom, WRAP_SIZE, WRAP_VAL);
|
||||
|
||||
// 5) clear data
|
||||
#ifdef MEM_CLEAR_ON_ALLOC
|
||||
memSetVal(data, aBlockSize, CLEAR_ALLOC_VAL);
|
||||
|
|
@ -102,6 +116,8 @@ void* HeapAllocGlobal::allocate(ualni aBlockSize) {
|
|||
}
|
||||
|
||||
void HeapAllocGlobal::deallocate(void* aPtr) {
|
||||
if (!aPtr) return;
|
||||
|
||||
// 1) Restore the pointers
|
||||
auto head = ((MemHead*)((int1*)aPtr - WRAP_SIZE)) - 1;
|
||||
auto wrap_top = (int1*)(head + 1);
|
||||
|
|
@ -109,6 +125,7 @@ void HeapAllocGlobal::deallocate(void* aPtr) {
|
|||
auto wrap_bottom = data + head->mBlockSize;
|
||||
|
||||
// 2) Unlink with blocks
|
||||
mMutex.lock();
|
||||
mNumAllocations--;
|
||||
DEBUG_ASSERT(!mEntry->mNext)
|
||||
if (head->mNext) head->mNext->mPrev = head->mPrev;
|
||||
|
|
@ -116,34 +133,65 @@ void HeapAllocGlobal::deallocate(void* aPtr) {
|
|||
if (head == mEntry) {
|
||||
mEntry = head->mPrev;
|
||||
}
|
||||
mMutex.unlock();
|
||||
|
||||
if (!head->mIgnored) {
|
||||
// 3) Check the wrap
|
||||
ASSERT(!memCompareVal(wrap_top, WRAP_SIZE, WRAP_VAL) && "Allocated Block Wrap Corrupted!")
|
||||
ASSERT(!memCompareVal(wrap_bottom, WRAP_SIZE, WRAP_VAL) && "Allocated Block Wrap Corrupted!")
|
||||
if (memCompareVal(wrap_top, WRAP_SIZE, WRAP_VAL)) {
|
||||
CallStackCapture::printSnapshot(head->mCallStack);
|
||||
ASSERT(!"Allocated Block Wrap Corrupted!")
|
||||
}
|
||||
|
||||
if (memCompareVal(wrap_bottom, WRAP_SIZE, WRAP_VAL)) {
|
||||
CallStackCapture::printSnapshot(head->mCallStack);
|
||||
ASSERT(!"Allocated Block Wrap Corrupted!")
|
||||
}
|
||||
|
||||
// 4) clear data
|
||||
#ifdef MEM_CLEAR_ON_ALLOC
|
||||
#ifdef MEM_CLEAR_ON_ALLOC
|
||||
memSetVal(data, head->mBlockSize, CLEAR_DEALLOC_VAL);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
// 5) free the block
|
||||
free(head);
|
||||
}
|
||||
|
||||
bool HeapAllocGlobal::checkLeaks() {
|
||||
ualni ignoredCount = 0;
|
||||
for (auto iter = mEntry; iter; iter = iter->mPrev) {
|
||||
ignoredCount += iter->mIgnored;
|
||||
}
|
||||
|
||||
// 1) Check for not deallocated memory
|
||||
if (mNumAllocations) {
|
||||
if (mNumAllocations && ignoredCount < mNumAllocations) {
|
||||
|
||||
#ifdef MEM_STACK_TRACE
|
||||
gCSCapture->logLeaks();
|
||||
for (auto iter = mEntry; iter; iter = iter->mPrev) {
|
||||
if (!iter->mIgnored) CallStackCapture::printSnapshot(iter->mCallStack);
|
||||
}
|
||||
#endif
|
||||
|
||||
DEBUG_BREAK("Destruction of not freed Allocator")
|
||||
printf(" Count : %llu", mNumAllocations - ignoredCount);
|
||||
|
||||
ASSERT(!"Destruction of not freed Allocator")
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void HeapAllocGlobal::startIgnore() {
|
||||
mMutex.lock();
|
||||
mIgnore = true;
|
||||
mMutex.unlock();
|
||||
}
|
||||
|
||||
void HeapAllocGlobal::stopIgnore() {
|
||||
mMutex.lock();
|
||||
mIgnore = false;
|
||||
mMutex.unlock();
|
||||
}
|
||||
|
||||
HeapAllocGlobal::~HeapAllocGlobal() = default;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "Module.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#include "HeapAllocatorGlobal.hpp"
|
||||
#include "HeapAllocator.hpp"
|
||||
|
|
@ -11,8 +11,6 @@ namespace tp {
|
|||
extern ModuleManifest gModuleAllocators;
|
||||
}
|
||||
|
||||
inline void* operator new(std::size_t aSize, void* aWhere) noexcept { return aWhere; }
|
||||
|
||||
void* operator new(std::size_t aSize);
|
||||
void* operator new[](std::size_t aSize);
|
||||
void operator delete(void* aPtr) noexcept;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
* 2) updating list entry to that block.
|
||||
*/
|
||||
|
||||
#include "HeapAllocatorGlobal.hpp"
|
||||
#include "Environment.hpp"
|
||||
#include "PrivateConfig.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "Module.hpp"
|
||||
#include "Multithreading.hpp"
|
||||
|
||||
namespace tp {
|
||||
|
||||
|
|
@ -9,6 +10,8 @@ namespace tp {
|
|||
#ifdef MEM_DEBUG
|
||||
static ualni mNumAllocations;
|
||||
static struct MemHead* mEntry;
|
||||
static Mutex mMutex;
|
||||
static bool mIgnore;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
|
@ -20,6 +23,9 @@ namespace tp {
|
|||
static void deallocate(void* aPtr);
|
||||
|
||||
static bool checkLeaks();
|
||||
static void startIgnore();
|
||||
static void stopIgnore();
|
||||
|
||||
public:
|
||||
[[nodiscard]] bool checkWrap() const { return false; }
|
||||
void checkValid() {}
|
||||
|
|
|
|||
6
Allocators/public/NewPlacement.hpp
Normal file
6
Allocators/public/NewPlacement.hpp
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "Common.hpp"
|
||||
|
||||
inline void* operator new(std::size_t aSize, void* aWhere) noexcept { return aWhere; }
|
||||
inline void* operator new[](std::size_t aSize, void* aWhere) noexcept { return aWhere; }
|
||||
|
|
@ -10,8 +10,19 @@ project(Types)
|
|||
|
||||
add_compile_definitions(MEM_DEBUG)
|
||||
|
||||
set(EXTERNALS ../Externals)
|
||||
|
||||
add_subdirectory(Modules)
|
||||
add_subdirectory(Utils)
|
||||
add_subdirectory(Containers)
|
||||
add_subdirectory(Math)
|
||||
add_subdirectory(Allocators)
|
||||
add_subdirectory(Strings)
|
||||
add_subdirectory(Tokenizer)
|
||||
add_subdirectory(Parser)
|
||||
add_subdirectory(CommandLine)
|
||||
add_subdirectory(Externals)
|
||||
add_subdirectory(Connection)
|
||||
add_subdirectory(Graphics)
|
||||
add_subdirectory(Objects)
|
||||
add_subdirectory(Chat)
|
||||
|
|
|
|||
15
CMakeSettings.json
Normal file
15
CMakeSettings.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "x64-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
33
Chat/CMakeLists.txt
Normal file
33
Chat/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
project(Chat)
|
||||
|
||||
### ---------------------- Externals --------------------- ###
|
||||
set(BINDINGS_INCLUDE ${EXTERNALS}/glfw/include ${EXTERNALS}/glew/include)
|
||||
set(BINDINGS_LIBS glfw glew_s Imgui Nanovg)
|
||||
|
||||
### ---------------------- Static Library --------------------- ###
|
||||
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
|
||||
file(GLOB HEADERS "./public/*.hpp")
|
||||
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${BINDINGS_INCLUDE})
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Graphics Connection)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${BINDINGS_LIBS})
|
||||
|
||||
### -------------------------- Examples -------------------------- ###
|
||||
add_executable(ChatGUI applications/ChatGUI.cpp)
|
||||
target_link_libraries(ChatGUI ${PROJECT_NAME} ${BINDINGS_LIBS})
|
||||
target_include_directories(ChatGUI PRIVATE ${BINDINGS_INCLUDE})
|
||||
|
||||
### -------------------------- Tests -------------------------- ###
|
||||
enable_testing()
|
||||
file(GLOB TEST_SOURCES "./tests/*.cpp")
|
||||
add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES})
|
||||
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Utils)
|
||||
add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests)
|
||||
|
||||
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/lib)
|
||||
41
Chat/applications/ChatGUI.cpp
Normal file
41
Chat/applications/ChatGUI.cpp
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
#include "NewPlacement.hpp"
|
||||
|
||||
#include "ClientGui.hpp"
|
||||
#include "Window.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
int main() {
|
||||
|
||||
ModuleManifest* deps[] = { &tp::gModuleChat, nullptr };
|
||||
ModuleManifest testModule("ClientGUI", nullptr, nullptr, deps);
|
||||
|
||||
if (!testModule.initialize()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
ChatAPI chat;
|
||||
ClientGUI gui;
|
||||
|
||||
auto window = Window::createWindow(1000, 700, "Window 1");
|
||||
|
||||
if (window) {
|
||||
|
||||
window->getGraphics().getDebugGui().setFontSize(4);
|
||||
|
||||
while (!window->shouldClose()) {
|
||||
window->processEvents();
|
||||
|
||||
gui.draw(chat);
|
||||
|
||||
window->draw();
|
||||
}
|
||||
}
|
||||
|
||||
Window::destroyWindow(window);
|
||||
}
|
||||
|
||||
testModule.deinitialize();
|
||||
}
|
||||
51
Chat/private/Chat.cpp
Normal file
51
Chat/private/Chat.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
#include "NewPlacement.hpp"
|
||||
|
||||
#include "Chat.hpp"
|
||||
|
||||
#include "Graphics.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
static ModuleManifest* deps[] = { &gModuleGraphics, nullptr };
|
||||
|
||||
ModuleManifest tp::gModuleChat = ModuleManifest("Chat", nullptr, nullptr, deps );
|
||||
|
||||
bool ChatAPI::isLogged() const {
|
||||
return mLogged;
|
||||
}
|
||||
|
||||
void ChatAPI::login(const Credentials& credentials) {
|
||||
mLogged = String::Logic::isEqualLogic(credentials.pass, "1812") && String::Logic::isEqualLogic(credentials.name, "Igor");
|
||||
mChatsList = { "Serg", "Friends" };
|
||||
mChatHistories.put("Serg", { { "Serg", "Hello wanna some coke-cola?" }, { "Serg", "Will be in 5 mins" } });
|
||||
mChatHistories.put("Friends", { { "Artem", "Whos is that Serg?" }, { "Erog", "idunno" } });
|
||||
}
|
||||
|
||||
void ChatAPI::logout() {
|
||||
mLogged = false;
|
||||
mChatsList.removeAll();
|
||||
mChatHistories.removeAll();
|
||||
}
|
||||
|
||||
const ChatAPI::ChatsList* ChatAPI::getChatsList() const {
|
||||
return mLogged ? &mChatsList : nullptr;
|
||||
}
|
||||
|
||||
const ChatAPI::ChatHistory* ChatAPI::getChatHistory(const String& chatName) const {
|
||||
if (!mLogged) return nullptr;
|
||||
|
||||
auto history = mChatHistories.presents(chatName);
|
||||
return history ? &mChatHistories.getSlotVal(history) : nullptr;
|
||||
}
|
||||
|
||||
void ChatAPI::send(const String& chatName, const Message& message) {
|
||||
if (!mLogged) return;
|
||||
|
||||
auto iter = mChatHistories.presents(chatName);
|
||||
auto history = iter ? &mChatHistories.getSlotVal(iter) : nullptr;
|
||||
|
||||
if (!history) return;
|
||||
|
||||
history->pushBack(message);
|
||||
}
|
||||
89
Chat/private/ClientGUI.cpp
Normal file
89
Chat/private/ClientGUI.cpp
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
|
||||
#include "ClientGui.hpp"
|
||||
#include "imgui.h"
|
||||
#include "imgui_internal.h"
|
||||
|
||||
using namespace tp;
|
||||
using namespace ImGui;
|
||||
|
||||
void ClientGUI::draw(ChatAPI& api) {
|
||||
DockSpaceOverViewport(GetWindowViewport());
|
||||
|
||||
if (api.isLogged()) {
|
||||
drawChat(api);
|
||||
|
||||
} else {
|
||||
if (Begin("Authentication")) {
|
||||
InputText("Name", mCredentials.name, ChatAPI::Credentials::SIZE);
|
||||
InputText("Pass", mCredentials.pass, ChatAPI::Credentials::SIZE);
|
||||
|
||||
if (mInvalidCredentials) {
|
||||
Text("Invalid Credentials");
|
||||
}
|
||||
|
||||
if (Button("Login")) {
|
||||
api.login(mCredentials);
|
||||
mInvalidCredentials = !api.isLogged();
|
||||
}
|
||||
}
|
||||
End();
|
||||
}
|
||||
}
|
||||
|
||||
void ClientGUI::drawChat(tp::ChatAPI& api) {
|
||||
if (Begin("Chats")) {
|
||||
if (Button("Logout", {GetContentRegionAvail().x, 0})) {
|
||||
api.logout();
|
||||
mCredentials.pass[0] = 0;
|
||||
mActiveChatName = "Not Selected";
|
||||
}
|
||||
|
||||
if (BeginListBox("##chats", GetContentRegionAvail())) {
|
||||
auto chats = api.getChatsList();
|
||||
if (chats) {
|
||||
for (auto user : *chats) {
|
||||
if (Selectable(user->read())) {
|
||||
mActiveChatName = user.data();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Text("Error");
|
||||
}
|
||||
|
||||
EndListBox();
|
||||
}
|
||||
}
|
||||
End();
|
||||
|
||||
if (Begin("History")) {
|
||||
Text("%s", mActiveChatName.read());
|
||||
|
||||
auto history = api.getChatHistory(mActiveChatName);
|
||||
|
||||
if (history) {
|
||||
if (BeginListBox("##History", GetContentRegionAvail())) {
|
||||
for (auto message : *history) {
|
||||
Text("%s : %s", message->user.read(), message->text.read());
|
||||
Separator();
|
||||
}
|
||||
}
|
||||
|
||||
EndListBox();
|
||||
} else {
|
||||
Text("No History");
|
||||
}
|
||||
}
|
||||
End();
|
||||
|
||||
if (Begin("Message")) {
|
||||
if (Button("Send")) {
|
||||
if (String::Logic::calcLength(mMessageBuff) > 0) {
|
||||
api.send(mActiveChatName, {mCredentials.name, mMessageBuff});
|
||||
}
|
||||
mMessageBuff[0] = 0;
|
||||
}
|
||||
|
||||
InputTextMultiline("##Message", mMessageBuff, MESSAGE_SIZE, GetContentRegionAvail());
|
||||
}
|
||||
End();
|
||||
}
|
||||
45
Chat/public/Chat.hpp
Normal file
45
Chat/public/Chat.hpp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
#include "Strings.hpp"
|
||||
#include "Map.hpp"
|
||||
#include "List.hpp"
|
||||
|
||||
namespace tp {
|
||||
|
||||
extern ModuleManifest gModuleChat;
|
||||
|
||||
class ChatAPI {
|
||||
public:
|
||||
struct Credentials {
|
||||
enum { SIZE = 64 };
|
||||
tp::int1 name[SIZE] {0};
|
||||
tp::int1 pass[SIZE] {0};
|
||||
};
|
||||
|
||||
typedef List<String> ChatsList;
|
||||
|
||||
struct Message {
|
||||
String user;
|
||||
String text;
|
||||
};
|
||||
|
||||
typedef List<Message> ChatHistory;
|
||||
|
||||
public:
|
||||
ChatAPI() = default;
|
||||
[[nodiscard]] bool isLogged() const;
|
||||
void login(const Credentials& credentials);
|
||||
[[nodiscard]] const ChatsList* getChatsList() const;
|
||||
[[nodiscard]] const ChatHistory* getChatHistory(const String& chatName) const;
|
||||
void logout();
|
||||
void send(const String& chatName, const Message& message);
|
||||
|
||||
private:
|
||||
bool mLogged = false;
|
||||
Credentials mCredentials;
|
||||
ChatsList mChatsList;
|
||||
|
||||
Map<String, ChatHistory> mChatHistories;
|
||||
};
|
||||
}
|
||||
|
||||
20
Chat/public/ClientGui.hpp
Normal file
20
Chat/public/ClientGui.hpp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include "Chat.hpp"
|
||||
|
||||
namespace tp {
|
||||
class ClientGUI {
|
||||
enum { MESSAGE_SIZE = 1024 };
|
||||
ChatAPI::Credentials mCredentials;
|
||||
bool mInvalidCredentials = false;
|
||||
char mMessageBuff[1000] {0};
|
||||
String mActiveChatName = "Not Selected";
|
||||
|
||||
public:
|
||||
ClientGUI() = default;
|
||||
void draw(ChatAPI& api);
|
||||
|
||||
private:
|
||||
void drawChat(ChatAPI& api);
|
||||
};
|
||||
}
|
||||
4
Chat/tests/Tests.cpp
Normal file
4
Chat/tests/Tests.cpp
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
int main () {
|
||||
|
||||
}
|
||||
22
CommandLine/CMakeLists.txt
Normal file
22
CommandLine/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
project(CommandLine)
|
||||
|
||||
### ---------------------- Static Library --------------------- ###
|
||||
file(GLOB SOURCES "./private/*.cpp")
|
||||
file(GLOB HEADERS "./public/*.hpp")
|
||||
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Tokenizer Connection)
|
||||
|
||||
### -------------------------- Tests -------------------------- ###
|
||||
enable_testing()
|
||||
file(GLOB TEST_SOURCES "./tests/*.cpp")
|
||||
add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES})
|
||||
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Utils)
|
||||
add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests)
|
||||
|
||||
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/lib)
|
||||
122
CommandLine/private/CmdLineInterpreter.cpp
Normal file
122
CommandLine/private/CmdLineInterpreter.cpp
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
#include "NewPlacement.hpp"
|
||||
|
||||
#include "CmdLineInterpreter.hpp"
|
||||
|
||||
#define MAX_LINE_LENGTH 1024
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
using namespace tp;
|
||||
|
||||
static bool helpFunction(CmdLineInterpreter* self, const CommandLine& args) {
|
||||
self->help(args);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CmdLineInterpreter::help(const CommandLine& args) const {
|
||||
auto commandName = args.getString("CommandName");
|
||||
auto allCommands = commandName == "_none_";
|
||||
|
||||
if (allCommands) {
|
||||
printf("Commands:\n");
|
||||
for (auto command : mCommands) {
|
||||
printf(" %s\n", command->key.read());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto idx = mCommands.presents(commandName);
|
||||
if (!idx) {
|
||||
printf("Command '%s' not found\n", commandName.read());
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Command '%s'\n", commandName.read());
|
||||
auto command = &mCommands.getSlotVal(idx);
|
||||
command->args->help();
|
||||
}
|
||||
|
||||
CmdLineInterpreter::CmdLineInterpreter() {
|
||||
auto helpArgs = new CommandLine{
|
||||
{ "CommandName", "_none_" }
|
||||
};
|
||||
|
||||
addCommand("help", helpArgs, (CommandFunction) helpFunction, this);
|
||||
}
|
||||
|
||||
|
||||
void CmdLineInterpreter::addCommand(const String& id, CommandLine* args, CommandFunction function, void* customData) {
|
||||
ASSERT(!mCommands.presents(id))
|
||||
mCommands.put(id, { args, function, customData });
|
||||
}
|
||||
|
||||
void CmdLineInterpreter::run() {
|
||||
char buffer[MAX_LINE_LENGTH];
|
||||
printf("Command Line Interpreter (or type 'exit' to quit):\n");
|
||||
|
||||
while (true) {
|
||||
printf("%s >> ", mName.read());
|
||||
|
||||
// Read input from the user
|
||||
if (fgets(buffer, MAX_LINE_LENGTH, stdin) == nullptr) {
|
||||
printf("Error reading input.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the trailing newline character if it exists
|
||||
auto length = strlen(buffer);
|
||||
if (length > 0 && buffer[length - 1] == '\n') {
|
||||
buffer[length - 1] = '\0';
|
||||
}
|
||||
|
||||
// Check if the user wants to exit
|
||||
if (strcmp(buffer, "exit") == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Process the input here
|
||||
processCommand(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool CmdLineInterpreter::processCommand(int1* commandString) {
|
||||
ualni commandLen = 0;
|
||||
for (auto i = commandString; *i != 0; i++) {
|
||||
if (*i == ' ') break;
|
||||
commandLen++;
|
||||
}
|
||||
|
||||
commandString[commandLen] = 0;
|
||||
auto args = commandString + commandLen + 1;
|
||||
|
||||
auto idx = mCommands.presents(commandString);
|
||||
if (!idx) {
|
||||
printf("ERROR: Command '%s' is not found\n", commandString);
|
||||
printf("Please execute 'help' for more information\n\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
auto command = &mCommands.getSlotVal(idx);
|
||||
|
||||
command->args->parse(args);
|
||||
|
||||
if (command->args->mError) {
|
||||
printf("ERROR: Command call '%s' has invalid arguments\n", commandString);
|
||||
command->args->resetError();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!command->function(command->customData, *command->args)) {
|
||||
printf("ERROR: Command call '%s' failed\n", commandString);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CmdLineInterpreter::~CmdLineInterpreter() {
|
||||
for (auto cmd : mCommands) {
|
||||
delete cmd->val.args;
|
||||
}
|
||||
}
|
||||
412
CommandLine/private/CommandLine.cpp
Normal file
412
CommandLine/private/CommandLine.cpp
Normal file
|
|
@ -0,0 +1,412 @@
|
|||
#include "NewPlacement.hpp"
|
||||
|
||||
#include "CommandLine.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
static ModuleManifest* sModuleDependencies[] = { &gModuleTokenizer, &gModuleConnection, nullptr };
|
||||
ModuleManifest tp::gModuleCommandLine = ModuleManifest("CommandLine", nullptr, nullptr, sModuleDependencies);
|
||||
|
||||
const char* regexSpace = "\n|\t| |\r";
|
||||
const char* regexFalse = "N|n|(False)|(false)";
|
||||
const char* regexTrue = "Y|y|(True)|(true)";
|
||||
const char* regexInt = "((\\-)|(\\+))?[0-9]+";
|
||||
const char* regexFloat = R"(((\-)|(\+))?([0-9]+)(\.)([0-9]*)?)";
|
||||
const char* regexString = "'{'-'}*'";
|
||||
|
||||
CommandLine::Arg::Arg(const Arg& arg) {
|
||||
mId = arg.mId;
|
||||
switch (arg.mType) {
|
||||
case CommandLine::Arg::INT: mType = INT; mInt = arg.mInt; break;
|
||||
case CommandLine::Arg::FLOAT: mType = FLOAT; mFloat = arg.mFloat; break;
|
||||
case CommandLine::Arg::BOOL: mType = BOOL; mBool = arg.mBool; break;
|
||||
case CommandLine::Arg::STR: mType = STR; new (&mStr) StringArg(); mStr = arg.mStr; break;
|
||||
case CommandLine::Arg::FILE_IN: mType = FILE_IN; new (&mFile) FileInputArg(); mFile = arg.mFile; break;
|
||||
default:
|
||||
ASSERT(false)
|
||||
}
|
||||
mOptional = arg.mOptional;
|
||||
}
|
||||
|
||||
CommandLine::Arg::Arg(const String& id, Type type) {
|
||||
mId = id;
|
||||
switch (type) {
|
||||
case CommandLine::Arg::INT: mType = INT; new (&mInt) IntArg(); break;
|
||||
case CommandLine::Arg::FLOAT: mType = FLOAT; new (&mFloat) FloatArg(); break;
|
||||
case CommandLine::Arg::BOOL: mType = BOOL; new (&mBool) BoolArg(); break;
|
||||
case CommandLine::Arg::STR: mType = STR; new (&mStr) StringArg(); break;
|
||||
case CommandLine::Arg::FILE_IN: mType = FILE_IN; new (&mFile) FileInputArg(); break;
|
||||
default: ASSERT(false)
|
||||
}
|
||||
mOptional = false;
|
||||
}
|
||||
|
||||
CommandLine::Arg::Arg(const String& id, const Range<alni>& aAcceptingRange) {
|
||||
mId = id;
|
||||
mType = FLOAT;
|
||||
mInt = { 0, 0, aAcceptingRange };
|
||||
mOptional = false;
|
||||
}
|
||||
|
||||
CommandLine::Arg::Arg(const String& id, const Range<alnf>& aAcceptingRange) {
|
||||
mId = id;
|
||||
mType = FLOAT;
|
||||
mFloat = { 0, 0, aAcceptingRange };
|
||||
mOptional = false;
|
||||
}
|
||||
|
||||
CommandLine::Arg::Arg(const String& id, const Range<alni>& aAcceptingRange, alni aDefault) {
|
||||
mId = id;
|
||||
mType = INT;
|
||||
mInt = { 0, aDefault, aAcceptingRange };
|
||||
}
|
||||
|
||||
CommandLine::Arg::Arg(const String& id, const Range<alnf>& aAcceptingRange, alnf aDefault) {
|
||||
mId = id;
|
||||
mType = FLOAT;
|
||||
mFloat = { 0, aDefault, aAcceptingRange };
|
||||
}
|
||||
|
||||
CommandLine::Arg::Arg(const String& id, bool aDefault) {
|
||||
mId = id;
|
||||
mType = BOOL;
|
||||
mBool.mDefault = aDefault;
|
||||
}
|
||||
|
||||
CommandLine::Arg::Arg(const String& id, const char* aDefault) {
|
||||
mId = id;
|
||||
mType = STR;
|
||||
new (&mStr) StringArg();
|
||||
mStr.mDefault = aDefault;
|
||||
}
|
||||
|
||||
CommandLine::Arg::~Arg() {
|
||||
switch (mType) {
|
||||
case CommandLine::Arg::STR:
|
||||
mStr.~StringArg();
|
||||
break;
|
||||
case CommandLine::Arg::FILE_IN:
|
||||
mFile.~FileInputArg();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CommandLine::CommandLine(const InitialierList<Arg>& args) {
|
||||
bool optional_start = false;
|
||||
|
||||
for (auto& arg : args) {
|
||||
ASSERT(!mArgs.presents(arg.mId) && "Argument Redefinition")
|
||||
|
||||
auto copy_arg = new Arg(arg);
|
||||
|
||||
mArgs.put(arg.mId, copy_arg);
|
||||
mArgsOrder.pushBack(mArgs.get(arg.mId));
|
||||
|
||||
if (arg.mOptional) {
|
||||
mOptionals++;
|
||||
}
|
||||
|
||||
if (optional_start) {
|
||||
ASSERT(arg.mOptional && "Not Optional Argument After Optionals")
|
||||
}
|
||||
else if (arg.mOptional) {
|
||||
optional_start = true;
|
||||
}
|
||||
}
|
||||
|
||||
mTokenizer.build({
|
||||
{ regexSpace, TokType::SPACE },
|
||||
{ regexFalse, TokType::BOOL_FALSE },
|
||||
{ regexTrue, TokType::BOOL_TRUE },
|
||||
{ regexInt, TokType::INT },
|
||||
{ regexFloat, TokType::FLOAT },
|
||||
{ regexString, TokType::STR },
|
||||
});
|
||||
|
||||
ASSERT(mTokenizer.isBuild() && "Internal Error")
|
||||
|
||||
mArgumentTokenizer.build({
|
||||
{ regexSpace, ArgTokType::SPACE },
|
||||
{ "{ - }*", ArgTokType::ARG }
|
||||
});
|
||||
|
||||
ASSERT(mTokenizer.isBuild() && "Internal Error")
|
||||
}
|
||||
|
||||
CommandLine::~CommandLine() {
|
||||
for (auto arg : mArgsOrder) {
|
||||
delete arg.data();
|
||||
}
|
||||
}
|
||||
|
||||
bool CommandLine::parse(char argc, const char* argv[], bool logError, ualni skipArgs) {
|
||||
// discard some arguments
|
||||
argc -= (char) skipArgs;
|
||||
argv += skipArgs;
|
||||
|
||||
if (argc < mArgs.size() - mOptionals) {
|
||||
ErrInvalidArgCount();
|
||||
if (logError) {
|
||||
ErrLog();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ualni idx = 0;
|
||||
for (auto arg : mArgsOrder) {
|
||||
if (idx < argc) {
|
||||
parseArg(*arg.data(), argv[idx]);
|
||||
} else {
|
||||
initDefault(*arg.data());
|
||||
}
|
||||
if (mError) {
|
||||
if (logError) ErrLog();
|
||||
return false;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandLine::parse(const char* args, bool logError) {
|
||||
mArgumentTokenizer.bindSource(args);
|
||||
mArgumentTokenizer.reset();
|
||||
|
||||
ualni argc = 0;
|
||||
auto tok = mArgumentTokenizer.readTok();
|
||||
auto argument = mArgsOrder.first();
|
||||
|
||||
while (tok != ArgTokType::FAILURE && tok != ArgTokType::END) {
|
||||
if (tok != ArgTokType::ARG) {
|
||||
tok = mArgumentTokenizer.readTok();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!argument) {
|
||||
ErrInvalidArgCount();
|
||||
if (logError) ErrLog();
|
||||
return false;
|
||||
}
|
||||
|
||||
parseArg(*argument->data, mArgumentTokenizer.extractVal().read());
|
||||
|
||||
if (mError && logError) {
|
||||
ErrLog();
|
||||
return false;
|
||||
}
|
||||
|
||||
argc++;
|
||||
argument = argument->next;
|
||||
tok = mArgumentTokenizer.readTok();
|
||||
}
|
||||
|
||||
ualni idx = 0;
|
||||
for (auto arg : mArgsOrder) {
|
||||
if (idx >= argc) {
|
||||
initDefault(*arg.data());
|
||||
}
|
||||
if (mError) {
|
||||
if (logError) ErrLog();
|
||||
return false;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
alni CommandLine::getInt(const String& id) const { auto& arg = getArg(id, Arg::INT); return arg.mInt.mVal; }
|
||||
alnf CommandLine::getFloat(const String& id) const { auto& arg = getArg(id, Arg::FLOAT); return arg.mFloat.mVal; }
|
||||
bool CommandLine::getBool(const String& id) const { auto& arg = getArg(id, Arg::BOOL); return arg.mBool.mFlag; }
|
||||
const String& CommandLine::getString(const String& id) const { auto& arg = getArg(id, Arg::STR); return arg.mStr.mStr; }
|
||||
const LocalConnection::Location& CommandLine::getFile(const String& id) const { auto& arg = getArg(id, Arg::FILE_IN); return arg.mFile.mFileLocation; }
|
||||
|
||||
|
||||
CommandLine::Arg& CommandLine::getArg(const String& id, Arg::Type type) {
|
||||
auto idx = mArgs.presents(id);
|
||||
ASSERT(idx && "Invalid Id")
|
||||
auto& arg = mArgs.getSlotVal(idx);
|
||||
ASSERT(arg->mType == type && "Invalid Type Requested")
|
||||
return *arg;
|
||||
}
|
||||
|
||||
const CommandLine::Arg& CommandLine::getArg(const String& id, Arg::Type type) const {
|
||||
auto idx = mArgs.presents(id);
|
||||
ASSERT(idx && "Invalid Id")
|
||||
auto& arg = mArgs.getSlotVal(idx);
|
||||
ASSERT(arg->mType == type && "Invalid Type Requested")
|
||||
return *arg;
|
||||
}
|
||||
|
||||
void CommandLine::ErrInvalidArgCount() { mError = { "Invalid Number Of Arguments Passed", nullptr }; }
|
||||
void CommandLine::ErrInvalidArgSyntax(Arg* arg) { mError = { "Invalid Syntax Of Argument", arg }; }
|
||||
void CommandLine::ErrInvalidArgType(Arg* arg) { mError = { "Invalid Type Of Argument", arg }; }
|
||||
void CommandLine::ErrFileNotExists(Arg* arg) { mError = { "File Not Exists", arg }; }
|
||||
void CommandLine::ErrFileCouldNotOpen(Arg* arg) { mError = { "Could Not Open File", arg }; }
|
||||
void CommandLine::ErrValNotinRange(Arg* arg) { mError = { "Value Not In Range", arg }; }
|
||||
|
||||
void CommandLine::ErrLog() {
|
||||
printf("\nERROR : Invalid Command Line\n");
|
||||
|
||||
if (mError.mArg) {
|
||||
alni idx = 0;
|
||||
for (auto arg : mArgsOrder) {
|
||||
if (mError.mArg == arg.data()) break;
|
||||
idx++;
|
||||
}
|
||||
|
||||
printf("\nArgument: %lli\n", idx);
|
||||
logArg(*mError.mArg);
|
||||
}
|
||||
|
||||
printf("Error Description: %s. \n", mError.mDescr);
|
||||
|
||||
printf("\nExpected Arguments are: \n");
|
||||
ualni idx = 0;
|
||||
for (auto arg : mArgsOrder) {
|
||||
printf(" -- %lli -- \n", idx);
|
||||
logArg(*arg.data());
|
||||
idx++;
|
||||
}
|
||||
|
||||
printf("\nNote regex for types are:\n");
|
||||
printf(" False - %s\n", regexFalse);
|
||||
printf(" True - %s\n", regexTrue);
|
||||
printf(" Int - %s\n", regexInt);
|
||||
printf(" Float - %s\n", regexFloat);
|
||||
printf(" String - %s\n", regexString);
|
||||
printf(" File - else\n");
|
||||
}
|
||||
|
||||
void CommandLine::logArg(const Arg& arg) {
|
||||
switch (arg.mType) {
|
||||
case Arg::INT: {
|
||||
printf("Type : Int\n");
|
||||
printf("Range : %lli - %lli\n", arg.mInt.mAcceptingRange.mBegin, arg.mInt.mAcceptingRange.mEnd);
|
||||
if (arg.mOptional) {
|
||||
printf("Default : %lli\n", arg.mInt.mDefault);
|
||||
}
|
||||
printf("Value : %lli\n", arg.mInt.mVal);
|
||||
} break;
|
||||
case Arg::FLOAT: {
|
||||
printf("Type : Float\n");
|
||||
printf("Range : %f - %f\n", (halnf) arg.mFloat.mAcceptingRange.mBegin, (halnf) arg.mFloat.mAcceptingRange.mEnd);
|
||||
if (arg.mOptional) {
|
||||
printf("Default : %f\n", arg.mFloat.mDefault);
|
||||
}
|
||||
printf("Value : %f\n", arg.mFloat.mVal);
|
||||
} break;
|
||||
case Arg::BOOL: {
|
||||
printf("Type : Bool\n");
|
||||
if (arg.mOptional) {
|
||||
printf("Default : %s\n", arg.mBool.mDefault ? "True" : "False");
|
||||
}
|
||||
printf("Value : %s\n", arg.mBool.mFlag ? "True" : "False");
|
||||
} break;
|
||||
case Arg::STR: {
|
||||
printf("Type : String\n");
|
||||
if (arg.mOptional) {
|
||||
printf("Default : %s\n", arg.mStr.mDefault.read());
|
||||
}
|
||||
printf("Value : %s\n", arg.mStr.mStr.read());
|
||||
} break;
|
||||
case Arg::FILE_IN: {
|
||||
printf("Type : File Input\n");
|
||||
printf("Value Path : %s\n", arg.mFile.mFileLocation.getLocation().read());
|
||||
} break;
|
||||
default: ASSERT(false)
|
||||
}
|
||||
}
|
||||
|
||||
void CommandLine::initDefault(Arg& arg) {
|
||||
switch (arg.mType) {
|
||||
case Arg::INT: arg.mInt.mVal = arg.mInt.mDefault; break;
|
||||
case Arg::FLOAT: arg.mFloat.mVal = arg.mFloat.mDefault; break;
|
||||
case Arg::BOOL: arg.mBool.mFlag = arg.mBool.mDefault; break;
|
||||
case Arg::STR: arg.mStr.mStr = arg.mStr.mDefault; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CommandLine::parseArg(Arg& arg, const char* src) {
|
||||
mTokenizer.reset();
|
||||
mTokenizer.bindSource(src);
|
||||
|
||||
auto tok = mTokenizer.readTok();
|
||||
if (tok < TokType::INT || tok > TokType::STR) {
|
||||
ErrInvalidArgSyntax(&arg);
|
||||
return;
|
||||
}
|
||||
|
||||
auto val = mTokenizer.extractVal();
|
||||
|
||||
switch (arg.mType) {
|
||||
case Arg::INT: {
|
||||
if (tok != TokType::INT) {
|
||||
ErrInvalidArgType(&arg);
|
||||
return;
|
||||
}
|
||||
auto converted = String::Logic::convertStringToValue(val.read(), arg.mInt.mVal);
|
||||
if (converted && arg.mInt.mVal < arg.mInt.mAcceptingRange.mBegin || arg.mInt.mVal > arg.mInt.mAcceptingRange.mEnd) {
|
||||
ErrValNotinRange(&arg);
|
||||
return;
|
||||
}
|
||||
} break;
|
||||
|
||||
case Arg::FLOAT: {
|
||||
if (tok != TokType::FLOAT) {
|
||||
ErrInvalidArgType(&arg);
|
||||
return;
|
||||
}
|
||||
auto converted = String::Logic::convertStringToValue(val.read(), arg.mFloat.mVal);
|
||||
if (converted && arg.mFloat.mVal < arg.mFloat.mAcceptingRange.mBegin || arg.mFloat.mVal > arg.mFloat.mAcceptingRange.mEnd) {
|
||||
ErrValNotinRange(&arg);
|
||||
return;
|
||||
}
|
||||
} break;
|
||||
|
||||
case Arg::STR: {
|
||||
if (tok != TokType::STR) {
|
||||
ErrInvalidArgType(&arg);
|
||||
return;
|
||||
}
|
||||
arg.mStr.mStr.resize(val.size() - 2);
|
||||
memCopy(arg.mStr.mStr.write(), val.read() + 1, val.size() - 2);
|
||||
} break;
|
||||
|
||||
case Arg::BOOL: {
|
||||
if (tok != TokType::BOOL_FALSE && tok != TokType::BOOL_TRUE) {
|
||||
ErrInvalidArgType(&arg);
|
||||
return;
|
||||
}
|
||||
arg.mBool.mFlag = tok == TokType::BOOL_TRUE;
|
||||
} break;
|
||||
|
||||
case Arg::FILE_IN: {
|
||||
if (tok != TokType::STR) {
|
||||
ErrInvalidArgType(&arg);
|
||||
return;
|
||||
}
|
||||
|
||||
arg.mFile.mFileLocation.setLocation(val);
|
||||
|
||||
if (!arg.mFile.mFileLocation.exists()) {
|
||||
ErrFileNotExists(&arg);
|
||||
return;
|
||||
}
|
||||
|
||||
} break;
|
||||
default: ASSERT(false)
|
||||
}
|
||||
|
||||
arg.mIsPassed = true;
|
||||
}
|
||||
|
||||
void CommandLine::help() const {
|
||||
printf("Arguments:\n");
|
||||
for (auto arg : mArgsOrder) {
|
||||
logArg(*arg.data());
|
||||
}
|
||||
}
|
||||
36
CommandLine/public/CmdLineInterpreter.hpp
Normal file
36
CommandLine/public/CmdLineInterpreter.hpp
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include "CommandLine.hpp"
|
||||
#include "Map.hpp"
|
||||
|
||||
namespace tp {
|
||||
|
||||
class CmdLineInterpreter {
|
||||
public:
|
||||
|
||||
typedef bool (*CommandFunction)(void* customData, const CommandLine& args);
|
||||
|
||||
private:
|
||||
|
||||
struct Command {
|
||||
CommandLine* args;
|
||||
CommandFunction function;
|
||||
void* customData = nullptr;
|
||||
};
|
||||
|
||||
Map<String, Command> mCommands;
|
||||
String mName = "InterpName";
|
||||
|
||||
public:
|
||||
CmdLineInterpreter();
|
||||
~CmdLineInterpreter();
|
||||
|
||||
void setName(const String& name) { mName = name; }
|
||||
[[nodiscard]] const String& getName() const { return mName; }
|
||||
|
||||
void help(const CommandLine& args) const;
|
||||
void addCommand(const String& id, CommandLine* args, CommandFunction function, void* customData = nullptr);
|
||||
void run();
|
||||
bool processCommand(int1* command);
|
||||
};
|
||||
}
|
||||
114
CommandLine/public/CommandLine.hpp
Normal file
114
CommandLine/public/CommandLine.hpp
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
#pragma once
|
||||
|
||||
#include "Map.hpp"
|
||||
#include "LocalConnection.hpp"
|
||||
#include "Tokenizer.hpp"
|
||||
|
||||
namespace tp {
|
||||
|
||||
extern ModuleManifest gModuleCommandLine;
|
||||
|
||||
struct CommandLine {
|
||||
|
||||
struct IntArg {
|
||||
alni mVal = 0;
|
||||
alni mDefault = 0;
|
||||
Range<alni> mAcceptingRange = { -(std::numeric_limits<alni>::max() - 1), std::numeric_limits<alni>::max() };
|
||||
};
|
||||
|
||||
struct FloatArg {
|
||||
alnf mVal = 0.f;
|
||||
alnf mDefault = 0.f;
|
||||
Range<alnf> mAcceptingRange = { -(std::numeric_limits<alnf>::max() - 1), std::numeric_limits<alnf>::max() };
|
||||
};
|
||||
|
||||
struct BoolArg {
|
||||
bool mFlag = false;
|
||||
bool mDefault = false;
|
||||
};
|
||||
|
||||
struct StringArg {
|
||||
String mStr;
|
||||
String mDefault;
|
||||
};
|
||||
|
||||
struct FileInputArg {
|
||||
LocalConnection::Location mFileLocation;
|
||||
};
|
||||
|
||||
struct Arg {
|
||||
String mId;
|
||||
enum Type { INT, FLOAT, BOOL, STR, FILE_IN, NONE } mType = NONE;
|
||||
union {
|
||||
IntArg mInt;
|
||||
FloatArg mFloat;
|
||||
BoolArg mBool;
|
||||
StringArg mStr;
|
||||
FileInputArg mFile;
|
||||
};
|
||||
|
||||
bool mOptional = true;
|
||||
bool mIsPassed = false;
|
||||
|
||||
Arg(const Arg& arg);
|
||||
Arg(const String& id, Type type);
|
||||
Arg(const String& id, const Range<alni>& aAcceptingRange);
|
||||
Arg(const String& id, const Range<alnf>& aAcceptingRange);
|
||||
Arg(const String& id, const Range<alni>& aAcceptingRange, alni aDefault);
|
||||
Arg(const String& id, const Range<alnf>& aAcceptingRange, alnf aDefault);
|
||||
Arg(const String& id, bool aDefault);
|
||||
Arg(const String& id, const char* aDefault);
|
||||
~Arg();
|
||||
};
|
||||
|
||||
struct Error {
|
||||
const char* mDescr = nullptr;
|
||||
Arg* mArg = nullptr;
|
||||
operator bool() { return mDescr != nullptr; }
|
||||
} mError;
|
||||
|
||||
CommandLine(const InitialierList<Arg>& args);
|
||||
~CommandLine();
|
||||
|
||||
void resetError() { mError.mDescr = nullptr; }
|
||||
|
||||
bool parse(char argc, const char* argv[], bool logError = true, ualni skipArgs = 1);
|
||||
bool parse(const char* args, bool logError = true);
|
||||
|
||||
void help() const;
|
||||
|
||||
[[nodiscard]] alni getInt(const String& id) const;
|
||||
[[nodiscard]] alnf getFloat(const String& id) const;
|
||||
[[nodiscard]] bool getBool(const String& id) const;
|
||||
[[nodiscard]] const String& getString(const String& id) const;
|
||||
[[nodiscard]] const LocalConnection::Location& getFile(const String& id) const;
|
||||
|
||||
const CommandLine& operator=(const CommandLine&) = delete;
|
||||
|
||||
private:
|
||||
enum class TokType { SPACE, INT, FLOAT, BOOL_FALSE, BOOL_TRUE, STR, NONE, FAILURE, END, };
|
||||
typedef SimpleTokenizer<char, TokType, TokType::NONE, TokType::FAILURE, TokType::END> Tokenizer;
|
||||
|
||||
Tokenizer mTokenizer;
|
||||
Map<String, Arg*> mArgs;
|
||||
List<Arg*> mArgsOrder;
|
||||
ualni mOptionals = 0;
|
||||
|
||||
enum class ArgTokType { SPACE, ARG, NONE, FAILURE, END, };
|
||||
SimpleTokenizer<char, ArgTokType, ArgTokType::NONE, ArgTokType::FAILURE, ArgTokType::END> mArgumentTokenizer;
|
||||
|
||||
Arg& getArg(const String& id, Arg::Type type);
|
||||
[[nodiscard]] const Arg& getArg(const String& id, Arg::Type type) const;
|
||||
|
||||
void ErrInvalidArgCount();
|
||||
void ErrInvalidArgSyntax(Arg* arg);
|
||||
void ErrInvalidArgType(Arg* arg);
|
||||
void ErrFileNotExists(Arg* arg);
|
||||
void ErrFileCouldNotOpen(Arg* arg);
|
||||
void ErrValNotinRange(Arg* arg);
|
||||
void ErrLog();
|
||||
static void logArg(const Arg& arg);
|
||||
static void initDefault(Arg& arg);
|
||||
void parseArg(Arg& arg, const char* src);
|
||||
};
|
||||
}
|
||||
25
CommandLine/tests/TestCommandLine.cpp
Normal file
25
CommandLine/tests/TestCommandLine.cpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#include "NewPlacement.hpp"
|
||||
|
||||
#include "Tests.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
static CommandLine createCmdLine() {
|
||||
CommandLine cmd({
|
||||
{ "bool", CommandLine::Arg::BOOL },
|
||||
{ "int", CommandLine::Arg::INT },
|
||||
{ "string", CommandLine::Arg::STR },
|
||||
{ "float", CommandLine::Arg::FLOAT },
|
||||
});
|
||||
return cmd;
|
||||
}
|
||||
|
||||
TEST_DEF_STATIC(Simple) {
|
||||
auto cmd = createCmdLine();
|
||||
const char* args[] = { "false", "2", "'str'", "-0.15" };
|
||||
cmd.parse(4, args, true, 0);
|
||||
}
|
||||
|
||||
TEST_DEF(CommandLine) {
|
||||
testSimple();
|
||||
}
|
||||
36
CommandLine/tests/TestInterpreter.cpp
Normal file
36
CommandLine/tests/TestInterpreter.cpp
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#include "NewPlacement.hpp"
|
||||
|
||||
#include "Tests.hpp"
|
||||
#include "CmdLineInterpreter.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
TEST_DEF_STATIC(Simple) {
|
||||
|
||||
struct TestStruct {
|
||||
int val = 0;
|
||||
|
||||
static bool print(TestStruct* self, const CommandLine& args) {
|
||||
printf("Test Val - %i\n", (int) args.getBool("bool"));
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
TestStruct self;
|
||||
|
||||
CmdLineInterpreter interp;
|
||||
|
||||
interp.addCommand("test", new CommandLine{ { "bool", CommandLine::Arg::BOOL } }, (CmdLineInterpreter::CommandFunction) TestStruct::print);
|
||||
|
||||
printf("test false\n", stdin);
|
||||
printf("help\n", stdin);
|
||||
printf("help test\n", stdin);
|
||||
printf("exit\n", stdin);
|
||||
|
||||
interp.run();
|
||||
}
|
||||
|
||||
TEST_DEF(Interpreter) {
|
||||
//testSimple();
|
||||
}
|
||||
18
CommandLine/tests/Tests.cpp
Normal file
18
CommandLine/tests/Tests.cpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#include "NewPlacement.hpp"
|
||||
|
||||
#include "Tests.hpp"
|
||||
|
||||
int main() {
|
||||
|
||||
tp::ModuleManifest* deps[] = { &tp::gModuleUtils, &tp::gModuleTokenizer, nullptr };
|
||||
tp::ModuleManifest testModule("CommandLineTest", nullptr, nullptr, deps);
|
||||
|
||||
if (!testModule.initialize()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// testCommandLine();
|
||||
testInterpreter();
|
||||
|
||||
testModule.deinitialize();
|
||||
}
|
||||
8
CommandLine/tests/Tests.hpp
Normal file
8
CommandLine/tests/Tests.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "Testing.hpp"
|
||||
#include "Allocators.hpp"
|
||||
#include "CommandLine.hpp"
|
||||
|
||||
void testCommandLine();
|
||||
void testInterpreter();
|
||||
25
Connection/CMakeLists.txt
Normal file
25
Connection/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
project(Connection)
|
||||
|
||||
set(BINDINGS_INCLUDE ./../Externals/asio/asio/include)
|
||||
|
||||
### ---------------------- Static Library --------------------- ###
|
||||
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
|
||||
file(GLOB HEADERS "./public/*.hpp")
|
||||
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${BINDINGS_INCLUDE})
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Strings)
|
||||
|
||||
### -------------------------- Tests -------------------------- ###
|
||||
enable_testing()
|
||||
file(GLOB TEST_SOURCES "./tests/*.cpp")
|
||||
add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES})
|
||||
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Utils)
|
||||
add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests)
|
||||
|
||||
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/lib)
|
||||
9
Connection/private/ConnectionCommon.cpp
Normal file
9
Connection/private/ConnectionCommon.cpp
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
#include "ConnectionCommon.hpp"
|
||||
|
||||
static tp::ModuleManifest* sModuleDependencies[] = {
|
||||
&tp::gModuleStrings,
|
||||
nullptr
|
||||
};
|
||||
|
||||
tp::ModuleManifest tp::gModuleConnection = ModuleManifest("Storage", nullptr, nullptr, sModuleDependencies);
|
||||
92
Connection/private/LocalConnection.cpp
Normal file
92
Connection/private/LocalConnection.cpp
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
#include "NewPlacement.hpp"
|
||||
|
||||
#include "LocalConnection.hpp"
|
||||
|
||||
#include "bindings/Disk.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
using namespace tp;
|
||||
|
||||
bool LocalConnection::Location::exists() const {
|
||||
FILE* file = fopen(mLocation.read(), "r");
|
||||
if (file) {
|
||||
// File exists, close it and return 1
|
||||
fclose(file);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LocalConnection::connect(const Location& location, const Type& connectionInfo) {
|
||||
DEBUG_ASSERT(!mStatus.isOpened());
|
||||
if (mStatus.isOpened()) return false;
|
||||
|
||||
auto handle = new LocalConnectionContext();
|
||||
|
||||
switch (connectionInfo.getType()) {
|
||||
case Type::READ:
|
||||
handle->open(location.getLocation().read(), true);
|
||||
break;
|
||||
|
||||
case Type::WRITE:
|
||||
handle->open(location.getLocation().read(), false);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
if (!handle->isOpen()) {
|
||||
mStatus.setStatus(Status::DENIED);
|
||||
delete handle;
|
||||
return false;
|
||||
}
|
||||
|
||||
mStatus.setStatus(Status::OPENED);
|
||||
mHandle = handle;
|
||||
mConnectionType = connectionInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LocalConnection::disconnect() {
|
||||
DEBUG_ASSERT(mStatus.isOpened());
|
||||
if (!mStatus.isOpened() || !mHandle) return false;
|
||||
mHandle->close();
|
||||
delete mHandle;
|
||||
mStatus.setStatus(Status::CLOSED);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LocalConnection::setPointer(BytePointer pointer) {
|
||||
DEBUG_ASSERT(mStatus.isOpened());
|
||||
if (!mStatus.isOpened()) return false;
|
||||
mPointer = pointer;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LocalConnection::readBytes(Byte* bytes, SizeBytes size) {
|
||||
DEBUG_ASSERT(mStatus.isOpened() && mConnectionType.isRead());
|
||||
if (!mStatus.isOpened() || !mConnectionType.isRead()) return false;
|
||||
|
||||
mHandle->seekp(mPointer);
|
||||
mHandle->read(bytes, size);
|
||||
mPointer += size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LocalConnection::writeBytes(const Byte* bytes, SizeBytes size) {
|
||||
DEBUG_ASSERT(mStatus.isOpened() && mConnectionType.isWrite());
|
||||
if (!mStatus.isOpened() || !mConnectionType.isWrite()) return false;
|
||||
|
||||
mHandle->seekp(mPointer);
|
||||
mHandle->write(bytes, size);
|
||||
mPointer += size;
|
||||
return true;
|
||||
}
|
||||
|
||||
LocalConnection::SizeBytes LocalConnection::size() {
|
||||
DEBUG_ASSERT(mStatus.isOpened());
|
||||
if (!mStatus.isOpened() || !mHandle) return 0;
|
||||
return mHandle->size();
|
||||
}
|
||||
2
Connection/private/RemoteConnection.cpp
Normal file
2
Connection/private/RemoteConnection.cpp
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
#include "RemoteConnection.hpp"
|
||||
57
Connection/private/bindings/Disk.cpp
Normal file
57
Connection/private/bindings/Disk.cpp
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#include "Disk.hpp"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
using namespace tp;
|
||||
|
||||
ualni tp::LocalConnectionContext::size() {
|
||||
auto strm = (std::fstream*) stream;
|
||||
ualni out = 0;
|
||||
strm->seekg(0, std::ios::beg);
|
||||
out = strm->tellg();
|
||||
strm->seekg(0, std::ios::end);
|
||||
out = (ualni) strm->tellg() - out;
|
||||
return out;
|
||||
}
|
||||
|
||||
LocalConnectionContext::LocalConnectionContext() {
|
||||
stream = new std::fstream();
|
||||
}
|
||||
|
||||
LocalConnectionContext::~LocalConnectionContext() {
|
||||
auto strm = (std::fstream*) stream;
|
||||
delete strm;
|
||||
}
|
||||
|
||||
bool LocalConnectionContext::isOpen() {
|
||||
auto strm = (std::fstream*) stream;
|
||||
return strm->is_open();
|
||||
}
|
||||
|
||||
void LocalConnectionContext::close() {
|
||||
auto strm = (std::fstream*) stream;
|
||||
strm->close();
|
||||
}
|
||||
|
||||
void LocalConnectionContext::seekp(ualni in) {
|
||||
auto strm = (std::fstream*) stream;
|
||||
strm->seekp(in);
|
||||
}
|
||||
|
||||
void LocalConnectionContext::read(int1* in, ualni size) {
|
||||
auto strm = (std::fstream*) stream;
|
||||
strm->read(in, size);
|
||||
}
|
||||
|
||||
void LocalConnectionContext::write(const int1* in, ualni size) {
|
||||
auto strm = (std::fstream*) stream;
|
||||
strm->write(in, size);
|
||||
}
|
||||
|
||||
void LocalConnectionContext::open(const char* path, bool read) {
|
||||
auto strm = (std::fstream*) stream;
|
||||
if (read)
|
||||
strm->open(path, std::ios::in | std::ios::binary | std::ios::app);
|
||||
else
|
||||
strm->open(path, std::ios::out | std::ios::binary | std::ios::trunc);
|
||||
}
|
||||
17
Connection/private/bindings/Disk.hpp
Normal file
17
Connection/private/bindings/Disk.hpp
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#include "Common.hpp"
|
||||
|
||||
namespace tp {
|
||||
class LocalConnectionContext {
|
||||
void* stream;
|
||||
public:
|
||||
LocalConnectionContext();
|
||||
~LocalConnectionContext();
|
||||
void open(const char*, bool);
|
||||
bool isOpen();
|
||||
void close();
|
||||
void seekp(ualni);
|
||||
void read(int1*, ualni);
|
||||
void write(const int1*, ualni);
|
||||
ualni size();
|
||||
};
|
||||
}
|
||||
130
Connection/private/bindings/Network.cpp
Normal file
130
Connection/private/bindings/Network.cpp
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
#include "Network.hpp"
|
||||
|
||||
#include "asio.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace tp;
|
||||
|
||||
class tp::ServerContext {
|
||||
friend class Server;
|
||||
|
||||
asio::io_context context;
|
||||
asio::ip::tcp::acceptor socket;
|
||||
typedef asio::ip::tcp::socket Socket;
|
||||
|
||||
ServerContext() : socket(context) {}
|
||||
|
||||
~ServerContext() {
|
||||
context.stop();
|
||||
socket.close();
|
||||
}
|
||||
};
|
||||
|
||||
class tp::ClientContext {
|
||||
friend Client;
|
||||
|
||||
asio::io_context context;
|
||||
asio::ip::tcp::socket socket;
|
||||
|
||||
public:
|
||||
ClientContext() : socket(context) {}
|
||||
|
||||
~ClientContext() {
|
||||
context.stop();
|
||||
socket.close();
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------- //
|
||||
|
||||
Server::Server() {
|
||||
mContext = new ServerContext();
|
||||
}
|
||||
|
||||
Server::~Server() {
|
||||
delete mContext;
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void Server::start(ualni port) {
|
||||
mContext->socket.open(asio::ip::tcp::v4());
|
||||
mContext->socket.bind(asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port));
|
||||
mContext->socket.listen();
|
||||
std::cout << "Server listening on port " << port << std::endl;
|
||||
}
|
||||
|
||||
Server::Socket Server::accept() {
|
||||
auto clientSocket = new asio::ip::tcp::socket(mContext->context);
|
||||
mContext->socket.accept(*clientSocket);
|
||||
std::cout << "New client accepted "<< std::endl;
|
||||
return clientSocket;
|
||||
}
|
||||
|
||||
int1* Server::read(Socket client) {
|
||||
short messageSize;
|
||||
if (asio::read(*(ServerContext::Socket*)client, asio::buffer(&messageSize, 2)) == -1) {
|
||||
std::cerr << "Failed to read from socket" << std::endl;
|
||||
((ServerContext::Socket*)client)->close();
|
||||
return nullptr;
|
||||
}
|
||||
auto message = new char[messageSize + 1];
|
||||
message[messageSize] = '\0';
|
||||
if (asio::read(*(ServerContext::Socket*)client, asio::buffer(message, messageSize)) == -1) {
|
||||
std::cerr << "Failed to read from socket" << std::endl;
|
||||
memcpy(message, "Client wanna say something but i cant read", 100);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
void Server::write(Socket client, const char* message) {
|
||||
auto messageSize = (short) strlen(message);
|
||||
if (asio::write(*(ServerContext::Socket*)client, asio::buffer(&messageSize, 2)) == -1) {
|
||||
std::cerr << "Failed to write to socket" << std::endl;
|
||||
}
|
||||
if (asio::write(*(ServerContext::Socket*)client, asio::buffer(message, messageSize)) == -1) {
|
||||
std::cerr << "Failed to write to socket" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------- //
|
||||
|
||||
Client::Client() {
|
||||
mContext = new ClientContext();
|
||||
}
|
||||
|
||||
Client::~Client() {
|
||||
delete mContext;
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void Client::connect(const char* IP, ualni PORT) {
|
||||
asio::ip::tcp::endpoint endpoint(asio::ip::address::from_string(IP), PORT);
|
||||
mContext->socket.connect(endpoint);
|
||||
}
|
||||
|
||||
char* Client::read() {
|
||||
short messageSize;
|
||||
if (asio::read(mContext->socket, asio::buffer(&messageSize, 2)) == -1) {
|
||||
std::cerr << "Failed to read from socket" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
auto message = new char[messageSize + 1];
|
||||
message[messageSize] = '\0';
|
||||
if (asio::read(mContext->socket, asio::buffer(message, messageSize)) == -1) {
|
||||
std::cerr << "Failed to read from socket" << std::endl;
|
||||
memcpy(message, "Cant wanna say something but i cant read", 100);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
void Client::write( const char* message ) {
|
||||
auto messageSize = (short) strlen(message);
|
||||
if (asio::write(mContext->socket, asio::buffer(&messageSize, 2)) == -1) {
|
||||
std::cerr << "Failed to write to socket" << std::endl;
|
||||
}
|
||||
if (asio::write(mContext->socket, asio::buffer(message, messageSize)) == -1) {
|
||||
std::cerr << "Failed to write to socket" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
36
Connection/private/bindings/Network.hpp
Normal file
36
Connection/private/bindings/Network.hpp
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include "Common.hpp"
|
||||
|
||||
namespace tp {
|
||||
class ServerContext;
|
||||
class ClientContext;
|
||||
|
||||
class Server {
|
||||
ServerContext* mContext;
|
||||
|
||||
public:
|
||||
typedef void* Socket;
|
||||
|
||||
public:
|
||||
Server();
|
||||
~Server();
|
||||
|
||||
void start(ualni port);
|
||||
Socket accept();
|
||||
static int1* read(Socket client);
|
||||
static void write(Socket client, const int1* message);
|
||||
};
|
||||
|
||||
class Client {
|
||||
ClientContext* mContext;
|
||||
|
||||
public:
|
||||
Client();
|
||||
~Client();
|
||||
|
||||
void connect(const int1* IP, ualni PORT);
|
||||
int1* read();
|
||||
void write(const int1* message);
|
||||
};
|
||||
}
|
||||
65
Connection/public/ConnectionCommon.hpp
Normal file
65
Connection/public/ConnectionCommon.hpp
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
#pragma once
|
||||
|
||||
#include "Strings.hpp"
|
||||
|
||||
namespace tp {
|
||||
extern ModuleManifest gModuleConnection;
|
||||
|
||||
class Connection {
|
||||
public:
|
||||
typedef ualni SizeBytes;
|
||||
typedef ualni BytePointer;
|
||||
typedef int1 Byte;
|
||||
|
||||
class Status {
|
||||
public:
|
||||
enum State {
|
||||
NONE,
|
||||
OPENED,
|
||||
CLOSED,
|
||||
DENIED,
|
||||
INVALID,
|
||||
};
|
||||
|
||||
private:
|
||||
State mStatus = NONE;
|
||||
|
||||
public:
|
||||
Status() = default;
|
||||
[[nodiscard]] State getStatus() const { return mStatus; }
|
||||
void setStatus(State status) { mStatus = status; }
|
||||
[[nodiscard]] bool isOpened() const { return mStatus == OPENED; }
|
||||
};
|
||||
|
||||
class Type {
|
||||
public:
|
||||
enum State {
|
||||
WRITE,
|
||||
READ,
|
||||
READ_WRITE,
|
||||
NONE,
|
||||
};
|
||||
|
||||
private:
|
||||
State mHandleType = NONE;
|
||||
|
||||
public:
|
||||
Type() = default;
|
||||
explicit Type(bool read) : mHandleType((State) read) {}
|
||||
explicit Type(State handleType) : mHandleType(handleType) {}
|
||||
[[nodiscard]] State getType() const { return mHandleType; }
|
||||
[[nodiscard]] bool isRead() const { return mHandleType == READ; }
|
||||
[[nodiscard]] bool isWrite() const { return mHandleType == WRITE; }
|
||||
};
|
||||
|
||||
protected:
|
||||
Status mStatus;
|
||||
Type mConnectionType;
|
||||
|
||||
public:
|
||||
Connection() = default;
|
||||
|
||||
virtual const Status& getConnectionStatus() { return mStatus; }
|
||||
virtual const Type& getConnectionType() { return mConnectionType; }
|
||||
};
|
||||
}
|
||||
51
Connection/public/LocalConnection.hpp
Normal file
51
Connection/public/LocalConnection.hpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#pragma once
|
||||
|
||||
#include "ConnectionCommon.hpp"
|
||||
|
||||
namespace tp {
|
||||
class LocalConnectionContext;
|
||||
|
||||
class LocalConnection : public Connection {
|
||||
public:
|
||||
class Location {
|
||||
String mLocation;
|
||||
public:
|
||||
Location() : mLocation("tmp") {};
|
||||
explicit Location(const String& location) : mLocation(location) {}
|
||||
void setLocation(const String& location) { mLocation = location; }
|
||||
[[nodiscard]] const String& getLocation() const { return mLocation; }
|
||||
[[nodiscard]] bool exists() const;
|
||||
};
|
||||
|
||||
public:
|
||||
LocalConnection() {
|
||||
MODULE_SANITY_CHECK(gModuleConnection)
|
||||
};
|
||||
|
||||
virtual ~LocalConnection() {
|
||||
if (mStatus.isOpened()) LocalConnection::disconnect();
|
||||
}
|
||||
|
||||
public:
|
||||
virtual bool connect(const Location& location, const Type& connectionInfo);
|
||||
virtual bool disconnect();
|
||||
|
||||
public:
|
||||
virtual const Status& getConnectionStatus() { return mStatus; }
|
||||
virtual const Type& getConnectionType() { return mConnectionType; }
|
||||
virtual const Location& getLocation() { return mLocation; }
|
||||
|
||||
public:
|
||||
virtual bool setPointer(BytePointer pointer);
|
||||
virtual bool readBytes(Byte* bytes, SizeBytes size);
|
||||
virtual bool writeBytes(const Byte* bytes, SizeBytes size);
|
||||
|
||||
public:
|
||||
virtual SizeBytes size();
|
||||
|
||||
private:
|
||||
LocalConnectionContext* mHandle = nullptr;
|
||||
Location mLocation;
|
||||
BytePointer mPointer = 0;
|
||||
};
|
||||
}
|
||||
42
Connection/public/RemoteConnection.hpp
Normal file
42
Connection/public/RemoteConnection.hpp
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#pragma once
|
||||
|
||||
#include "ConnectionCommon.hpp"
|
||||
#include "List.hpp"
|
||||
|
||||
namespace tp {
|
||||
|
||||
class RemoteConnectionContext;
|
||||
|
||||
class RemoteConnection : public Connection {
|
||||
public:
|
||||
class Location {
|
||||
ualni mId = 0;
|
||||
public:
|
||||
Location() = default;
|
||||
};
|
||||
|
||||
public:
|
||||
RemoteConnection() {
|
||||
MODULE_SANITY_CHECK(gModuleConnection)
|
||||
};
|
||||
|
||||
virtual ~RemoteConnection() {
|
||||
if (mStatus.isOpened()) RemoteConnection::disconnect();
|
||||
}
|
||||
|
||||
public:
|
||||
virtual bool connect(const Location& location, const Type& connectionInfo);
|
||||
virtual bool disconnect();
|
||||
|
||||
public:
|
||||
virtual const Location& getLocation() { return mLocation; }
|
||||
|
||||
public:
|
||||
virtual bool readBytes(Byte* bytes, SizeBytes size);
|
||||
virtual bool writeBytes(const Byte* bytes, SizeBytes size);
|
||||
|
||||
private:
|
||||
RemoteConnectionContext* mHandle = nullptr;
|
||||
Location mLocation;
|
||||
};
|
||||
}
|
||||
35
Connection/tests/TestLocal.cpp
Normal file
35
Connection/tests/TestLocal.cpp
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
#include "NewPlacement.hpp"
|
||||
|
||||
#include "LocalConnection.hpp"
|
||||
#include "Testing.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
TEST_DEF_STATIC(Simple) {
|
||||
|
||||
const int1* data = "abcde\0";
|
||||
int1 dataRead[6]{};
|
||||
|
||||
{
|
||||
LocalConnection file;
|
||||
file.connect(LocalConnection::Location(String("tmp2.txt")), LocalConnection::Type(false));
|
||||
file.writeBytes(data, 6);
|
||||
file.disconnect();
|
||||
}
|
||||
|
||||
{
|
||||
LocalConnection file;
|
||||
file.connect(LocalConnection::Location(String("tmp2.txt")), LocalConnection::Type(true));
|
||||
file.readBytes(dataRead, 6);
|
||||
file.disconnect();
|
||||
}
|
||||
|
||||
for (auto i = 0; i < 5; i++) {
|
||||
TEST(data[i] == dataRead[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_DEF(LocalConnection) {
|
||||
testSimple();
|
||||
}
|
||||
19
Connection/tests/Tests.cpp
Normal file
19
Connection/tests/Tests.cpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
#include "ConnectionCommon.hpp"
|
||||
#include "Testing.hpp"
|
||||
|
||||
void testLocalConnection();
|
||||
|
||||
int main() {
|
||||
|
||||
tp::ModuleManifest* deps[] = { &tp::gModuleConnection, nullptr };
|
||||
tp::ModuleManifest testModule("ConnectionTest", nullptr, nullptr, deps);
|
||||
|
||||
if (!testModule.initialize()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
testLocalConnection();
|
||||
|
||||
testModule.deinitialize();
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ target_link_libraries(${PROJECT_NAME} PUBLIC Modules)
|
|||
enable_testing()
|
||||
file(GLOB TEST_SOURCES "./tests/*.cpp")
|
||||
add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES})
|
||||
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Utils)
|
||||
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Allocators)
|
||||
add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests)
|
||||
|
||||
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/lib)
|
||||
|
|
@ -20,42 +20,140 @@ namespace tp {
|
|||
|
||||
template<typename tType, ualni tSize>
|
||||
class ConstSizeBuffer {
|
||||
SelCopyArg<tType> Arg;
|
||||
typedef SelectValueOrReference<tType> Arg;
|
||||
|
||||
private:
|
||||
tType mBuff[tSize];
|
||||
ualni mLoad = 0;
|
||||
|
||||
public:
|
||||
ConstSizeBuffer() = default;
|
||||
|
||||
~ConstSizeBuffer() {
|
||||
for (auto i = 0; i < mLoad; i++) {
|
||||
mBuff[i].~tType();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
[[nodiscard]] ualni size() const { return tSize; }
|
||||
[[nodiscard]] ualni size() const { return mLoad; }
|
||||
[[nodiscard]] ualni getBuffSize() const { return tSize; }
|
||||
|
||||
tType& first() {
|
||||
DEBUG_ASSERT(mLoad)
|
||||
return *mBuff;
|
||||
}
|
||||
|
||||
const tType& first() const {
|
||||
DEBUG_ASSERT(mLoad)
|
||||
return *mBuff;
|
||||
}
|
||||
|
||||
tType& last() {
|
||||
return mBuff[tSize - 1];
|
||||
DEBUG_ASSERT(mLoad)
|
||||
return mBuff[mLoad - 1];
|
||||
}
|
||||
|
||||
const tType& last() const {
|
||||
return mBuff[tSize - 1];
|
||||
DEBUG_ASSERT(mLoad)
|
||||
return mBuff[mLoad - 1];
|
||||
}
|
||||
|
||||
tType& operator[](ualni aIdx) {
|
||||
DEBUG_ASSERT(aIdx >= 0 && aIdx < tSize)
|
||||
DEBUG_ASSERT(aIdx >= 0 && aIdx < mLoad)
|
||||
return mBuff[aIdx];
|
||||
}
|
||||
|
||||
const tType& operator[](ualni aIdx) const {
|
||||
DEBUG_ASSERT(aIdx >= 0 && aIdx < tSize)
|
||||
DEBUG_ASSERT(aIdx >= 0 && aIdx < mLoad)
|
||||
return mBuff[aIdx];
|
||||
}
|
||||
|
||||
void append(Arg data) {
|
||||
ASSERT(mLoad != tSize)
|
||||
new (&mBuff[mLoad]) tType(data);
|
||||
mLoad++;
|
||||
}
|
||||
|
||||
void pop() {
|
||||
DEBUG_ASSERT(mLoad)
|
||||
mBuff[mLoad].~tType();
|
||||
mLoad--;
|
||||
}
|
||||
|
||||
ConstSizeBuffer& operator=(const tp::InitialierList<tType>& init) {
|
||||
for (auto arg : init) {
|
||||
append(arg);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
this->~ConstSizeBuffer();
|
||||
new (this) ConstSizeBuffer();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
class IteratorPointer {
|
||||
protected:
|
||||
tType* mIter;
|
||||
public:
|
||||
IteratorPointer() = default;
|
||||
tType& operator->() { return *mIter; }
|
||||
const tType& operator->() const { return *mIter; }
|
||||
};
|
||||
|
||||
class IteratorReference {
|
||||
protected:
|
||||
tType* mIter;
|
||||
public:
|
||||
IteratorReference() = default;
|
||||
tType* operator->() { return mIter; }
|
||||
const tType* operator->() const { return mIter; }
|
||||
};
|
||||
|
||||
class Iterator : public TypeSelect<TypeTraits<tType>::isPointer, IteratorPointer, IteratorReference>::Result {
|
||||
public:
|
||||
|
||||
explicit Iterator(tType* iter) { this->mIter = iter; }
|
||||
|
||||
const Iterator& operator*() const { return *this; }
|
||||
|
||||
Iterator& operator++() {
|
||||
this->mIter++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const Iterator& left) const { return left.mIter == this->mIter; }
|
||||
bool operator!=(const Iterator& left) const { return left.mIter != this->mIter; }
|
||||
};
|
||||
|
||||
[[nodiscard]] Iterator begin() const {
|
||||
return Iterator(mBuff);
|
||||
}
|
||||
|
||||
[[nodiscard]] Iterator end() const {
|
||||
return Iterator(mBuff + mLoad);
|
||||
}
|
||||
|
||||
public:
|
||||
template<class tArchiver>
|
||||
void archiveWrite(tArchiver& ar) const {
|
||||
ar << mLoad;
|
||||
for (auto item : *this) {
|
||||
ar << item.data();
|
||||
}
|
||||
}
|
||||
|
||||
template<class tArchiver>
|
||||
void archiveRead(tArchiver& ar) {
|
||||
clear();
|
||||
ar >> mLoad;
|
||||
for (auto i = 0; i < mLoad; i++) {
|
||||
ar >> mBuff[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<
|
||||
|
|
@ -66,7 +164,7 @@ namespace tp {
|
|||
ualni tMinSize = 4
|
||||
>
|
||||
class Buffer {
|
||||
typedef SelCopyArg<tType> Arg;
|
||||
typedef SelectValueOrReference<tType> Arg;
|
||||
|
||||
private:
|
||||
tType* mBuff;
|
||||
|
|
@ -80,7 +178,7 @@ namespace tp {
|
|||
}
|
||||
|
||||
explicit Buffer(ualni size) : mSize(size), mLoad(0) {
|
||||
mBuff = (tType*) mAllocator.allocate(sizeof(tType) * tMinSize);
|
||||
mBuff = (tType*) mAllocator.allocate(sizeof(tType) * size);
|
||||
}
|
||||
|
||||
Buffer(const Buffer& in) : mSize(in.mSize), mLoad(in.mLoad) {
|
||||
|
|
@ -88,10 +186,14 @@ namespace tp {
|
|||
for (ualni i = 0; i < mLoad; i++) new (&mBuff[i]) tType(in.mBuff[i]);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
this->~Buffer();
|
||||
new (this) Buffer();
|
||||
}
|
||||
|
||||
Buffer& operator=(const Buffer& in) {
|
||||
if (this == &in) return *this;
|
||||
this->~Buffer();
|
||||
new (this) Buffer(in);
|
||||
clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -150,6 +252,14 @@ namespace tp {
|
|||
}
|
||||
|
||||
public:
|
||||
Buffer& operator=(const tp::InitialierList<tType>& init) {
|
||||
// TODO : optimize
|
||||
for (auto arg : init) {
|
||||
append(arg);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void append(Arg data) {
|
||||
if (mLoad == mSize) resizeBuffer(tResizePolicy(mSize));
|
||||
new (&mBuff[mLoad]) tType(data);
|
||||
|
|
@ -175,6 +285,83 @@ namespace tp {
|
|||
if (prevSize > mLoad) resizeBuffer(prevSize);
|
||||
}
|
||||
|
||||
void reserve(ualni aSize) {
|
||||
for (ualni i = 0; i < mLoad; i++) mBuff[i].~tType();
|
||||
mBuff = (tType*) mAllocator.allocate(sizeof(tType) * aSize);
|
||||
mSize = aSize;
|
||||
mLoad = aSize;
|
||||
for (ualni i = 0; i < mLoad; i++) new (mBuff + i) tType();
|
||||
}
|
||||
|
||||
public:
|
||||
class IteratorPointer {
|
||||
protected:
|
||||
tType* mIter;
|
||||
public:
|
||||
IteratorPointer() = default;
|
||||
tType& operator->() { return *mIter; }
|
||||
const tType& operator->() const { return *mIter; }
|
||||
};
|
||||
|
||||
class IteratorReference {
|
||||
protected:
|
||||
tType* mIter;
|
||||
public:
|
||||
IteratorReference() = default;
|
||||
tType* operator->() { return mIter; }
|
||||
const tType* operator->() const { return mIter; }
|
||||
};
|
||||
|
||||
class Iterator : public TypeSelect<TypeTraits<tType>::isPointer, IteratorPointer, IteratorReference>::Result {
|
||||
public:
|
||||
|
||||
explicit Iterator(tType* iter) { this->mIter = iter; }
|
||||
|
||||
const Iterator& operator*() const { return *this; }
|
||||
|
||||
tType& data() {
|
||||
return *this->mIter;
|
||||
}
|
||||
|
||||
Iterator& operator++() {
|
||||
this->mIter++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const Iterator& left) const { return left.mIter == this->mIter; }
|
||||
bool operator!=(const Iterator& left) const { return left.mIter != this->mIter; }
|
||||
};
|
||||
|
||||
[[nodiscard]] Iterator begin() const {
|
||||
return Iterator(mBuff);
|
||||
}
|
||||
|
||||
[[nodiscard]] Iterator end() const {
|
||||
return Iterator(mBuff + mLoad);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
template<class tArchiver>
|
||||
void archiveWrite(tArchiver& ar) const {
|
||||
ar << mLoad;
|
||||
for (auto item : *this) {
|
||||
ar << item.data();
|
||||
}
|
||||
}
|
||||
|
||||
template<class tArchiver>
|
||||
void archiveRead(tArchiver& ar) {
|
||||
clear();
|
||||
decltype(mLoad) len;
|
||||
ar >> len;
|
||||
for (auto i = len; i; i--) {
|
||||
// TODO : optimize
|
||||
if (mLoad == mSize) resizeBuffer(tResizePolicy(mSize));
|
||||
ar >> mBuff[mLoad];
|
||||
mLoad++;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void resizeBuffer(ualni newSize) {
|
||||
|
|
@ -187,4 +374,36 @@ namespace tp {
|
|||
mSize = newSize;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename tType>
|
||||
void generatePermutations(const Buffer<Buffer<tType>>& in, Buffer<Buffer<tType>>& out) {
|
||||
typedef long long Idx;
|
||||
|
||||
// sanity check
|
||||
for (const auto & vec : in) {
|
||||
if (!vec.size()) return;
|
||||
}
|
||||
|
||||
out.resize(in.size());
|
||||
auto len = Idx(1);
|
||||
for (const auto & vec : in) len *= (Idx) vec.size();
|
||||
for (auto i = 0; i < in.size(); i++) out[i].resize(len);
|
||||
|
||||
auto dub = Idx(1);
|
||||
for (auto power = (Idx) in.size() - 1; power >= 0; power--) {
|
||||
auto& vec = in[power];
|
||||
long long i = 0;
|
||||
while (i < len) {
|
||||
for (auto val : vec) {
|
||||
for (auto j = 0; j < dub; j++) {
|
||||
out[power][i] = val;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
dub *= (Idx) vec.size();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
112
Containers/public/Buffer2D.hpp
Normal file
112
Containers/public/Buffer2D.hpp
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
|
||||
#include "Buffer.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace tp {
|
||||
|
||||
template< typename tType, ualni tSizeX, ualni tSizeY >
|
||||
using ConstSizeBuffer2D = ConstSizeBuffer<ConstSizeBuffer<tType, tSizeX>, tSizeY>;
|
||||
|
||||
template <
|
||||
typename tType,
|
||||
class tAllocator = DefaultAllocator
|
||||
>
|
||||
class Buffer2D {
|
||||
public:
|
||||
typedef ualni Index;
|
||||
typedef Pair<Index, Index> Index2D;
|
||||
typedef SelectValueOrReference<tType> tTypeArg;
|
||||
|
||||
private:
|
||||
tAllocator mAlloc;
|
||||
tType* mBuff = nullptr;
|
||||
Index2D mSize = { 0, 0 };
|
||||
|
||||
void deleteBuffer() {
|
||||
if (!mBuff) return;
|
||||
for (ualni i = 0; i < mSize.x * mSize.y; i++) mBuff[i].~tType();
|
||||
mAlloc.deallocate(mBuff);
|
||||
}
|
||||
|
||||
void allocateBuffer(Index2D size) {
|
||||
deleteBuffer();
|
||||
mBuff = (tType*) mAlloc.allocate(sizeof(tType) * size.x * size.y);
|
||||
for (ualni i = 0; i < mSize.x * mSize.y; i++) new (mBuff + i) tType();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Buffer2D() = default;
|
||||
|
||||
~Buffer2D() {
|
||||
deleteBuffer();
|
||||
mSize = { 0, 0 };
|
||||
}
|
||||
|
||||
explicit Buffer2D(Index2D aSize) {
|
||||
reserve(aSize);
|
||||
}
|
||||
|
||||
[[nodiscard]] Index2D size() const {
|
||||
return { mSize.x, mSize.y };
|
||||
}
|
||||
|
||||
tType* getBuff() const {
|
||||
return mBuff;
|
||||
}
|
||||
|
||||
inline tType& get(const Index2D& at) {
|
||||
DEBUG_ASSERT(mBuff && at.x < mSize.x && at.y < mSize.y && at.x >= 0 && at.y >= 0)
|
||||
return *(mBuff + mSize.x * at.y + at.x);
|
||||
}
|
||||
|
||||
inline const tType& get(const Index2D& at) const {
|
||||
DEBUG_ASSERT(mBuff && at.x < mSize.x && at.y < mSize.y && at.x >= 0 && at.y >= 0)
|
||||
return *(mBuff + mSize.x * at.y + at.x);
|
||||
}
|
||||
|
||||
inline void set(const Index2D& at, tTypeArg value) {
|
||||
DEBUG_ASSERT(mBuff && at.x < mSize.x && at.y < mSize.y && at.x >= 0 && at.y >= 0)
|
||||
*(mBuff + mSize.x * at.y + at.x) = value;
|
||||
}
|
||||
|
||||
void reserve(const Index2D& newSize) {
|
||||
if (mSize.x != newSize.x || mSize.y != newSize.y) {
|
||||
allocateBuffer(newSize);
|
||||
mSize = newSize;
|
||||
}
|
||||
}
|
||||
|
||||
void assign(tType value) {
|
||||
DEBUG_ASSERT(mBuff);
|
||||
Index len = mSize.x * mSize.y;
|
||||
for (Index i = 0; i < len; i++) {
|
||||
mBuff[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
template<class tArchiver>
|
||||
void archiveWrite(tArchiver& ar) const {
|
||||
ar << mSize;
|
||||
for (auto i = 0; i < mSize.x; i++) {
|
||||
for (auto j = 0; j < mSize.y; j++) {
|
||||
ar << get(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class tArchiver>
|
||||
void archiveRead(tArchiver& ar) {
|
||||
decltype(mSize) size;
|
||||
deleteBuffer();
|
||||
ar >> size;
|
||||
reserve(size);
|
||||
for (auto i = 0; i < mSize.x; i++) {
|
||||
for (auto j = 0; j < mSize.y; j++) {
|
||||
ar >> get(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ namespace tp {
|
|||
template <typename Type, class Allocator = DefaultAllocator>
|
||||
class List {
|
||||
|
||||
typedef SelCopyArg<Type> TypeArg;
|
||||
typedef SelectValueOrReference<Type> TypeArg;
|
||||
typedef ualni Index;
|
||||
|
||||
public:
|
||||
|
|
@ -72,8 +72,8 @@ namespace tp {
|
|||
public:
|
||||
|
||||
List() = default;
|
||||
|
||||
List(const init_list<Type>& list) { operator=(list); }
|
||||
List(const List& in) { this->operator=(in); }
|
||||
List(const InitialierList<Type>& list) { operator=(list); }
|
||||
|
||||
[[nodiscard]] inline Node* first() const { return mFirst; }
|
||||
[[nodiscard]] inline Node* last() const { return mLast; }
|
||||
|
|
@ -146,7 +146,7 @@ namespace tp {
|
|||
}
|
||||
|
||||
[[nodiscard]] Node* findIdx(Index idx) const {
|
||||
DEBUG_ASSERT(!mFirst || idx > mLength - 1)
|
||||
DEBUG_ASSERT(mFirst && idx < mLength && idx >= 0)
|
||||
Node* found = mFirst;
|
||||
for (int i = 0; i != idx; i++) {
|
||||
found = found->next;
|
||||
|
|
@ -157,6 +157,7 @@ namespace tp {
|
|||
[[nodiscard]] Node* find(const TypeArg data) const {
|
||||
Node* found = mFirst;
|
||||
for (alni i = 0; data != found->data; i++) {
|
||||
if (i == length()) return nullptr;
|
||||
if (!found->next) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -177,8 +178,9 @@ namespace tp {
|
|||
|
||||
void popBack() {
|
||||
DEBUG_ASSERT(mLast)
|
||||
auto const tmp = mLast;
|
||||
detach(mLast);
|
||||
deleteNode(mLast);
|
||||
deleteNode(tmp);
|
||||
}
|
||||
|
||||
void popFront() {
|
||||
|
|
@ -221,7 +223,7 @@ namespace tp {
|
|||
return *this;
|
||||
}
|
||||
|
||||
List& operator+=(const init_list<Type>& list) {
|
||||
List& operator+=(const InitialierList<Type>& list) {
|
||||
for (auto item : list) {
|
||||
pushBack(item);
|
||||
}
|
||||
|
|
@ -235,14 +237,14 @@ namespace tp {
|
|||
return *this;
|
||||
}
|
||||
|
||||
List& operator=(const init_list<Type>& list) {
|
||||
List& operator=(const InitialierList<Type>& list) {
|
||||
removeAll();
|
||||
*this += list;
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool operator==(const List& in) const {
|
||||
if (in == *this) { return true; }
|
||||
if (&in == this) { return true; }
|
||||
if (in.length() != length()) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -252,6 +254,8 @@ namespace tp {
|
|||
if (left->data != right->data) {
|
||||
return false;
|
||||
}
|
||||
left = left->next;
|
||||
right = right->next;
|
||||
}
|
||||
if (left != right) {
|
||||
return false;
|
||||
|
|
@ -295,22 +299,23 @@ namespace tp {
|
|||
}
|
||||
}
|
||||
|
||||
template<class Saver>
|
||||
void write(Saver& file) const {
|
||||
file.write(mLength);
|
||||
public:
|
||||
template<class tArchiver>
|
||||
void archiveWrite(tArchiver& ar) const {
|
||||
ar << mLength;
|
||||
for (auto item : *this) {
|
||||
file.write(item.data());
|
||||
ar << item.data();
|
||||
}
|
||||
}
|
||||
|
||||
template<class Loader>
|
||||
void read(Loader& file) {
|
||||
template<class tArchiver>
|
||||
void archiveRead(tArchiver& ar) {
|
||||
removeAll();
|
||||
ualni len;
|
||||
file.read(len);
|
||||
decltype(mLength) len;
|
||||
ar >> len;
|
||||
for (auto i = len; i; i--) {
|
||||
auto node = newNodeNotConstructed();
|
||||
file.read(node->data);
|
||||
ar >> node->data;
|
||||
pushBack(node);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
namespace tp {
|
||||
|
||||
template<typename Key>
|
||||
ualni DefaultHashFunc(SelCopyArg<Key> key) {
|
||||
ualni DefaultHashFunc(SelectValueOrReference<Key> key) {
|
||||
return hash(key);
|
||||
}
|
||||
|
||||
template<typename tKey, typename tVal, class tAllocator = DefaultAllocator, ualni(*tHashFunc)(SelCopyArg<tKey>) = DefaultHashFunc<tKey>, int tTableInitialSize = 4>
|
||||
template<typename tKey, typename tVal, class tAllocator = DefaultAllocator, ualni(*tHashFunc)(SelectValueOrReference<tKey>) = DefaultHashFunc<tKey>, int tTableInitialSize = 4>
|
||||
class Map {
|
||||
|
||||
enum {
|
||||
|
|
@ -20,8 +20,8 @@ namespace tp {
|
|||
MAP_MAX_LOAD_PERCENTAGE = 66,
|
||||
};
|
||||
|
||||
typedef SelCopyArg<tKey> KeyArg;
|
||||
typedef SelCopyArg<tVal> ValArg;
|
||||
typedef SelectValueOrReference<tKey> KeyArg;
|
||||
typedef SelectValueOrReference<tVal> ValArg;
|
||||
|
||||
public:
|
||||
|
||||
|
|
@ -35,12 +35,13 @@ namespace tp {
|
|||
|
||||
struct Idx {
|
||||
alni idx = -1;
|
||||
operator bool() { return idx != -1; }
|
||||
[[nodiscard]] bool isValid() const { return bool(*this); }
|
||||
explicit operator bool() const { return idx != -1; }
|
||||
};
|
||||
|
||||
private:
|
||||
tAllocator mAlloc;
|
||||
Node** mTable;
|
||||
Node** mTable = nullptr;
|
||||
ualni mNSlots = 0;
|
||||
ualni mNEntries = 0;
|
||||
|
||||
|
|
@ -180,6 +181,10 @@ namespace tp {
|
|||
mTable = newTable(mNSlots);
|
||||
}
|
||||
|
||||
Map(const Map& in) {
|
||||
this->operator=(in);
|
||||
}
|
||||
|
||||
Node** buff() const {
|
||||
return mTable;
|
||||
}
|
||||
|
|
@ -201,8 +206,9 @@ namespace tp {
|
|||
if (!mTable[idx] || isDeletedNode(mTable[idx])) {
|
||||
mTable[idx] = newNode(key, val);
|
||||
mNEntries++;
|
||||
}
|
||||
} else {
|
||||
mTable[idx]->val = val;
|
||||
}
|
||||
if ((halnf) mNEntries / mNSlots > maxLoadFactor()) {
|
||||
rehash();
|
||||
}
|
||||
|
|
@ -247,7 +253,7 @@ namespace tp {
|
|||
|
||||
const tVal& getSlotVal(Idx slot) const {
|
||||
DEBUG_ASSERT(slot.idx < mNSlots && (mTable[slot.idx] && !isDeletedNode(mTable[slot.idx])) && "Key Error")
|
||||
return mTable[slot]->val;
|
||||
return mTable[slot.idx]->val;
|
||||
}
|
||||
|
||||
tVal& getSlotVal(Idx slot) {
|
||||
|
|
@ -365,28 +371,35 @@ namespace tp {
|
|||
return mNSlots;
|
||||
}
|
||||
|
||||
template<class Saver>
|
||||
void write(Saver& file) {
|
||||
file.write(mNEntries);
|
||||
template<class Archiver>
|
||||
void archiveWrite(Archiver& ar) const {
|
||||
ar << mNEntries;
|
||||
for (auto item : *this) {
|
||||
file.write(item->val);
|
||||
file.write(item->key);
|
||||
ar << item->val;
|
||||
ar << item->key;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Loader>
|
||||
void read(Loader& file) {
|
||||
template<class Archiver>
|
||||
void archiveRead(Archiver& ar) {
|
||||
removeAll();
|
||||
ualni len;
|
||||
file.read(len);
|
||||
decltype(mNSlots) len;
|
||||
ar >> len;
|
||||
for (auto i = len; i; i--) {
|
||||
auto node = newNodeNotConstructed();
|
||||
file.read(node->val);
|
||||
file.read(node->key);
|
||||
ar >> node->val;
|
||||
ar >> node->key;
|
||||
put(node);
|
||||
}
|
||||
}
|
||||
|
||||
~Map() { removeAll(); }
|
||||
~Map() {
|
||||
for (ualni i = 0; i < mNSlots; i++) {
|
||||
if (mTable[i] && !isDeletedNode(mTable[i])) {
|
||||
deleteNode(mTable[i]);
|
||||
}
|
||||
}
|
||||
deleteTable(mTable);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -25,8 +25,8 @@ namespace tp {
|
|||
|
||||
template <typename Key, typename Data, class Allocator = DefaultAllocator>
|
||||
class AvlTree {
|
||||
typedef SelCopyArg<Key> KeyArg;
|
||||
typedef SelCopyArg<Data> DataArg;
|
||||
typedef SelectValueOrReference<Key> KeyArg;
|
||||
typedef SelectValueOrReference<Data> DataArg;
|
||||
|
||||
public:
|
||||
class Node {
|
||||
|
|
@ -369,5 +369,32 @@ namespace tp {
|
|||
}
|
||||
|
||||
bool isValid() { return findInvalidNode(head()) == nullptr; }
|
||||
|
||||
template<typename tFunctor>
|
||||
void traverse(Node* node, bool after, tFunctor functor) {
|
||||
if (!after) functor(node);
|
||||
if (node->mLeft) traverse(node->mLeft, after, functor);
|
||||
if (node->mRight) traverse(node->mRight, after, functor);
|
||||
if (after) functor(node);
|
||||
}
|
||||
|
||||
void removeAll() {
|
||||
traverse(mRoot, true, [this](Node* node) {
|
||||
deleteNode(node);
|
||||
});
|
||||
mRoot = nullptr;
|
||||
mSize = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
template<class tArchiver>
|
||||
void archiveWrite(tArchiver& file) const {
|
||||
FAIL("not implemented")
|
||||
}
|
||||
|
||||
template<class tArchiver>
|
||||
void archiveRead(tArchiver&) {
|
||||
FAIL("not implemented")
|
||||
}
|
||||
};
|
||||
}
|
||||
25
Containers/tests/Buffer2DTest.cpp
Normal file
25
Containers/tests/Buffer2DTest.cpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#include "NewPlacement.hpp"
|
||||
|
||||
#include "Tests.hpp"
|
||||
#include "Testing.hpp"
|
||||
#include "Buffer2D.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
const ualni size = 1000;
|
||||
|
||||
TEST_DEF_STATIC(Simple1) {
|
||||
Buffer2D<int, HeapAlloc> buff;
|
||||
buff.reserve({ 4, 4 });
|
||||
buff.set( { 2, 2 }, 5);
|
||||
TEST(buff.get( { 2, 2 } ) == 5);
|
||||
}
|
||||
|
||||
TEST_DEF_STATIC(Simple2) {
|
||||
// TEST(false);
|
||||
}
|
||||
|
||||
TEST_DEF(Buffer2d) {
|
||||
testSimple1();
|
||||
testSimple2();
|
||||
}
|
||||
|
|
@ -1,18 +1,15 @@
|
|||
#include "NewPlacement.hpp"
|
||||
|
||||
#include "Tests.hpp"
|
||||
|
||||
#include "Buffer.hpp"
|
||||
|
||||
#include "Testing.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace tp;
|
||||
|
||||
const ualni size = 1000;
|
||||
|
||||
TEST_DEF_STATIC(Simple1) {
|
||||
Buffer<TestClass> buff;
|
||||
Buffer<TestClass, HeapAlloc> buff;
|
||||
TEST(buff.size() == 0);
|
||||
for (auto i : Range(size * 10)) {
|
||||
buff.append(TestClass(i));
|
||||
|
|
@ -23,7 +20,7 @@ TEST_DEF_STATIC(Simple1) {
|
|||
}
|
||||
|
||||
TEST_DEF_STATIC(Simple2) {
|
||||
Buffer<TestClass> buff(size);
|
||||
Buffer<TestClass, HeapAlloc> buff(size);
|
||||
TEST(buff.size() == 0);
|
||||
for (auto i : Range(size * 10)) buff.append(TestClass(i));
|
||||
TEST(buff.size() == size * 10);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
#include "NewPlacement.hpp"
|
||||
|
||||
#include "Tests.hpp"
|
||||
#include "Testing.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include "Archiver.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
TEST_DEF_STATIC(SimpleReference) {
|
||||
tp::List<TestClass, TestAllocator> list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) };
|
||||
tp::List<TestClass, HeapAlloc> list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) };
|
||||
|
||||
list.pushBack(TestClass(5));
|
||||
list.pushFront(TestClass(0));
|
||||
|
|
@ -21,11 +21,10 @@ TEST_DEF_STATIC(SimpleReference) {
|
|||
TEST(i == 5);
|
||||
|
||||
list.removeAll();
|
||||
TEST(list.getAllocator().getAllocationsCount() == 0);
|
||||
}
|
||||
|
||||
TEST_DEF_STATIC(SimplePointer) {
|
||||
tp::List<TestClass*, TestAllocator> list = { new TestClass(1), new TestClass(2), new TestClass(3), new TestClass(4) };
|
||||
tp::List<TestClass*, HeapAlloc> list = { new TestClass(1), new TestClass(2), new TestClass(3), new TestClass(4) };
|
||||
|
||||
list.pushBack(new TestClass(5));
|
||||
list.pushFront(new TestClass(0));
|
||||
|
|
@ -38,36 +37,36 @@ TEST_DEF_STATIC(SimplePointer) {
|
|||
|
||||
TEST(i == 5);
|
||||
|
||||
list.removeAll();
|
||||
for (auto iter : list) {
|
||||
delete iter.data();
|
||||
}
|
||||
|
||||
TEST(list.getAllocator().getAllocationsCount() == 0);
|
||||
list.removeAll();
|
||||
}
|
||||
|
||||
TEST_DEF_STATIC(Copy) {
|
||||
tp::List<TestClass, TestAllocator> list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) };
|
||||
tp::List<TestClass, TestAllocator> list2 = list;
|
||||
tp::List<TestClass, HeapAlloc> list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) };
|
||||
tp::List<TestClass, HeapAlloc> list2 = list;
|
||||
|
||||
TEST_EQUAL(list, list2);
|
||||
|
||||
list.removeAll();
|
||||
list2.removeAll();
|
||||
|
||||
TEST(list.getAllocator().getAllocationsCount() == 0);
|
||||
TEST(list2.getAllocator().getAllocationsCount() == 0);
|
||||
}
|
||||
|
||||
TEST_DEF_STATIC(SaveLoad) {
|
||||
tp::List<TestClass, TestAllocator> list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) };
|
||||
TEST_DEF_STATIC(Serialization) {
|
||||
tp::List<TestClass, HeapAlloc> list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) };
|
||||
|
||||
TestFile file;
|
||||
ArchiverExample<1024, false> write;
|
||||
ArchiverExample<1024, true> read;
|
||||
|
||||
list.write(file);
|
||||
write % list;
|
||||
|
||||
list.removeAll();
|
||||
|
||||
file.setAddress(0);
|
||||
memCopy(read.mBuff, write.mBuff, sizeof(write.mBuff));
|
||||
|
||||
list.read(file);
|
||||
read % list;
|
||||
|
||||
ualni i = 0;
|
||||
for (auto iter : list) {
|
||||
|
|
@ -77,12 +76,10 @@ TEST_DEF_STATIC(SaveLoad) {
|
|||
TEST(i == 4);
|
||||
|
||||
list.removeAll();
|
||||
|
||||
TEST(list.getAllocator().getAllocationsCount() == 0);
|
||||
}
|
||||
|
||||
TEST_DEF(List) {
|
||||
testSimplePointer();
|
||||
testSimpleReference();
|
||||
testSaveLoad();
|
||||
testSerialization();
|
||||
}
|
||||
|
|
@ -1,15 +1,14 @@
|
|||
#include "NewPlacement.hpp"
|
||||
|
||||
#include "Tests.hpp"
|
||||
#include "Testing.hpp"
|
||||
|
||||
#include "Map.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include "Archiver.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
TEST_DEF_STATIC(SimpleReference) {
|
||||
tp::Map<tp::ualni, TestClass, TestAllocator> map;
|
||||
tp::Map<tp::ualni, TestClass, HeapAlloc> map;
|
||||
|
||||
for (auto i : Range(1000, 100000)) {
|
||||
map.put(i, TestClass(i));
|
||||
|
|
@ -40,12 +39,10 @@ TEST_DEF_STATIC(SimpleReference) {
|
|||
}
|
||||
|
||||
map.removeAll();
|
||||
|
||||
TEST(map.getAllocator().getAllocationsCount() == 1);
|
||||
}
|
||||
|
||||
TEST_DEF_STATIC(SimplePointer) {
|
||||
tp::Map<tp::ualni, TestClass*, TestAllocator> map;
|
||||
tp::Map<tp::ualni, TestClass*, HeapAlloc> map;
|
||||
|
||||
for (auto i : Range(1000)) {
|
||||
map.put(i, new TestClass(i));
|
||||
|
|
@ -57,11 +54,14 @@ TEST_DEF_STATIC(SimplePointer) {
|
|||
}
|
||||
|
||||
for (auto i : Range(1000)) {
|
||||
auto del = map.get(i);
|
||||
map.put(i, new TestClass(i));
|
||||
delete del;
|
||||
}
|
||||
|
||||
for (auto i : Range(900, 1000)) {
|
||||
TEST(map.presents(i));
|
||||
delete map.get(i);
|
||||
map.remove(i);
|
||||
TEST(!map.presents(i));
|
||||
}
|
||||
|
|
@ -77,48 +77,44 @@ TEST_DEF_STATIC(SimplePointer) {
|
|||
}
|
||||
|
||||
map.removeAll();
|
||||
|
||||
TEST(map.getAllocator().getAllocationsCount() == 1);
|
||||
}
|
||||
|
||||
TEST_DEF_STATIC(Copy) {
|
||||
tp::Map<tp::ualni, TestClass, TestAllocator> map;
|
||||
tp::Map<tp::ualni, TestClass, HeapAlloc> map;
|
||||
|
||||
for (auto i : Range(10)) {
|
||||
map.put(i, TestClass(i));
|
||||
}
|
||||
|
||||
tp::Map<tp::ualni, TestClass, TestAllocator> map2 = map;
|
||||
tp::Map<tp::ualni, TestClass, HeapAlloc> map2 = map;
|
||||
|
||||
TEST_EQUAL(map, map2);
|
||||
|
||||
map.removeAll();
|
||||
map2.removeAll();
|
||||
|
||||
TEST(map.getAllocator().getAllocationsCount() == 1);
|
||||
TEST(map2.getAllocator().getAllocationsCount() == 1);
|
||||
}
|
||||
|
||||
TEST_DEF_STATIC(SaveLoad) {
|
||||
tp::Map<tp::ualni, TestClass, TestAllocator> map;
|
||||
tp::Map<tp::ualni, TestClass, HeapAlloc> map;
|
||||
|
||||
for (auto i : Range(10)) {
|
||||
map.put(i, TestClass(i));
|
||||
}
|
||||
|
||||
TestFile file;
|
||||
ArchiverExample<1024, false> write;
|
||||
ArchiverExample<1024, true> read;
|
||||
|
||||
map.write(file);
|
||||
write % map;
|
||||
|
||||
map.removeAll();
|
||||
|
||||
TEST(map.getAllocator().getAllocationsCount() == 1);
|
||||
TEST(map.size() == 0);
|
||||
|
||||
file.setAddress(0);
|
||||
memCopy(read.mBuff, write.mBuff, sizeof(write.mBuff));
|
||||
|
||||
map.read(file);
|
||||
read % map;
|
||||
|
||||
TEST(map.getAllocator().getAllocationsCount() == 11);
|
||||
TEST(map.size() == 10);
|
||||
|
||||
for (auto i : Range(10)) {
|
||||
TEST(map.presents(i));
|
||||
|
|
@ -126,8 +122,6 @@ TEST_DEF_STATIC(SaveLoad) {
|
|||
}
|
||||
|
||||
map.removeAll();
|
||||
|
||||
TEST(map.getAllocator().getAllocationsCount() == 1);
|
||||
}
|
||||
|
||||
TEST_DEF(Map) {
|
||||
|
|
|
|||
|
|
@ -1,32 +1,15 @@
|
|||
|
||||
#include "Tests.hpp"
|
||||
|
||||
#include "Testing.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
static bool init(const tp::ModuleManifest* self) {
|
||||
tp::gTesting.setRootName(self->getName());
|
||||
return true;
|
||||
}
|
||||
|
||||
void* TestAllocator::allocate(tp::ualni size) {
|
||||
nAllocations++;
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void TestAllocator::deallocate(void* p) {
|
||||
nAllocations--;
|
||||
free(p);
|
||||
}
|
||||
|
||||
tp::ualni TestAllocator::getAllocationsCount() const {
|
||||
return nAllocations;
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
tp::ModuleManifest* deps[] = { &tp::gModuleContainers, &tp::gModuleUtils, nullptr };
|
||||
tp::ModuleManifest* deps[] = { &tp::gModuleUtils, &tp::gModuleAllocators, nullptr };
|
||||
tp::ModuleManifest testModule("ContainersTest", init, nullptr, deps);
|
||||
|
||||
if (!testModule.initialize()) {
|
||||
|
|
@ -37,6 +20,7 @@ int main() {
|
|||
testMap();
|
||||
testAvl();
|
||||
testBuffer();
|
||||
testBuffer2d();
|
||||
|
||||
testModule.deinitialize();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "Utils.hpp"
|
||||
#include "Allocators.hpp"
|
||||
|
||||
class TestClass {
|
||||
tp::ualni val2 = 0;
|
||||
|
|
@ -27,48 +28,9 @@ public:
|
|||
void setVal(tp::ualni val) { val1 = val; }
|
||||
};
|
||||
|
||||
class TestAllocator {
|
||||
tp::ualni nAllocations = 0;
|
||||
public:
|
||||
TestAllocator() = default;
|
||||
void* allocate(tp::ualni size);
|
||||
void deallocate(void* p);
|
||||
[[nodiscard]] tp::ualni getAllocationsCount() const;
|
||||
};
|
||||
|
||||
class TestFile {
|
||||
tp::ualni mem[1024] = { 0 };
|
||||
tp::ualni address = 0;
|
||||
|
||||
public:
|
||||
TestFile() = default;
|
||||
|
||||
template<typename Type>
|
||||
void write(const Type& val) {
|
||||
val.write(*this);
|
||||
}
|
||||
|
||||
template<>
|
||||
void write<tp::ualni>(const tp::ualni& val) {
|
||||
mem[address] = val;
|
||||
address++;
|
||||
}
|
||||
|
||||
void setAddress(tp::ualni addr) { address = addr; }
|
||||
|
||||
template<typename Type>
|
||||
void read(Type& val) {
|
||||
val.read(*this);
|
||||
}
|
||||
|
||||
template<>
|
||||
void read<tp::ualni>(tp::ualni& val) {
|
||||
val = mem[address];
|
||||
address++;
|
||||
}
|
||||
};
|
||||
|
||||
void testList();
|
||||
void testMap();
|
||||
void testAvl();
|
||||
void testBuffer();
|
||||
void testBuffer2d();
|
||||
|
|
@ -1,16 +1,13 @@
|
|||
#include "NewPlacement.hpp"
|
||||
|
||||
#include "Tests.hpp"
|
||||
|
||||
#include "Tree.hpp"
|
||||
|
||||
#include "Testing.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace tp;
|
||||
|
||||
TEST_DEF_STATIC(Simple) {
|
||||
AvlTree<AvlNumericKey<alni>, TestClass, TestAllocator> tree;
|
||||
AvlTree<AvlNumericKey<alni>, TestClass, HeapAlloc> tree;
|
||||
|
||||
TEST(tree.size() == 0);
|
||||
TEST(tree.head() == nullptr);
|
||||
|
|
@ -27,7 +24,7 @@ TEST_DEF_STATIC(Simple) {
|
|||
}
|
||||
|
||||
TEST_DEF_STATIC(Persistance) {
|
||||
AvlTree<AvlNumericKey<alni>, TestClass, TestAllocator> tree;
|
||||
AvlTree<AvlNumericKey<alni>, TestClass, HeapAlloc> tree;
|
||||
|
||||
const auto size = 1000;
|
||||
|
||||
|
|
@ -46,7 +43,7 @@ TEST_DEF_STATIC(Persistance) {
|
|||
// random load
|
||||
ualni loadSize = 0;
|
||||
while (loadSize < size / 2) {
|
||||
ualni idx = rand() % (size - 1);
|
||||
auto idx = ualni(randomFloat() * (size - 1));
|
||||
DEBUG_ASSERT(idx < size)
|
||||
if (!buff[idx].presents) {
|
||||
tree.insert((alni) buff[idx].data.getVal(), buff[idx].data);
|
||||
|
|
@ -86,7 +83,7 @@ TEST_DEF_STATIC(Persistance) {
|
|||
// random unload
|
||||
ualni unloadSize = 0;
|
||||
while (unloadSize < size / 2) {
|
||||
ualni idx = rand() % (size - 1);
|
||||
auto idx = ualni(randomFloat() * (size - 1));
|
||||
if (buff[idx].presents) {
|
||||
|
||||
tree.remove((alni) buff[idx].data.getVal());
|
||||
|
|
|
|||
28
Externals/CMakeLists.txt
vendored
Normal file
28
Externals/CMakeLists.txt
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
add_subdirectory(glew/build/cmake/)
|
||||
target_compile_definitions(glew_s PUBLIC GLEW_NO_GLU)
|
||||
|
||||
add_subdirectory(glfw)
|
||||
|
||||
project(Imgui)
|
||||
set(${PROJECT_NAME}_SOURCES
|
||||
imgui/imgui.cpp
|
||||
imgui/imgui_draw.cpp
|
||||
imgui/imgui_tables.cpp
|
||||
imgui/imgui_widgets.cpp
|
||||
|
||||
imgui/backends/imgui_impl_glfw.cpp
|
||||
imgui/backends/imgui_impl_opengl3.cpp
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC ${${PROJECT_NAME}_SOURCES})
|
||||
include_directories(${PROJECT_NAME} ./glfw/include)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ./imgui/ ./imgui/backends/)
|
||||
|
||||
project(Nanovg)
|
||||
set(${PROJECT_NAME}_SOURCES
|
||||
nanovg/src/nanovg.c
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC ${${PROJECT_NAME}_SOURCES})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ./nanovg/src/ ./nanovg/obsolete/)
|
||||
1
Externals/asio
vendored
Submodule
1
Externals/asio
vendored
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit d6b95c0188e0359a8cdbdb6571f0cbacf11a538c
|
||||
1
Externals/glew
vendored
Submodule
1
Externals/glew
vendored
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit a98195b83df746202bdf5a6f92e9d4e86b497045
|
||||
1
Externals/glfw
vendored
Submodule
1
Externals/glfw
vendored
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 3eaf1255b29fdf5c2895856c7be7d7185ef2b241
|
||||
1
Externals/imgui
vendored
Submodule
1
Externals/imgui
vendored
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 4144d7d772a800f08693b8b13f7c81f1f22a73c4
|
||||
1
Externals/nanovg
vendored
Submodule
1
Externals/nanovg
vendored
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 7544c114e83db7cf67bd1c9e012349b70caacc2f
|
||||
34
Graphics/CMakeLists.txt
Normal file
34
Graphics/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
project(Graphics)
|
||||
|
||||
### ---------------------- Externals --------------------- ###
|
||||
set(BINDINGS_INCLUDE ${EXTERNALS}/glfw/include ${EXTERNALS}/glew/include)
|
||||
set(BINDINGS_LIBS glfw glew_s Imgui Nanovg)
|
||||
|
||||
|
||||
### ---------------------- Static Library --------------------- ###
|
||||
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
|
||||
file(GLOB HEADERS "./public/*.hpp")
|
||||
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${BINDINGS_INCLUDE})
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Strings Math Utils)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${BINDINGS_LIBS})
|
||||
|
||||
### -------------------------- Examples -------------------------- ###
|
||||
add_executable(${PROJECT_NAME}Example ./examples/Example.cpp)
|
||||
target_link_libraries(${PROJECT_NAME}Example ${PROJECT_NAME} ${BINDINGS_LIBS})
|
||||
target_include_directories(${PROJECT_NAME}Example PRIVATE ${BINDINGS_INCLUDE})
|
||||
|
||||
### -------------------------- Tests -------------------------- ###
|
||||
enable_testing()
|
||||
file(GLOB TEST_SOURCES "./tests/*.cpp")
|
||||
add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES})
|
||||
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Utils)
|
||||
add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests)
|
||||
|
||||
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/lib)
|
||||
31
Graphics/examples/Example.cpp
Normal file
31
Graphics/examples/Example.cpp
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
#include "Window.hpp"
|
||||
|
||||
#include "imgui.h"
|
||||
|
||||
int main() {
|
||||
tp::ModuleManifest* deps[] = { &tp::gModuleGraphics, nullptr };
|
||||
tp::ModuleManifest testModule("Example", nullptr, nullptr, deps);
|
||||
|
||||
if (!testModule.initialize()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
auto window = tp::Window::createWindow(800, 600, "Window 1");
|
||||
|
||||
if (window) {
|
||||
while (!window->shouldClose()) {
|
||||
window->processEvents();
|
||||
|
||||
window->getGraphics().getDebugGui().drawDebugInfoWindow();
|
||||
|
||||
window->draw();
|
||||
}
|
||||
}
|
||||
|
||||
tp::Window::destroyWindow(window);
|
||||
}
|
||||
|
||||
testModule.deinitialize();
|
||||
}
|
||||
104
Graphics/private/Animations.cpp
Normal file
104
Graphics/private/Animations.cpp
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
|
||||
#include "Animations.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
bool AnimValue::gInTransition = false;
|
||||
|
||||
halnf AnimValue::interpolate() const {
|
||||
if (!mTimeAnim) {
|
||||
return mVal;
|
||||
}
|
||||
|
||||
auto dt = gCurrentTime - mTimeStart;
|
||||
if (dt > mTimeAnim) dt = mTimeAnim;
|
||||
auto t = (halnf)dt / (halnf)mTimeAnim;
|
||||
t = (halnf)(0.511 + atan((t - 0.36) * 28) / 2.9);
|
||||
t = clamp(t, 0.f, 1.f);
|
||||
auto out = mValPrev + (mVal - mValPrev) * t;
|
||||
return out;
|
||||
}
|
||||
|
||||
AnimValue::AnimValue() = default;
|
||||
|
||||
void AnimValue::setAnimTime(halni time) {
|
||||
mTimeAnim = time;
|
||||
}
|
||||
|
||||
AnimValue::AnimValue(halnf val) {
|
||||
mVal = val;
|
||||
mValPrev = mVal;
|
||||
mTimeStart = gCurrentTime;
|
||||
}
|
||||
|
||||
bool AnimValue::inTransition() const {
|
||||
auto timePassed = gCurrentTime - mTimeStart >= mTimeAnim;
|
||||
return !timePassed;
|
||||
}
|
||||
|
||||
void AnimValue::set(halnf val) {
|
||||
if (!inTransition()) mValPrev = mVal;
|
||||
if (val == mVal) return;
|
||||
mValPrev = get();
|
||||
mVal = val;
|
||||
if (!inTransition()) mTimeStart = (halni)gCurrentTime;
|
||||
}
|
||||
|
||||
halnf AnimValue::getTarget() const {
|
||||
return mVal;
|
||||
}
|
||||
|
||||
void AnimValue::setNoTransition(halnf val) {
|
||||
mValPrev = val;
|
||||
mVal = val;
|
||||
mTimeStart -= mTimeStart;
|
||||
}
|
||||
|
||||
halnf AnimValue::get() const {
|
||||
if (inTransition()) {
|
||||
gInTransition = true;
|
||||
}
|
||||
return interpolate();
|
||||
}
|
||||
|
||||
AnimValue::operator halnf() const {
|
||||
return get();
|
||||
}
|
||||
|
||||
RectF AnimRect::get() const {
|
||||
return { x.get(), y.get() , z.get(), w.get() };
|
||||
}
|
||||
|
||||
RectF AnimRect::getTarget() const {
|
||||
return { x.getTarget(), y.getTarget() , z.getTarget(), w.getTarget() };
|
||||
}
|
||||
|
||||
void AnimRect::setNoTransition(RectF rec) {
|
||||
x.setNoTransition(rec.x);
|
||||
y.setNoTransition(rec.y);
|
||||
z.setNoTransition(rec.z);
|
||||
w.setNoTransition(rec.w);
|
||||
}
|
||||
|
||||
void AnimRect::setAnimTime(const halni time) {
|
||||
x.setAnimTime(time);
|
||||
y.setAnimTime(time);
|
||||
z.setAnimTime(time);
|
||||
w.setAnimTime(time);
|
||||
}
|
||||
|
||||
void AnimRect::set(const RectF& in) {
|
||||
x.set(in.x);
|
||||
y.set(in.y);
|
||||
z.set(in.z);
|
||||
w.set(in.w);
|
||||
}
|
||||
|
||||
RGBA AnimColor::get() const {
|
||||
auto col = mColor.get();
|
||||
return {col.x, col.y, col.z, col.w};
|
||||
}
|
||||
|
||||
void AnimColor::set(const RGBA& col) {
|
||||
mColor.set(RectF(col.r, col.g, col.b, col.a));
|
||||
}
|
||||
6
Graphics/private/GraphicsCommon.cpp
Normal file
6
Graphics/private/GraphicsCommon.cpp
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#include "GraphicsCommon.hpp"
|
||||
|
||||
namespace tp {
|
||||
static ModuleManifest* deps[] = { &gModuleStrings, &gModuleMath, nullptr };
|
||||
ModuleManifest gModuleGraphics = ModuleManifest("Graphics", nullptr, nullptr, deps);
|
||||
}
|
||||
59
Graphics/private/bindings/Canvas.cpp
Normal file
59
Graphics/private/bindings/Canvas.cpp
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
#include "Window.hpp"
|
||||
|
||||
// -------- OpenGL -------- //
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "WindowContext.hpp"
|
||||
|
||||
// -------- Canvas -------- //
|
||||
#define NANOVG_GL3_IMPLEMENTATION
|
||||
#include <nanovg.h>
|
||||
#include <nanovg_gl.h>
|
||||
|
||||
namespace tp {
|
||||
class Graphics::Canvas::Context {
|
||||
public:
|
||||
NVGcontext* vg;
|
||||
};
|
||||
}
|
||||
|
||||
using namespace tp;
|
||||
|
||||
Graphics::Canvas::Canvas() {
|
||||
mContext = new Context();
|
||||
}
|
||||
|
||||
Graphics::Canvas::~Canvas() {
|
||||
delete mContext;
|
||||
}
|
||||
|
||||
void Graphics::Canvas::init() {
|
||||
mContext->vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
|
||||
}
|
||||
|
||||
void Graphics::Canvas::deinit() {
|
||||
// Cleanup
|
||||
nvgDeleteGL3(mContext->vg);
|
||||
}
|
||||
|
||||
void Graphics::Canvas::proc() {
|
||||
auto width = 600;
|
||||
auto height = 600;
|
||||
|
||||
// Start NanoVG rendering
|
||||
nvgBeginFrame(mContext->vg, width, height, 1.0);
|
||||
|
||||
// Draw a rectangle
|
||||
nvgBeginPath(mContext->vg);
|
||||
nvgRect(mContext->vg, 50, 50, 50, 50);
|
||||
nvgFillColor(mContext->vg, nvgRGBf(0.8f, 0.4f, 0.1f));
|
||||
nvgFill(mContext->vg);
|
||||
|
||||
// End NanoVG rendering
|
||||
nvgEndFrame(mContext->vg);
|
||||
}
|
||||
|
||||
void Graphics::Canvas::draw() {
|
||||
// End NanoVG rendering
|
||||
nvgEndFrame(mContext->vg);
|
||||
}
|
||||
278
Graphics/private/bindings/DebugGUI.cpp
Normal file
278
Graphics/private/bindings/DebugGUI.cpp
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
#include "Window.hpp"
|
||||
|
||||
#include "Timing.hpp"
|
||||
|
||||
#include "WindowContext.hpp"
|
||||
|
||||
// -------- Debug UI -------- //
|
||||
#include <imgui.h>
|
||||
#include <imgui_impl_glfw.h>
|
||||
#include <imgui_impl_opengl3.h>
|
||||
|
||||
#include "DefaultFont.bin"
|
||||
|
||||
namespace tp {
|
||||
class Graphics::GUI::Context {
|
||||
public:
|
||||
ImGuiIO* io{};
|
||||
ImGuiContext* ctx{};
|
||||
|
||||
halnf dpmm = 3;
|
||||
halnf uiScale = 1;
|
||||
halnf fontSizeMM = 2.55f;
|
||||
|
||||
Timer timer = Timer(1000);
|
||||
ualni fps {};
|
||||
ualni frames = 0;
|
||||
};
|
||||
}
|
||||
|
||||
using namespace tp;
|
||||
|
||||
Graphics::GUI::GUI() {
|
||||
mContext = new Context();
|
||||
}
|
||||
|
||||
Graphics::GUI::~GUI() {
|
||||
delete mContext;
|
||||
}
|
||||
|
||||
void Graphics::GUI::init(Window* window) {
|
||||
IMGUI_CHECKVERSION();
|
||||
|
||||
mContext->ctx = ImGui::CreateContext();
|
||||
mContext->io = &ImGui::GetIO();
|
||||
|
||||
mContext->io->ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
|
||||
// Initialize ImGui with GLFW and OpenGL
|
||||
ImGui_ImplGlfw_InitForOpenGL(window->getContext()->window, true);
|
||||
ImGui_ImplOpenGL3_Init("#version 330");
|
||||
|
||||
mContext->dpmm = (window->getMonitor().pixelSize.x / window->getMonitor().mmSize.x);
|
||||
|
||||
setStyle();
|
||||
}
|
||||
|
||||
void Graphics::GUI::deinit() {
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
}
|
||||
|
||||
void Graphics::GUI::proc() {
|
||||
tp::HeapAllocGlobal::startIgnore();
|
||||
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
tp::HeapAllocGlobal::stopIgnore();
|
||||
|
||||
// ImGui::DockSpaceOverViewport(NULL, ImGuiDockNodeFlags_PassthruCentralNode);
|
||||
}
|
||||
|
||||
void Graphics::GUI::draw() {
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
mContext->frames++;
|
||||
|
||||
if (mContext->timer.isTimeout()) {
|
||||
mContext->fps = mContext->frames;
|
||||
mContext->frames = 0;
|
||||
mContext->timer.reset();
|
||||
}
|
||||
}
|
||||
|
||||
halnf Graphics::GUI::getFontSize() const { return mContext->fontSizeMM; }
|
||||
halnf Graphics::GUI::getUIScale() const { return mContext->uiScale; }
|
||||
|
||||
void Graphics::GUI::setDPMM(ualni dpmm) {
|
||||
mContext->dpmm = dpmm;
|
||||
setStyle();
|
||||
}
|
||||
|
||||
void Graphics::GUI::setFontSize(ualni size) {
|
||||
mContext->fontSizeMM = size;
|
||||
setStyle();
|
||||
}
|
||||
|
||||
void Graphics::GUI::setUIScale(ualni scale) {
|
||||
mContext->uiScale = scale;
|
||||
setStyle();
|
||||
}
|
||||
|
||||
void Graphics::GUI::drawDebugInfoWindow() {
|
||||
ImGui::Begin("Debug Info");
|
||||
|
||||
ImGui::Text("FPS : %llu", mContext->fps);
|
||||
|
||||
ImGui::SliderFloat("UI Scale", &mContext->uiScale, 0, 10);
|
||||
ImGui::SliderFloat("Font Size MM", &mContext->fontSizeMM, 3, 20);
|
||||
ImGui::SliderFloat("DPMM", &mContext->dpmm, 2, 10);
|
||||
|
||||
setStyle();
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void Graphics::GUI::setStyle() {
|
||||
auto dpmm = mContext->dpmm;
|
||||
auto font_size_mm = mContext->fontSizeMM;
|
||||
auto ui_scale = mContext->uiScale;
|
||||
|
||||
#define VAL(val) (val * dpmm * ui_scale)
|
||||
#define VEC(x, y) ImVec2(x * dpmm, y * dpmm * ui_scale)
|
||||
|
||||
ImGuiStyle* style = &ImGui::GetStyle();
|
||||
auto& io = *mContext->io;
|
||||
bool first_init = io.Fonts->Fonts.Size == 0;
|
||||
auto font_path = ".";
|
||||
//auto font_path = getFontPath();
|
||||
|
||||
// supports PDMM from 0.3 to 10
|
||||
const float min_dpmm = 0.3f;
|
||||
const float max_dpmm = 20.f;
|
||||
dpmm = tp::clamp(dpmm, min_dpmm, max_dpmm);
|
||||
|
||||
// calc font
|
||||
const float font_size_mm_max = 10;
|
||||
const float font_size_pixels_min = 9;
|
||||
float font_size_mm_min = font_size_pixels_min / dpmm;
|
||||
const int font_quality_steps = 3;
|
||||
font_size_mm = tp::clamp(font_size_mm, font_size_mm_min, font_size_mm_max);
|
||||
|
||||
float font_sizes[font_quality_steps];
|
||||
for (auto i = 0; i < font_quality_steps; i++) {
|
||||
auto mm = font_size_mm_min + (font_size_mm_max - font_size_mm_min) * tp::pow(((tp::halnf) (i + 1) / font_quality_steps), 3);
|
||||
font_sizes[i] = dpmm * mm;
|
||||
}
|
||||
|
||||
if (first_init) {
|
||||
for (auto i = 0; i < font_quality_steps; i++) {
|
||||
//io.Fonts->AddFontFromFileTTF(font_path, font_sizes[i] * 1);
|
||||
ImFontConfig font_cfg_template;
|
||||
font_cfg_template.FontDataOwnedByAtlas = false;
|
||||
io.Fonts->AddFontFromMemoryTTF(CONSOLAB_TTF, CONSOLAB_TTF_len, font_sizes[i] * 1, &font_cfg_template);
|
||||
}
|
||||
}
|
||||
|
||||
// select fonts
|
||||
auto const pixels_required = dpmm * font_size_mm;
|
||||
auto idx = -1;
|
||||
for (auto i = 0; i < font_quality_steps; i++) {
|
||||
idx = i;
|
||||
if (pixels_required <= font_sizes[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
io.FontDefault = io.Fonts->Fonts[idx];
|
||||
io.FontGlobalScale = font_size_mm / (font_size_mm_min + ((font_size_mm_max - font_size_mm_min) / font_quality_steps) * (idx + 1));
|
||||
io.FontGlobalScale = pixels_required / font_sizes[idx];
|
||||
|
||||
auto rounding = VAL(1);
|
||||
auto pudding = VEC(1, 1);
|
||||
|
||||
// style->WindowPadding = pudding;
|
||||
style->WindowRounding = rounding;
|
||||
//style->WindowMinSize = VEC(11, 11);
|
||||
style->ChildRounding = rounding;
|
||||
style->PopupRounding = rounding;
|
||||
style->FramePadding = pudding;
|
||||
style->FrameRounding = rounding;
|
||||
style->ItemSpacing = VEC(1, 2);
|
||||
style->ItemInnerSpacing = VEC(1, 1);
|
||||
style->CellPadding = pudding;
|
||||
style->TouchExtraPadding = pudding;
|
||||
style->IndentSpacing = VAL(3);
|
||||
style->ColumnsMinSpacing = VAL(1.2);
|
||||
style->ScrollbarSize = VAL(5);
|
||||
style->ScrollbarRounding = rounding;
|
||||
style->GrabMinSize = VAL(0.6);
|
||||
style->GrabRounding = rounding;
|
||||
style->LogSliderDeadzone = VAL(0.6);
|
||||
style->TabRounding = rounding;
|
||||
style->TabMinWidthForCloseButton = VAL(1.3);
|
||||
style->DisplayWindowPadding = pudding;
|
||||
style->DisplaySafeAreaPadding = pudding;
|
||||
// style->MouseCursorScale = VAL(1.3);
|
||||
|
||||
// style->FrameBorderSize = VAL(0);
|
||||
style->WindowBorderSize = VAL(0.5);
|
||||
style->ChildBorderSize = VAL(0.6);
|
||||
|
||||
// style->WindowTitleAlign = VEC(0.1f, 0.2f);
|
||||
style->WindowMenuButtonPosition = ImGuiDir_Right;
|
||||
|
||||
if (!first_init)
|
||||
return;
|
||||
|
||||
ImVec4* colors = ImGui::GetStyle().Colors;
|
||||
colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
|
||||
colors[ImGuiCol_TextDisabled] = ImVec4(0.86f, 0.86f, 0.86f, 1.00f);
|
||||
colors[ImGuiCol_WindowBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_ChildBg] = ImVec4(0.09f, 0.09f, 0.10f, 1.00f);
|
||||
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.10f, 1.00f);
|
||||
colors[ImGuiCol_Border] = ImVec4(0.06f, 0.06f, 0.06f, 1.00f);
|
||||
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||
colors[ImGuiCol_FrameBg] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.27f, 0.27f, 0.33f, 1.00f);
|
||||
colors[ImGuiCol_FrameBgActive] = ImVec4(0.43f, 0.43f, 0.53f, 1.00f);
|
||||
colors[ImGuiCol_TitleBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_TitleBgActive] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_MenuBarBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.09f, 0.09f, 0.10f, 0.00f);
|
||||
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.15f, 0.15f, 0.19f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.21f, 0.20f, 0.25f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.30f, 0.29f, 0.35f, 1.00f);
|
||||
colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.48f, 0.50f, 1.00f);
|
||||
colors[ImGuiCol_SliderGrab] = ImVec4(0.53f, 0.57f, 0.64f, 1.00f);
|
||||
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.69f, 0.74f, 0.83f, 1.00f);
|
||||
colors[ImGuiCol_Button] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_ButtonHovered] = ImVec4(0.27f, 0.27f, 0.33f, 1.00f);
|
||||
colors[ImGuiCol_ButtonActive] = ImVec4(0.43f, 0.43f, 0.53f, 1.00f);
|
||||
colors[ImGuiCol_Header] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_HeaderHovered] = ImVec4(0.27f, 0.27f, 0.33f, 1.00f);
|
||||
colors[ImGuiCol_HeaderActive] = ImVec4(0.33f, 0.33f, 0.40f, 1.00f);
|
||||
colors[ImGuiCol_Separator] = ImVec4(0.37f, 0.37f, 0.40f, 1.00f);
|
||||
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.33f, 0.35f, 0.38f, 1.00f);
|
||||
colors[ImGuiCol_SeparatorActive] = ImVec4(0.37f, 0.39f, 0.42f, 1.00f);
|
||||
colors[ImGuiCol_ResizeGrip] = ImVec4(0.16f, 0.17f, 0.19f, 1.00f);
|
||||
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.33f, 0.35f, 0.38f, 1.00f);
|
||||
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.28f, 0.34f, 0.42f, 1.00f);
|
||||
colors[ImGuiCol_Tab] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_TabHovered] = ImVec4(0.23f, 0.23f, 0.28f, 1.00f);
|
||||
colors[ImGuiCol_TabActive] = ImVec4(0.23f, 0.23f, 0.28f, 1.00f);
|
||||
colors[ImGuiCol_TabUnfocused] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.43f, 0.45f, 0.48f, 1.00f);
|
||||
colors[ImGuiCol_DockingPreview] = ImVec4(0.81f, 0.81f, 0.81f, 0.18f);
|
||||
colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
|
||||
colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.33f, 0.35f, 0.38f, 1.00f);
|
||||
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
||||
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(0.49f, 0.51f, 0.54f, 1.00f);
|
||||
colors[ImGuiCol_TableHeaderBg] = ImVec4(0.13f, 0.13f, 0.20f, 1.00f);
|
||||
colors[ImGuiCol_TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.35f, 1.00f);
|
||||
colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 1.00f);
|
||||
colors[ImGuiCol_TableRowBg] = ImVec4(0.23f, 0.20f, 0.20f, 0.00f);
|
||||
colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
|
||||
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
|
||||
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
|
||||
colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
|
||||
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.38f, 0.22f, 0.22f, 0.20f);
|
||||
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
|
||||
|
||||
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.10f, 1.00f);
|
||||
colors[ImGuiCol_DockingPreview] = ImVec4(0.64f, 0.75f, 0.83f, 0.18f);
|
||||
colors[ImGuiCol_TabHovered] = ImVec4(0.39f, 0.39f, 0.47f, 1.00f);
|
||||
colors[ImGuiCol_TabActive] = ImVec4(0.27f, 0.27f, 0.33f, 1.00f);
|
||||
colors[ImGuiCol_TabUnfocused] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.24f, 0.24f, 0.29f, 1.00f);
|
||||
colors[ImGuiCol_Border] = ImVec4(0.65f, 0.65f, 0.65f, 0.70f);
|
||||
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
}
|
||||
30730
Graphics/private/bindings/DefaultFont.bin
Normal file
30730
Graphics/private/bindings/DefaultFont.bin
Normal file
File diff suppressed because it is too large
Load diff
170
Graphics/private/bindings/Window.cpp
Normal file
170
Graphics/private/bindings/Window.cpp
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
#include "Window.hpp"
|
||||
|
||||
// -------- OpenGL -------- //
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "WindowContext.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace tp {
|
||||
class Graphics::GL::Context {
|
||||
public:
|
||||
// Showoff data
|
||||
GLuint vao{};
|
||||
GLuint vbo{};
|
||||
GLfloat vertices[9] = {
|
||||
-0.0f, -0.0f, 0.0f, // Left vertex
|
||||
1.0f, 0.0f, 0.0f, // Right vertex
|
||||
0.5f, 1.0f, 0.0f // Top vertex
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
using namespace tp;
|
||||
|
||||
Graphics::GL::GL() {
|
||||
mContext = new Context();
|
||||
}
|
||||
|
||||
Graphics::GL::~GL() {
|
||||
delete mContext;
|
||||
}
|
||||
|
||||
void Graphics::GL::init() {
|
||||
// Create a Vertex Array Object (VAO)
|
||||
glGenVertexArrays(1, &mContext->vao);
|
||||
glBindVertexArray(mContext->vao);
|
||||
|
||||
// Create a Vertex Buffer Object (VBO)
|
||||
glGenBuffers(1, &mContext->vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mContext->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(mContext->vertices), mContext->vertices, GL_STATIC_DRAW);
|
||||
|
||||
// Set up vertex attributes
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*) nullptr);
|
||||
glEnableVertexAttribArray(0);
|
||||
}
|
||||
|
||||
void Graphics::GL::deinit() {
|
||||
glDeleteBuffers(1, &mContext->vbo);
|
||||
glDeleteVertexArrays(1, &mContext->vao);
|
||||
}
|
||||
|
||||
void Graphics::GL::proc() {
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void Graphics::GL::draw() {
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
}
|
||||
|
||||
void Graphics::init(Window* window) {
|
||||
mGl.init();
|
||||
mGui.init(window);
|
||||
mCanvas.init();
|
||||
}
|
||||
|
||||
void Graphics::deinit() {
|
||||
mCanvas.deinit();
|
||||
mGui.deinit();
|
||||
mGl.deinit();
|
||||
}
|
||||
|
||||
void Graphics::proc() {
|
||||
mGl.proc();
|
||||
mCanvas.proc();
|
||||
mGui.proc();
|
||||
}
|
||||
|
||||
void Graphics::draw() {
|
||||
mGl.draw();
|
||||
mCanvas.draw();
|
||||
mGui.draw();
|
||||
}
|
||||
|
||||
Window::Window(int width, int height, const char* title) {
|
||||
mContext = new Context();
|
||||
|
||||
// Create a window and OpenGL context
|
||||
mContext->window = glfwCreateWindow(width, height, title, nullptr, nullptr);
|
||||
if (!mContext->window) {
|
||||
printf("Failed to create GLFW window\n");
|
||||
return;
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(mContext->window);
|
||||
|
||||
// Initialize GLEW
|
||||
if (glewInit() != GLEW_OK) {
|
||||
printf("Failed to initialize GLEW\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// get some common information. maybe call it in loop to pick up monitor changes
|
||||
int width_mm, height_mm;
|
||||
auto monitor = glfwGetPrimaryMonitor();
|
||||
glfwGetMonitorPhysicalSize(monitor, &width_mm, &height_mm);
|
||||
mMonitor.mmSize = { width_mm, height_mm };
|
||||
|
||||
const GLFWvidmode * mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
|
||||
mMonitor.pixelSize = { mode->width, mode->height };
|
||||
mMonitor.refreshRate = mode->refreshRate;
|
||||
|
||||
mGraphics.init(this);
|
||||
}
|
||||
|
||||
Window::~Window() {
|
||||
mGraphics.deinit();
|
||||
glfwDestroyWindow(mContext->window);
|
||||
delete mContext;
|
||||
}
|
||||
|
||||
|
||||
Window* Window::createWindow(int width, int height, const char* title) {
|
||||
tp::HeapAllocGlobal::startIgnore();
|
||||
|
||||
static int count = 1;
|
||||
if (!count) {
|
||||
printf("Window class is a singleton\n");
|
||||
return nullptr;
|
||||
}
|
||||
count--;
|
||||
|
||||
// Initialize GLFW
|
||||
if (!glfwInit()) {
|
||||
printf("Failed to initialize GLFW\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Set the GLFW error callback
|
||||
glfwSetErrorCallback([] (int error, const char* description) {
|
||||
printf("GLFW Error: %i %s\n", error, description);
|
||||
});
|
||||
|
||||
auto out = new Window(width, height, title);
|
||||
|
||||
tp::HeapAllocGlobal::stopIgnore();
|
||||
return out;
|
||||
}
|
||||
|
||||
void Window::destroyWindow(Window* window) {
|
||||
delete window;
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
bool Window::shouldClose() const {
|
||||
return glfwWindowShouldClose(mContext->window);
|
||||
}
|
||||
|
||||
void Window::processEvents() {
|
||||
glfwPollEvents();
|
||||
mGraphics.proc();
|
||||
}
|
||||
|
||||
void Window::draw() {
|
||||
mGraphics.draw();
|
||||
glfwSwapBuffers(mContext->window);
|
||||
}
|
||||
|
||||
auto Window::getContext() -> Context* { return mContext; }
|
||||
16
Graphics/private/bindings/WindowContext.hpp
Normal file
16
Graphics/private/bindings/WindowContext.hpp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
// -------- Window Context -------- //
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
namespace tp {
|
||||
class Window;
|
||||
|
||||
class Window::Context {
|
||||
friend Graphics::GL;
|
||||
friend Graphics::GUI;
|
||||
friend Graphics::Canvas;
|
||||
public:
|
||||
GLFWwindow* window;
|
||||
};
|
||||
}
|
||||
53
Graphics/public/Animations.hpp
Normal file
53
Graphics/public/Animations.hpp
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#pragma once
|
||||
|
||||
#include "GraphicsCommon.hpp"
|
||||
|
||||
namespace tp {
|
||||
|
||||
class AnimValue {
|
||||
halnf mValPrev = 0;
|
||||
halnf mVal = 0;
|
||||
time_ms mTimeStart = 0;
|
||||
halni mTimeAnim = 250;
|
||||
|
||||
static bool gInTransition;
|
||||
|
||||
private:
|
||||
[[nodiscard]] halnf interpolate() const;
|
||||
|
||||
public:
|
||||
AnimValue();
|
||||
explicit AnimValue(halnf val);
|
||||
|
||||
[[nodiscard]] halnf prev() const { return mValPrev; }
|
||||
void set(halnf val);
|
||||
void setNoTransition(halnf);
|
||||
void setAnimTime(halni time);
|
||||
[[nodiscard]] halnf get() const;
|
||||
[[nodiscard]] halnf getTarget() const;
|
||||
[[nodiscard]] bool inTransition() const;
|
||||
explicit operator halnf() const;
|
||||
void operator=(halnf val);
|
||||
};
|
||||
|
||||
class AnimRect : Rect<AnimValue> {
|
||||
public:
|
||||
AnimRect() {
|
||||
set({ 0, 0, 0, 0 });
|
||||
setAnimTime(450);
|
||||
}
|
||||
|
||||
[[nodiscard]] RectF get() const;
|
||||
[[nodiscard]] RectF getTarget() const;
|
||||
void setNoTransition(RectF);
|
||||
void set(const RectF&);
|
||||
void setAnimTime(halni time_ms);
|
||||
};
|
||||
|
||||
class AnimColor {
|
||||
AnimRect mColor;
|
||||
public:
|
||||
[[nodiscard]] RGBA get() const;
|
||||
void set(const RGBA&);
|
||||
};
|
||||
};
|
||||
89
Graphics/public/Graphics.hpp
Normal file
89
Graphics/public/Graphics.hpp
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#pragma once
|
||||
|
||||
#include "GraphicsCommon.hpp"
|
||||
|
||||
namespace tp {
|
||||
class Window;
|
||||
|
||||
class Graphics {
|
||||
public:
|
||||
class GL {
|
||||
class Context;
|
||||
Context* mContext;
|
||||
private:
|
||||
friend Graphics;
|
||||
|
||||
GL();
|
||||
~GL();
|
||||
|
||||
void init();
|
||||
void deinit();
|
||||
static void proc();
|
||||
static void draw();
|
||||
public:
|
||||
// TODO : API
|
||||
};
|
||||
|
||||
class GUI {
|
||||
class Context;
|
||||
Context* mContext;
|
||||
private:
|
||||
friend Graphics;
|
||||
|
||||
GUI();
|
||||
~GUI();
|
||||
|
||||
void init(Window* window);
|
||||
void deinit();
|
||||
void proc();
|
||||
void draw();
|
||||
|
||||
void setStyle();
|
||||
|
||||
public:
|
||||
void drawDebugInfoWindow();
|
||||
|
||||
halnf getFontSize() const;
|
||||
halnf getUIScale() const;
|
||||
|
||||
void setDPMM(ualni);
|
||||
void setFontSize(ualni);
|
||||
void setUIScale(ualni);
|
||||
};
|
||||
|
||||
class Canvas {
|
||||
class Context;
|
||||
Context* mContext;
|
||||
private:
|
||||
friend Graphics;
|
||||
|
||||
Canvas();
|
||||
~Canvas();
|
||||
|
||||
void init();
|
||||
void deinit();
|
||||
void proc();
|
||||
void draw();
|
||||
|
||||
public:
|
||||
// TODO : API
|
||||
};
|
||||
|
||||
private:
|
||||
friend Window;
|
||||
|
||||
Graphics() = default;
|
||||
void init(Window* window);
|
||||
void deinit();
|
||||
void draw();
|
||||
void proc();
|
||||
|
||||
public:
|
||||
GUI& getDebugGui() { return mGui; }
|
||||
|
||||
private:
|
||||
GUI mGui;
|
||||
GL mGl;
|
||||
Canvas mCanvas;
|
||||
};
|
||||
}
|
||||
10
Graphics/public/GraphicsCommon.hpp
Normal file
10
Graphics/public/GraphicsCommon.hpp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include "Strings.hpp"
|
||||
#include "Rect.hpp"
|
||||
#include "Color.hpp"
|
||||
#include "Timing.hpp"
|
||||
|
||||
namespace tp {
|
||||
extern ModuleManifest gModuleGraphics;
|
||||
}
|
||||
166
Graphics/public/Keycodes.hpp
Normal file
166
Graphics/public/Keycodes.hpp
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
namespace tp {
|
||||
|
||||
// basically copy of glfw keys
|
||||
enum class Keycode {
|
||||
|
||||
/* Printable keys */
|
||||
SPACE = 32,
|
||||
APOSTROPHE = 39, /* ' */
|
||||
COMMA = 44, /* , */
|
||||
MINUS = 45, /* - */
|
||||
PERIOD = 46, /* . */
|
||||
SLASH = 0xBF, /* \ */
|
||||
N0 = 48,
|
||||
N1 = 49,
|
||||
N2 = 50,
|
||||
N3 = 51,
|
||||
N4 = 52,
|
||||
N5 = 53,
|
||||
N6 = 54,
|
||||
N7 = 55,
|
||||
N8 = 56,
|
||||
N9 = 57,
|
||||
SEMICOLON = 59, /* ; */
|
||||
EQUAL = 61, /* = */
|
||||
A = 65,
|
||||
B = 66,
|
||||
C = 67,
|
||||
D = 68,
|
||||
E = 69,
|
||||
F = 70,
|
||||
G = 71,
|
||||
H = 72,
|
||||
I = 73,
|
||||
J = 74,
|
||||
K = 75,
|
||||
L = 76,
|
||||
M = 77,
|
||||
N = 78,
|
||||
O = 79,
|
||||
P = 80,
|
||||
Q = 81,
|
||||
R = 82,
|
||||
S = 83,
|
||||
T = 84,
|
||||
U = 85,
|
||||
V = 86,
|
||||
W = 87,
|
||||
X = 88,
|
||||
Y = 89,
|
||||
Z = 90,
|
||||
LEFT_BRACKET = 91, /* [ */
|
||||
BACKSLASH = 92, /* \ */
|
||||
RIGHT_BRACKET = 93, /* ] */
|
||||
GRAVE_ACCENT = 96, /* ` */
|
||||
WORLD_1 = 161, /* non-US #1 */
|
||||
WORLD_2 = 162, /* non-US #2 */
|
||||
|
||||
/* function keys */
|
||||
|
||||
ESCAPE = 256,
|
||||
ENTER = 257,
|
||||
TAB = 258,
|
||||
BACKSPACE = 259,
|
||||
INSERT = 260,
|
||||
DELETE = 261,
|
||||
RIGHT = 262,
|
||||
LEFT = 263,
|
||||
DOWN = 264,
|
||||
UP = 265,
|
||||
PAGE_UP = 266,
|
||||
PAGE_DOWN = 267,
|
||||
HOME = 268,
|
||||
END = 269,
|
||||
CAPS_LOCK = 280,
|
||||
SCROLL_LOCK = 281,
|
||||
NUM_LOCK = 282,
|
||||
PRINT_SCREEN = 283,
|
||||
PAUSE = 284,
|
||||
F1 = 290,
|
||||
F2 = 291,
|
||||
F3 = 292,
|
||||
F4 = 293,
|
||||
F5 = 294,
|
||||
F6 = 295,
|
||||
F7 = 296,
|
||||
F8 = 297,
|
||||
F9 = 298,
|
||||
F10 = 299,
|
||||
F11 = 300,
|
||||
F12 = 301,
|
||||
F13 = 302,
|
||||
F14 = 303,
|
||||
F15 = 304,
|
||||
F16 = 305,
|
||||
F17 = 306,
|
||||
F18 = 307,
|
||||
F19 = 308,
|
||||
F20 = 309,
|
||||
F21 = 310,
|
||||
F22 = 311,
|
||||
F23 = 312,
|
||||
F24 = 313,
|
||||
F25 = 314,
|
||||
KP_0 = 320,
|
||||
KP_1 = 321,
|
||||
KP_2 = 322,
|
||||
KP_3 = 323,
|
||||
KP_4 = 324,
|
||||
KP_5 = 325,
|
||||
KP_6 = 326,
|
||||
KP_7 = 327,
|
||||
KP_8 = 328,
|
||||
KP_9 = 329,
|
||||
KP_DECIMAL = 330,
|
||||
KP_DIVIDE = 331,
|
||||
KP_MULTIPLY = 332,
|
||||
KP_SUBTRACT = 333,
|
||||
KP_ADD = 334,
|
||||
KP_ENTER = 335,
|
||||
KP_EQUAL = 336,
|
||||
LEFT_SHIFT = 340,
|
||||
LEFT_CONTROL = 341,
|
||||
LEFT_ALT = 342,
|
||||
LEFT_SUPER = 343,
|
||||
RIGHT_SHIFT = 344,
|
||||
RIGHT_CONTROL = 345,
|
||||
RIGHT_ALT = 346,
|
||||
RIGHT_SUPER = 347,
|
||||
MENU = 348,
|
||||
|
||||
INV_SLASH = 0xDC,
|
||||
BRA = 0xDB,
|
||||
KET = 0xDD,
|
||||
TILDA = 0xC0,
|
||||
DOUBLE_DOT = 0xBA,
|
||||
QUOTES = 0xDE,
|
||||
|
||||
MOUSE1 = 501,
|
||||
MOUSE2 = 502,
|
||||
MOUSE3 = 503,
|
||||
MOUSE4 = 504,
|
||||
MOUSE5 = 505,
|
||||
MOUSE_UP = 506,
|
||||
MOUSE_DOWN = 507,
|
||||
};
|
||||
|
||||
enum class KeyState {
|
||||
PRESSED,
|
||||
RELEASED,
|
||||
HOLD,
|
||||
REPEAT,
|
||||
NONE,
|
||||
};
|
||||
|
||||
struct KeyEvent {
|
||||
Keycode code;
|
||||
enum class EventState {
|
||||
RELEASED = 0,
|
||||
PRESSED = 1,
|
||||
REPEAT = 2,
|
||||
} event_state;
|
||||
};
|
||||
};
|
||||
52
Graphics/public/Window.hpp
Normal file
52
Graphics/public/Window.hpp
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#pragma once
|
||||
|
||||
#include "Graphics.hpp"
|
||||
#include "Buffer.hpp"
|
||||
#include "Keycodes.hpp"
|
||||
|
||||
namespace tp {
|
||||
|
||||
class Window {
|
||||
class Context;
|
||||
|
||||
public:
|
||||
struct Event {
|
||||
enum Type {
|
||||
KEY,
|
||||
MOUSE,
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
struct Monitor {
|
||||
ualni refreshRate = 60;
|
||||
Vec2F pixelSize;
|
||||
Vec2F mmSize;
|
||||
};
|
||||
|
||||
private:
|
||||
Window(int width, int height, const char* title);
|
||||
~Window();
|
||||
|
||||
public:
|
||||
static Window* createWindow(int width, int height, const char* title);
|
||||
static void destroyWindow(Window* window);
|
||||
|
||||
public:
|
||||
void draw();
|
||||
void processEvents();
|
||||
[[nodiscard]] bool shouldClose() const;
|
||||
|
||||
auto getContext() -> Context*;
|
||||
|
||||
Graphics& getGraphics() { return mGraphics; }
|
||||
|
||||
[[nodiscard]] const Monitor& getMonitor() const { return mMonitor; }
|
||||
|
||||
private:
|
||||
Context* mContext;
|
||||
Graphics mGraphics;
|
||||
Buffer<Event> mEvents;
|
||||
Monitor mMonitor;
|
||||
};
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue