Compare commits
23
Commits
dfb854985d
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dac78d9c82
|
||
|
|
a16bce419d
|
||
|
|
bed24ff28a
|
||
|
|
1acecd03ee
|
||
|
|
99b330b136
|
||
|
|
5e5907ed30
|
||
|
|
b4b1144c60
|
||
|
|
6e502d73d8
|
||
|
|
468a112274
|
||
|
|
4cf3685832
|
||
|
|
38a2b21ba0
|
||
|
|
38a1cad76a
|
||
|
|
d85610a0bd
|
||
|
|
88e367a299
|
||
|
|
28d2e291b3
|
||
|
|
c18ef2161a
|
||
|
|
d136e6ac5e
|
||
|
|
777b23f4c8
|
||
|
|
078af99ae5
|
||
|
|
febf506a5e
|
||
|
|
2a2a670e1a
|
||
|
|
830524c9eb
|
||
|
|
9731579af9
|
+322
@@ -0,0 +1,322 @@
|
||||
---
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -1
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionDeclarations: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionDeclarations: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionDeclarations: true
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionDeclarations: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveShortCaseStatements:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCaseArrows: false
|
||||
AlignCaseColons: false
|
||||
AlignConsecutiveTableGenBreakingDAGArgColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionDeclarations: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveTableGenCondOperatorColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionDeclarations: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveTableGenDefinitionColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionDeclarations: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments:
|
||||
Kind: Always
|
||||
OverEmptyLines: 0
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowBreakBeforeNoexceptSpecifier: Never
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseExpressionOnASingleLine: true
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortCompoundRequirementOnASingleLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AllowShortNamespacesOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackParameters: BinPack
|
||||
BitFieldColonSpacing: Both
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterExternBlock: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakAdjacentStringLiterals: true
|
||||
BreakAfterAttributes: Leave
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakAfterReturnType: None
|
||||
BreakArrays: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakBinaryOperations: Never
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakFunctionDefinitionParameters: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakStringLiterals: true
|
||||
BreakTemplateDeclarations: Yes
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: true
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '^<ext/.*\.h>'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^<.*'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseBlocks: false
|
||||
IndentCaseLabels: true
|
||||
IndentExportBlock: true
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentRequiresClause: true
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertBraces: false
|
||||
InsertNewlineAtEOF: false
|
||||
InsertTrailingCommas: None
|
||||
IntegerLiteralSeparator:
|
||||
Binary: 0
|
||||
BinaryMinDigits: 0
|
||||
Decimal: 0
|
||||
DecimalMinDigits: 0
|
||||
Hex: 0
|
||||
HexMinDigits: 0
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLines:
|
||||
AtEndOfFile: false
|
||||
AtStartOfBlock: false
|
||||
AtStartOfFile: true
|
||||
KeepFormFeed: false
|
||||
LambdaBodyIndentation: Signature
|
||||
LineEnding: DeriveLF
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MainIncludeChar: Quote
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Never
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PackConstructorInitializers: NextLine
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakBeforeMemberAccess: 150
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakScopeResolution: 500
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerAlignment: Left
|
||||
PPIndentWidth: -1
|
||||
QualifierAlignment: Leave
|
||||
RawStringFormats:
|
||||
- Language: Cpp
|
||||
Delimiters:
|
||||
- cc
|
||||
- CC
|
||||
- cpp
|
||||
- Cpp
|
||||
- CPP
|
||||
- 'c++'
|
||||
- 'C++'
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
- Language: TextProto
|
||||
Delimiters:
|
||||
- pb
|
||||
- PB
|
||||
- proto
|
||||
- PROTO
|
||||
EnclosingFunctions:
|
||||
- EqualsProto
|
||||
- EquivToProto
|
||||
- PARSE_PARTIAL_TEXT_PROTO
|
||||
- PARSE_TEST_PROTO
|
||||
- PARSE_TEXT_PROTO
|
||||
- ParseTextOrDie
|
||||
- ParseTextProtoOrDie
|
||||
- ParseTestProto
|
||||
- ParsePartialTestProto
|
||||
CanonicalDelimiter: pb
|
||||
BasedOnStyle: google
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: Always
|
||||
RemoveBracesLLVM: false
|
||||
RemoveEmptyLinesInUnwrappedLines: false
|
||||
RemoveParentheses: Leave
|
||||
RemoveSemicolon: false
|
||||
RequiresClausePosition: OwnLine
|
||||
RequiresExpressionIndentation: OuterScope
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SkipMacroDefinitionBody: false
|
||||
SortIncludes: CaseSensitive
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: LexicographicNumeric
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeJsonColon: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterForeachMacros: true
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterIfMacros: true
|
||||
AfterOverloadedOperator: false
|
||||
AfterPlacementOperator: true
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: Never
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParens: Never
|
||||
SpacesInParensOptions:
|
||||
ExceptDoubleParentheses: false
|
||||
InCStyleCasts: false
|
||||
InConditionalStatements: false
|
||||
InEmptyParentheses: false
|
||||
Other: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Auto
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TableGenBreakInsideDAGArg: DontBreak
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
VerilogBreakBetweenInstancePorts: true
|
||||
WhitespaceSensitiveMacros:
|
||||
- BOOST_PP_STRINGIZE
|
||||
- CF_SWIFT_NAME
|
||||
- NS_SWIFT_NAME
|
||||
- PP_STRINGIZE
|
||||
- STRINGIZE
|
||||
WrapNamespaceBodyWithEmptyLines: Leave
|
||||
...
|
||||
|
||||
+23
-6
@@ -5,31 +5,48 @@ project(amethyst)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED true)
|
||||
|
||||
option(AMY_BUILD_3DS "Build for 3ds" ON)
|
||||
option(AMY_GOD_DEV "Turn this on if you think you are god" OFF)
|
||||
# THis option should be disabled if you use STB_IMAGE in you main project
|
||||
option(AMY_BUILD_STB_IMAGE ON)
|
||||
option(AMY_BUILD_STB_TRUETYPE ON)
|
||||
|
||||
add_subdirectory(vendor/libpicasso)
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC
|
||||
source/app.cpp
|
||||
source/assets.cpp
|
||||
source/amethyst.cpp
|
||||
source/color.cpp
|
||||
source/godtrace.cpp
|
||||
source/image.cpp
|
||||
source/renderer.cpp
|
||||
source/texture.cpp
|
||||
source/utils.cpp
|
||||
source/c3d.cpp
|
||||
source/ctru.cpp
|
||||
source/iron/iron.cpp
|
||||
source/iron/drawlist.cpp
|
||||
source/iron/font.cpp
|
||||
source/maths/mat.cpp
|
||||
)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC include)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${DEVKITPRO}/portlibs/3ds/include
|
||||
)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/internal
|
||||
)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC pica::pica)
|
||||
if(${AMY_BUILD_3DS})
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC m z ctru citro3d)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC AMY_3DS)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC m z ctru citro3d mpg123)
|
||||
if(${AMY_BUILD_STB_IMAGE})
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC AMY_STB_IMAGE)
|
||||
endif()
|
||||
if(${AMY_BUILD_STB_TRUETYPE})
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC AMY_STB_TT)
|
||||
endif()
|
||||
|
||||
target_compile_options(${PROJECT_NAME} PUBLIC -Wno-psabi)
|
||||
|
||||
add_subdirectory(example)
|
||||
|
||||
install(TARGETS ${PROJECT_NAME})
|
||||
install(DIRECTORY include DESTINATION .)
|
||||
|
||||
@@ -1,3 +1,29 @@
|
||||
# amethyst
|
||||
|
||||
2d Renderer Library made for ReCraft3DS based on palladium.
|
||||
|
||||
## Usage
|
||||
|
||||
### Submodule:
|
||||
|
||||
Add amethyst as submodule to your repository
|
||||
|
||||
```bash
|
||||
git submodule add https://github.com/tobid7/amethyst vendor/amethyst
|
||||
```
|
||||
|
||||
Add it as submodule to your `CMakeLists.txt`
|
||||
|
||||
```cmake
|
||||
add_subdirectory(vendor/amethyst)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC amethyst)
|
||||
```
|
||||
|
||||
### Installed
|
||||
|
||||
Coming Soon...
|
||||
|
||||
## Credits
|
||||
|
||||
- [tobid7](https://github.com/tobid7) Lead Developer, Stealing a lot of code of [Palladium](https://github.com/tobid7/palladium)
|
||||
- [nothings](https://github.com/nothings) stb_image and stb_truetype from [here](https://github.com/nothings/stb)
|
||||
@@ -1,27 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
find_program(PICASSO NAMES picasso REQUIRED)
|
||||
|
||||
# Function origanally Created in Re-Craft-3DS
|
||||
function(__amy_make_shader arg1 arg2)
|
||||
# These only exist cause i was stupid
|
||||
set(__FILE ${arg1})
|
||||
set(__NAME ${arg2})
|
||||
|
||||
# Need to build shaders during config stage :(
|
||||
execute_process(
|
||||
COMMAND ${PICASSO} -o "${CMAKE_CURRENT_SOURCE_DIR}/romfs/shaders/${__NAME}.shbin" "${__FILE}"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
project(amethyst-example)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED true)
|
||||
|
||||
__amy_make_shader(${CMAKE_CURRENT_SOURCE_DIR}/shaders/shader2d.v.pica shader2d)
|
||||
__amy_make_shader(${CMAKE_CURRENT_SOURCE_DIR}/shaders/lithium.v.pica lithium)
|
||||
|
||||
add_executable(${PROJECT_NAME} source/main.cpp)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE amethyst)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE -O2)
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
Binary file not shown.
@@ -0,0 +1,93 @@
|
||||
Copyright 2014 The Comic Neue Project Authors (https://github.com/crozynski/comicneue)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
https://openfontlicense.org
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 107 B |
@@ -1,34 +0,0 @@
|
||||
; LI7 Shader
|
||||
; Constants
|
||||
.constf myconst(0.0, 1.0, 0.00392156862745, 0.0)
|
||||
.alias ones myconst.yyyy ; Vector full of ones
|
||||
|
||||
; Uniforms
|
||||
.fvec projection[4]
|
||||
|
||||
; Outputs
|
||||
.out out_position position
|
||||
.out out_color color
|
||||
.out out_uv texcoord0
|
||||
|
||||
; Inputs
|
||||
.alias in_xy v0
|
||||
.alias in_uvc v1
|
||||
.alias in_col v2
|
||||
|
||||
.entry vmain
|
||||
.proc vmain
|
||||
mov r0.xy, in_xy.xy
|
||||
mov r0.w, ones
|
||||
|
||||
dp4 out_position.x, projection[0], r0
|
||||
dp4 out_position.y, projection[1], r0
|
||||
dp4 out_position.z, projection[2], r0
|
||||
dp4 out_position.w, projection[3], r0
|
||||
|
||||
mov out_uv, in_uvc.xy
|
||||
|
||||
mul r1, myconst.zzzz, in_col
|
||||
mov out_color, r1
|
||||
end
|
||||
.end
|
||||
@@ -1,38 +0,0 @@
|
||||
; Example PICA200 vertex shader
|
||||
|
||||
; Uniforms
|
||||
.fvec projection[4]
|
||||
|
||||
; Constants
|
||||
.constf myconst(0.0, 1.0, -1.0, 0.1)
|
||||
.constf myconst2(0.3, 0.0, 0.0, 0.0)
|
||||
.alias zeros myconst.xxxx ; Vector full of zeros
|
||||
.alias ones myconst.yyyy ; Vector full of ones
|
||||
|
||||
; Outputs
|
||||
.out outpos position
|
||||
.out outclr color
|
||||
|
||||
; Inputs (defined as aliases for convenience)
|
||||
.alias inpos v0
|
||||
.alias inclr v1
|
||||
|
||||
.bool test
|
||||
|
||||
.proc main
|
||||
; Force the w component of inpos to be 1.0
|
||||
mov r0.xyz, inpos
|
||||
mov r0.w, ones
|
||||
|
||||
; outpos = projectionMatrix * inpos
|
||||
dp4 outpos.x, projection[0], r0
|
||||
dp4 outpos.y, projection[1], r0
|
||||
dp4 outpos.z, projection[2], r0
|
||||
dp4 outpos.w, projection[3], r0
|
||||
|
||||
; outclr = inclr
|
||||
mov outclr, inclr
|
||||
|
||||
; We're finished
|
||||
end
|
||||
.end
|
||||
+67
-48
@@ -1,58 +1,77 @@
|
||||
#include <amethyst.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#include "amethyst/iron.hpp"
|
||||
|
||||
class example : public amy::app {
|
||||
class Example : public Amy::App {
|
||||
public:
|
||||
example() {
|
||||
amy::ctru::init();
|
||||
consoleInit(GFX_BOTTOM, NULL);
|
||||
amy::c3d::init();
|
||||
m_top = amy::c3d::createScreen(GFX_TOP, GFX_LEFT);
|
||||
amy::iron::init();
|
||||
dl = new amy::iron::drawlist();
|
||||
dl->drawSolid();
|
||||
auto cmd = std::make_unique<amy::iron::command>();
|
||||
cmd->index = 0;
|
||||
cmd->layer = 0;
|
||||
cmd->tex = amy::iron::whiteTex();
|
||||
cmd->add(0).add(1).add(2);
|
||||
cmd->add(amy::iron::vertex(200, 50, 0, 0, 0xff0000ff));
|
||||
cmd->add(amy::iron::vertex(100, 190, 0, 0, 0xff00ff00));
|
||||
cmd->add(amy::iron::vertex(300, 190, 0, 0, 0xffff0000));
|
||||
cmdl.push_back(std::move(cmd));
|
||||
// throw std::runtime_error(std::format(
|
||||
// "solid tex: {:#08x}\nsize: {}\nptr: {:#08x}",
|
||||
// (amy::ui)amy::iron::whiteTex(), amy::iron::whiteTex()->size(),
|
||||
// (amy::ui)amy::iron::whiteTex()->ptr()));
|
||||
};
|
||||
~example() {
|
||||
amy::c3d::deleteScreen(m_top);
|
||||
amy::c3d::deinit();
|
||||
};
|
||||
|
||||
void main() {
|
||||
amy::c3d::startFrame();
|
||||
m_top->startDraw();
|
||||
m_top->clear();
|
||||
// dl->drawRectFilled(0, 50, 0xff00ff00);
|
||||
amy::iron::newFrame();
|
||||
amy::iron::drawOn(m_top);
|
||||
// amy::iron::draw(dl->data());
|
||||
amy::iron::draw(cmdl);
|
||||
// dl->clear();
|
||||
amy::c3d::endFrame();
|
||||
Example() {
|
||||
Amy::GTrace::Scope s("Init");
|
||||
gfxInitDefault();
|
||||
romfsInit();
|
||||
C3D::Init();
|
||||
Top = C3D::CreateScreen(GFX_TOP);
|
||||
Mgr = new Amy::AssetMgr();
|
||||
Iron::Init();
|
||||
Mgr->AutoLoad("icon", "romfs:/icon.png");
|
||||
auto fnt = Iron::Font::New();
|
||||
fnt->LoadBMF("romfs:/ComicNeue.png");
|
||||
Mgr->Add("font", fnt);
|
||||
// Mgr->AutoLoad("font", "romfs:/ComicNeue.ttf");
|
||||
dl = Iron::Drawlist::New();
|
||||
dl->SetFont(Mgr->Get<Iron::Font>("font"));
|
||||
}
|
||||
|
||||
private:
|
||||
amy::c3d::screen* m_top = nullptr;
|
||||
amy::iron::drawlist* dl = nullptr;
|
||||
std::vector<amy::iron::command::ref> cmdl;
|
||||
~Example() {
|
||||
dl.reset();
|
||||
delete Top;
|
||||
delete Mgr;
|
||||
Iron::Exit();
|
||||
C3D::Deinit();
|
||||
romfsExit();
|
||||
gfxExit();
|
||||
}
|
||||
|
||||
void Main() {
|
||||
hidScanInput();
|
||||
if (hidKeysDown() & KEY_START) {
|
||||
Exit();
|
||||
}
|
||||
std::string stats = std::format(
|
||||
"Delta: {:.3} -> {:.3} FPS\nTime: {}\nLinearRam: {}\nVIT: "
|
||||
"[{}/{}/{}]\nAssets: {}\nMain: {}",
|
||||
this->Delta(), 1000.0 / this->Delta(),
|
||||
Amy::Utils::FormatMillis(this->Time() * 1000.f),
|
||||
Amy::Utils::FormatBytes(linearSpaceFree()), Amy::Iron::VerticesDrawn(),
|
||||
Amy::Iron::IndicesDrawn(), Amy::Iron::IndicesDrawn() / 3,
|
||||
Mgr->CountAll(),
|
||||
Amy::Utils::FormatNanos(
|
||||
Amy::GTrace::GetTraceRef("Main")->GetLastDiff()));
|
||||
C3D::StartFrame();
|
||||
Amy::GTrace::Beg("Main");
|
||||
Top->Clear();
|
||||
Top->Use();
|
||||
dl->DrawTex(Mgr->Get<Amy::Texture>("icon"));
|
||||
dl->DrawRectFilled(Amy::fvec2(50, 0), 48, Amy::Color(255, 255, 255, 160));
|
||||
dl->DrawCircleFilled(Amy::fvec2(200, 120), 50, Amy::Color("#ffffff"), 40);
|
||||
dl->DrawSolid();
|
||||
dl->DrawRectFilled(0, 50, Amy::Color(0.f, 1.f, 0.f, 1.f));
|
||||
dl->DrawText(Amy::fvec2(5, 50), stats, Amy::Color(255, 0, 255));
|
||||
|
||||
Iron::NewFrame();
|
||||
Iron::DrawOn(Top);
|
||||
Iron::Draw(dl->Data());
|
||||
dl->Clear();
|
||||
C3D::EndFrame();
|
||||
Amy::GTrace::End("Main");
|
||||
}
|
||||
|
||||
C3D::Screen* Top;
|
||||
Amy::AssetMgr* Mgr;
|
||||
Iron::Drawlist::Ref dl = nullptr;
|
||||
};
|
||||
|
||||
int main() {
|
||||
amy::registerCxxExceptionHandler();
|
||||
example app;
|
||||
app.run();
|
||||
Amy::RegisterCxxExceptionHandler();
|
||||
Example App;
|
||||
App.Run();
|
||||
return 0;
|
||||
}
|
||||
+28
-4
@@ -3,11 +3,35 @@
|
||||
#include <amethyst/app.hpp>
|
||||
#include <amethyst/assets.hpp>
|
||||
#include <amethyst/c3d.hpp>
|
||||
#include <amethyst/ctru.hpp>
|
||||
#include <amethyst/color.hpp>
|
||||
#include <amethyst/godtrace.hpp>
|
||||
#include <amethyst/image.hpp>
|
||||
#include <amethyst/iron.hpp>
|
||||
#include <amethyst/renderer.hpp>
|
||||
#include <amethyst/texture.hpp>
|
||||
#include <amethyst/utils.hpp>
|
||||
#include <atomic>
|
||||
|
||||
namespace amy {
|
||||
void registerCxxExceptionHandler();
|
||||
}
|
||||
namespace Amy {
|
||||
void RegisterCxxExceptionHandler();
|
||||
void* Malloc(size_t size);
|
||||
void Free(void* ptr);
|
||||
namespace Memory {
|
||||
struct MemMetrics {
|
||||
std::atomic<ull> Allocated = 0; ///< Total Allocated Memory
|
||||
std::atomic<ull> Current = 0; ///< Current Allocated Memory
|
||||
std::atomic<ull> Deleted = 0; ///< Total Deleted Memory
|
||||
std::atomic<ull> Allocations = 0; ///< Current Allocations count
|
||||
/// @brief Gets the Currently Allocated Memory
|
||||
ull CurrentlyAllocated() { return Current; }
|
||||
};
|
||||
ull GetTotalAllocated();
|
||||
ull GetTotalFreed();
|
||||
ull GetCurrent();
|
||||
ull GetAllocationCount();
|
||||
} // namespace Memory
|
||||
} // namespace Amy
|
||||
|
||||
using Iron = Amy::Iron;
|
||||
using C3D = Amy::C3D;
|
||||
using GTrace = Amy::GTrace;
|
||||
|
||||
+20
-10
@@ -2,19 +2,29 @@
|
||||
|
||||
#include <amethyst/asset.hpp>
|
||||
#include <amethyst/types.hpp>
|
||||
#include <amethyst/utils.hpp>
|
||||
|
||||
namespace amy {
|
||||
class app {
|
||||
namespace Amy {
|
||||
class App {
|
||||
public:
|
||||
app() {}
|
||||
~app() {}
|
||||
App() {
|
||||
pDelta = 0.0;
|
||||
pTime = 0.0;
|
||||
pLast = 0LL;
|
||||
pExit = false;
|
||||
}
|
||||
~App() {}
|
||||
|
||||
virtual void main() {}
|
||||
void run();
|
||||
double delta() const { return m_delta; }
|
||||
virtual void Main() {}
|
||||
void Run();
|
||||
double Delta() const { return pDelta; }
|
||||
double Time() const { return pTime; }
|
||||
void Exit() { pExit = true; }
|
||||
|
||||
private:
|
||||
ull m_last;
|
||||
double m_delta;
|
||||
bool pExit;
|
||||
ull pLast;
|
||||
double pDelta;
|
||||
double pTime;
|
||||
};
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
@@ -1,9 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
namespace amy {
|
||||
class asset {
|
||||
#include <amethyst/types.hpp>
|
||||
|
||||
namespace Amy {
|
||||
class Asset {
|
||||
public:
|
||||
asset() = default;
|
||||
virtual ~asset() = default;
|
||||
Asset() = default;
|
||||
virtual ~Asset() = default;
|
||||
AMY_SHARED(Asset);
|
||||
};
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
|
||||
+51
-16
@@ -1,34 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include <amethyst/id.hpp>
|
||||
#include <amethyst/texture.hpp>
|
||||
#include <amethyst/types.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace amy {
|
||||
class assets {
|
||||
namespace Amy {
|
||||
class AssetMgr {
|
||||
public:
|
||||
assets() = default;
|
||||
~assets() = default;
|
||||
AssetMgr() = default;
|
||||
~AssetMgr() = default;
|
||||
|
||||
void add(cstr& id, asset* v) { m_assets[id] = v; }
|
||||
void remove(cstr& id) {
|
||||
if (m_assets.count(id)) {
|
||||
m_assets.erase(id);
|
||||
void AutoLoad(const ID& name, ksr path);
|
||||
|
||||
void Add(const ID& id, Asset::Ref v) {
|
||||
if (pAssets.count(id)) {
|
||||
throw std::runtime_error("[amy]: assets: " + id.GetName() +
|
||||
" already exists!");
|
||||
}
|
||||
pAssets[id] = v;
|
||||
}
|
||||
|
||||
void Remove(const ID& id) {
|
||||
if (pAssets.count(id)) {
|
||||
pAssets.erase(id);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* get(cstr& id) {
|
||||
auto r = m_assets.find(id);
|
||||
if (r == m_assets.end()) {
|
||||
throw std::runtime_error("[amy] assets: unable to find " + id);
|
||||
std::shared_ptr<T> Get(const ID& id) {
|
||||
auto r = pAssets.find(id);
|
||||
if (r == pAssets.end()) {
|
||||
throw std::runtime_error("[amy] assets: unable to find " + id.GetName());
|
||||
}
|
||||
if (auto v = dynamic_cast<T*>(r->second)) {
|
||||
if (auto v = std::dynamic_pointer_cast<T>(r->second)) {
|
||||
return v;
|
||||
} else {
|
||||
throw std::runtime_error(id + " is not of type " + typeid(T).name());
|
||||
throw std::runtime_error(id.GetName() + " is not of type " +
|
||||
typeid(T).name());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool IsType(const ID& id) {
|
||||
auto r = pAssets.find(id);
|
||||
if (r == pAssets.end()) {
|
||||
throw std::runtime_error("[amy] assets: unable to find " + id.GetName());
|
||||
}
|
||||
return std::dynamic_pointer_cast<T>(r->second) != nullptr;
|
||||
}
|
||||
|
||||
size_t CountAll() const { return pAssets.size(); }
|
||||
|
||||
template <typename T>
|
||||
size_t Count() const {
|
||||
size_t ret = 0;
|
||||
for (auto& it : pAssets) {
|
||||
if (std::dynamic_pointer_cast<T>(it.second)) {
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<str, asset*> m_assets;
|
||||
std::map<ID, Asset::Ref> pAssets;
|
||||
};
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
+69
-64
@@ -9,115 +9,120 @@
|
||||
#include <amethyst/types.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace amy {
|
||||
class c3d {
|
||||
namespace Amy {
|
||||
class C3D {
|
||||
public:
|
||||
c3d() = default;
|
||||
~c3d() = default;
|
||||
C3D() = default;
|
||||
~C3D() = default;
|
||||
|
||||
class screen {
|
||||
class Screen {
|
||||
public:
|
||||
screen(C3D_RenderTarget* t) {
|
||||
m_target = t;
|
||||
Screen(C3D_RenderTarget* t) {
|
||||
pTarget = t;
|
||||
// Width and height are swapped on 3ds due to screen layout
|
||||
m_width = m_target->frameBuf.height;
|
||||
m_height = m_target->frameBuf.width;
|
||||
pWidth = pTarget->frameBuf.height;
|
||||
pHeight = pTarget->frameBuf.width;
|
||||
}
|
||||
~screen() { C3D_RenderTargetDelete(m_target); }
|
||||
~Screen() { C3D_RenderTargetDelete(pTarget); }
|
||||
|
||||
int width() const { return m_width; }
|
||||
int height() const { return m_height; }
|
||||
ivec2 size() const { return ivec2(m_width, m_height); }
|
||||
void clear() { C3D_RenderTargetClear(m_target, C3D_CLEAR_ALL, 0, 0); }
|
||||
void startDraw() { C3D_FrameDrawOn(m_target); }
|
||||
int Width() const { return pWidth; }
|
||||
int Height() const { return pHeight; }
|
||||
ivec2 Size() const { return ivec2(pWidth, pHeight); }
|
||||
void Clear(ui clr = 0x0, ui depth_clr = 0x0) {
|
||||
C3D_RenderTargetClear(pTarget, C3D_CLEAR_ALL, clr, depth_clr);
|
||||
}
|
||||
void Use() { C3D_FrameDrawOn(pTarget); }
|
||||
C3D_RenderTarget* Ptr() { return pTarget; }
|
||||
|
||||
private:
|
||||
C3D_RenderTarget* m_target = nullptr;
|
||||
int m_width = 0;
|
||||
int m_height = 0;
|
||||
C3D_RenderTarget* pTarget = nullptr;
|
||||
int pWidth = 0;
|
||||
int pHeight = 0;
|
||||
};
|
||||
|
||||
class shader : public asset {
|
||||
class Shader : public Asset {
|
||||
public:
|
||||
shader(const std::string& path);
|
||||
shader() {}
|
||||
~shader();
|
||||
Shader(ksr path);
|
||||
Shader() {}
|
||||
~Shader();
|
||||
AMY_SHARED(Shader);
|
||||
|
||||
void load(const std::string& path);
|
||||
void load(const std::vector<uc>& data);
|
||||
void compile(const std::string& code);
|
||||
void use();
|
||||
void input(int reg, GPU_FORMATS f, int num);
|
||||
void input(GPU_FORMATS f, int num) { input(m_reg++, f, num); }
|
||||
void setMat4(int loc, C3D_Mtx* m);
|
||||
void setMat4(int loc, const mat4& m);
|
||||
int loc(const std::string& name);
|
||||
void Load(ksr path);
|
||||
void Load(kvr<uc> data);
|
||||
void Compile(ksr code);
|
||||
void Use();
|
||||
void Input(int reg, GPU_FORMATS f, int num);
|
||||
void Input(GPU_FORMATS f, int num) { Input(pReg++, f, num); }
|
||||
void SetMat4(int loc, C3D_Mtx* m);
|
||||
void SetMat4(int loc, const mat4& m);
|
||||
int loc(ksr name);
|
||||
|
||||
private:
|
||||
C3D_AttrInfo m_info;
|
||||
shaderProgram_s m_program;
|
||||
DVLB_s* m_code;
|
||||
int m_reg = 0;
|
||||
// private:
|
||||
C3D_AttrInfo pInfo;
|
||||
shaderProgram_s pProgram;
|
||||
DVLB_s* pCode = nullptr;
|
||||
int pReg = 0;
|
||||
std::vector<uc> pRawData;
|
||||
};
|
||||
|
||||
class frag {
|
||||
class Frag {
|
||||
public:
|
||||
frag() = default;
|
||||
~frag() = default;
|
||||
Frag() = default;
|
||||
~Frag() = default;
|
||||
|
||||
static void edit(int id = 0);
|
||||
static void src(C3D_TexEnvMode mode, GPU_TEVSRC s1 = GPU_PRIMARY_COLOR,
|
||||
static void Edit(int id = 0);
|
||||
static void Src(C3D_TexEnvMode mode, GPU_TEVSRC s1 = GPU_PRIMARY_COLOR,
|
||||
GPU_TEVSRC s2 = GPU_PRIMARY_COLOR,
|
||||
GPU_TEVSRC s3 = GPU_PRIMARY_COLOR);
|
||||
static void func(C3D_TexEnvMode mode, GPU_COMBINEFUNC func);
|
||||
static void Func(C3D_TexEnvMode mode, GPU_COMBINEFUNC func);
|
||||
|
||||
private:
|
||||
static C3D_TexEnv* m_env;
|
||||
static C3D_TexEnv* pEnv;
|
||||
};
|
||||
|
||||
static void init();
|
||||
static void deinit();
|
||||
static void startFrame(bool sync = true);
|
||||
static void endFrame();
|
||||
static screen* createScreen(gfxScreen_t screen, gfx3dSide_t side = GFX_LEFT);
|
||||
static void deleteScreen(screen* screen);
|
||||
static void drawArrays(int start, int count,
|
||||
static void Init();
|
||||
static void Deinit();
|
||||
static void StartFrame(bool sync = true);
|
||||
static void EndFrame();
|
||||
static Screen* CreateScreen(gfxScreen_t screen, gfx3dSide_t side = GFX_LEFT);
|
||||
static void DeleteScreen(Screen* screen);
|
||||
static void DrawArrays(int start, int count,
|
||||
GPU_Primitive_t prim = GPU_TRIANGLES);
|
||||
static void drawElements(int count, const void* idx_ptr,
|
||||
static void DrawElements(int count, const void* idx_ptr,
|
||||
int type = C3D_UNSIGNED_SHORT,
|
||||
GPU_Primitive_t prim = GPU_TRIANGLES);
|
||||
static void depthTest(bool on, GPU_TESTFUNC func = GPU_GREATER,
|
||||
static void DepthTest(bool on, GPU_TESTFUNC func = GPU_GREATER,
|
||||
GPU_WRITEMASK mask = GPU_WRITE_ALL);
|
||||
static void disableScissor();
|
||||
static void enableScissor(const ivec4 rect);
|
||||
static void DisableScissor();
|
||||
static void EnableScissor(const ivec4 rect);
|
||||
/**
|
||||
* Buf cfg die permutation at runtime berechnet
|
||||
*/
|
||||
static void bufCfg(void* ptr, int stride, int shader_attribs);
|
||||
static void BufCfg(void* ptr, int stride, int shader_attribs);
|
||||
/**
|
||||
* Klassische config bei der man selber die permutation eintragen muss
|
||||
*/
|
||||
static void bufCfg(void* ptr, int stride, int shader_attribs,
|
||||
static void BufCfg(void* ptr, int stride, int shader_attribs,
|
||||
u64 permutation);
|
||||
/**
|
||||
* Hacky funktion um die permutation automatisch at compile time zu berechnen,
|
||||
* falls diese immer gleich bleibt.
|
||||
* In der <> steht die anzahl der shader input werte
|
||||
* usage: c3d::bufCfg<3>(data, sizeof(vertex));
|
||||
* usage: C3D::bufCfg<3>(data, sizeof(vertex));
|
||||
*/
|
||||
template <int attribs>
|
||||
constexpr static void bufCfg(void* ptr, int stride) {
|
||||
constexpr static void BufCfg(void* ptr, int stride) {
|
||||
auto buf = C3D_GetBufInfo();
|
||||
BufInfo_Init(buf);
|
||||
constexpr int pm = permutation(attribs);
|
||||
constexpr int pm = pPermutation(attribs);
|
||||
BufInfo_Add(buf, ptr, stride, attribs, pm);
|
||||
}
|
||||
|
||||
static int drawcalls() { return m_drawcalls; }
|
||||
static int Drawcalls() { return pDrawcalls; }
|
||||
|
||||
private:
|
||||
static int m_drawcalls;
|
||||
static int m__dc__;
|
||||
static int pDrawcalls;
|
||||
static int p__dc__; // draw-calls internal
|
||||
|
||||
/**
|
||||
* Funktion die anhand von **ac** genau den permu station wert für BufInfo
|
||||
@@ -127,7 +132,7 @@ class c3d {
|
||||
* ac = 4 -> 0x3210
|
||||
* ```
|
||||
*/
|
||||
constexpr static u64 permutation(int ac) {
|
||||
constexpr static u64 pPermutation(int ac) {
|
||||
u64 ret = 0;
|
||||
if (ac < 1 || ac > 15) {
|
||||
throw std::runtime_error("[amy] " + std::to_string(ac) +
|
||||
@@ -139,4 +144,4 @@ class c3d {
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
@@ -0,0 +1,124 @@
|
||||
#pragma once
|
||||
|
||||
#include <amethyst/types.hpp>
|
||||
#include <amethyst/utils.hpp>
|
||||
|
||||
// We all know where the code is from ... RenderD7 -> Palladium/Amy
|
||||
|
||||
namespace Amy {
|
||||
class Color {
|
||||
public:
|
||||
/**
|
||||
* Default Constructor (all variables are set to 0)
|
||||
*/
|
||||
constexpr Color() : r(0), g(0), b(0), a(0) {}
|
||||
constexpr ~Color() {}
|
||||
/**
|
||||
* Constructor for 32Bit Color Input
|
||||
* @param color 32Bit Color value
|
||||
*/
|
||||
constexpr Color(ui clr) {
|
||||
a = (clr >> 24) & 0xff;
|
||||
b = (clr >> 16) & 0xff;
|
||||
g = (clr >> 8) & 0xff;
|
||||
r = clr & 0xff;
|
||||
}
|
||||
/**
|
||||
* Constructor for 8Bit Input
|
||||
* @param r Red Value
|
||||
* @param g Green Value
|
||||
* @param b Blue Value
|
||||
* @param a Optional Alpha Value (Defaults to 255)
|
||||
*/
|
||||
constexpr Color(int r, int g, int b, int a = 255) : r(r), g(g), b(b), a(a) {}
|
||||
/**
|
||||
* Constructor for float Input
|
||||
* @param r Red Value
|
||||
* @param g Green Value
|
||||
* @param b Blue Value
|
||||
* @param a Optional Alpha Value (Defaults to 1.0f)
|
||||
* @note There is no Check if the number is between 0.0 and 1.0
|
||||
*/
|
||||
constexpr Color(float r, float g, float b, float a = 1.f)
|
||||
: r(static_cast<uc>(255.f * r)),
|
||||
g(static_cast<uc>(255.f * g)),
|
||||
b(static_cast<uc>(255.f * b)),
|
||||
a(static_cast<uc>(255.f * a)) {}
|
||||
/**
|
||||
* Constructor for Hex Input
|
||||
* @param hex Hex String in `#ffffff` or `#ffffffff` format
|
||||
*/
|
||||
constexpr Color(const std::string& hex) { Hex(hex); }
|
||||
|
||||
/**
|
||||
* Create Color Object by Hex String
|
||||
* @param hex Hex String in `#ffffff` or `#ffffffff` format
|
||||
* @return Color class itself
|
||||
*/
|
||||
constexpr Color& Hex(const std::string& hex) {
|
||||
if (!(hex.length() == 7 || hex.length() == 9)) {
|
||||
throw "[PD] Color: hex string is not rgb or rgba!";
|
||||
}
|
||||
r = Utils::HexChar2Int(hex[1]) * 16 + Utils::HexChar2Int(hex[2]);
|
||||
g = Utils::HexChar2Int(hex[3]) * 16 + Utils::HexChar2Int(hex[4]);
|
||||
b = Utils::HexChar2Int(hex[5]) * 16 + Utils::HexChar2Int(hex[6]);
|
||||
if (hex.length() == 9) {
|
||||
a = Utils::HexChar2Int(hex[7]) * 16 + Utils::HexChar2Int(hex[8]);
|
||||
} else {
|
||||
a = 255;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Convert this Color Object to Hex string
|
||||
* @param rgba [default false] sets if 8 or 6 digit color should be returned
|
||||
* @return Color Hex String
|
||||
*/
|
||||
std::string Hex(bool rgba = false) const;
|
||||
|
||||
/**
|
||||
* Fade from Current to another Color
|
||||
* @param color Color to fade to
|
||||
* @param p Amount (supports -1.0 to 1.0 for use of sine)
|
||||
* @return Class Reference
|
||||
*/
|
||||
constexpr Color& Fade(const Color& color, float p) {
|
||||
a = static_cast<uc>((color.a - a) * ((p + 1.f) / 2));
|
||||
b = static_cast<uc>((color.b - b) * ((p + 1.f) / 2));
|
||||
g = static_cast<uc>((color.g - g) * ((p + 1.f) / 2));
|
||||
r = static_cast<uc>((color.r - r) * ((p + 1.f) / 2));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get 32Bit Color Value
|
||||
* @return 32Bit Color Value (ABGR iirc)
|
||||
*/
|
||||
constexpr ui Get() const { return (a << 24) | (b << 16) | (g << 8) | r; }
|
||||
/**
|
||||
* Get The Luminance of the Color
|
||||
* @return luminance (from 0.0 to 1.0)
|
||||
*/
|
||||
constexpr float Luminance() const {
|
||||
// For Reference https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness
|
||||
return (0.3 * (r / 255.f) + 0.59 * (g / 255.f) + 0.11 * (b / 255.f));
|
||||
}
|
||||
/**
|
||||
* Check if the Color is Light or Dark
|
||||
* @return true if light
|
||||
*/
|
||||
constexpr bool IsLight() const { return (Luminance() >= 0.5); }
|
||||
|
||||
/**
|
||||
* Operator to cast Color to 32Bit Value
|
||||
* @return 32Bit Color Value
|
||||
*/
|
||||
constexpr operator ui() const { return Get(); }
|
||||
|
||||
/** Public Access Data section */
|
||||
uc r;
|
||||
uc g;
|
||||
uc b;
|
||||
uc a;
|
||||
};
|
||||
} // namespace Amy
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <amethyst/types.hpp>
|
||||
|
||||
namespace amy {
|
||||
namespace ctru {
|
||||
enum services {
|
||||
romfs = 1 << 0,
|
||||
cfgu = 1 << 1,
|
||||
gfx = 1 << 2,
|
||||
gfx_def = 1 << 3,
|
||||
def = romfs | gfx_def
|
||||
};
|
||||
void init(unsigned int srv = def);
|
||||
ull getTime();
|
||||
} // namespace ctru
|
||||
} // namespace amy
|
||||
@@ -1,13 +1,212 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <amethyst/types.hpp>
|
||||
#include <amethyst/id.hpp>
|
||||
|
||||
namespace amy {
|
||||
class gtrace {
|
||||
namespace Amy {
|
||||
class GTrace {
|
||||
public:
|
||||
gtrace() = default;
|
||||
~gtrace() = default;
|
||||
GTrace() = default;
|
||||
~GTrace() = default;
|
||||
|
||||
class Stats {
|
||||
public:
|
||||
/**
|
||||
* Constructor taking a lengh for the List
|
||||
* @param l Lengh of the data list
|
||||
*/
|
||||
Stats(int l) : len(l), val(l, 0) {}
|
||||
~Stats() = default;
|
||||
|
||||
AMY_SHARED(Stats);
|
||||
|
||||
/**
|
||||
* Add a New Value to the list
|
||||
* @param v value to add
|
||||
*/
|
||||
void Add(ull v) {
|
||||
val[idx] = v;
|
||||
idx = next(idx);
|
||||
num_val = std::min(num_val + 1, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Avarage Num
|
||||
* @return Average
|
||||
*/
|
||||
ull GetAverage() {
|
||||
if (!num_val) return 0.f;
|
||||
ull res = 0;
|
||||
for (int i = 0; i < num_val; i++) {
|
||||
res += val[smart_idx(i)];
|
||||
}
|
||||
return res / num_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Minimum Num
|
||||
* @return Minimum value
|
||||
*/
|
||||
ull GetMin() {
|
||||
if (!num_val) return 0.f;
|
||||
ull res = std::numeric_limits<ull>::max();
|
||||
for (int i = 0; i < num_val; i++) {
|
||||
res = std::min(val[smart_idx(i)], res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Maximum Value
|
||||
* @return Max Value
|
||||
*/
|
||||
ull GetMax() {
|
||||
if (!num_val) return 0.f;
|
||||
ull res = 0;
|
||||
for (int i = 0; i < num_val; i++) {
|
||||
res = std::max(val[smart_idx(i)], res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the List
|
||||
*/
|
||||
void Clear() {
|
||||
val.assign(len, 0);
|
||||
idx = 0;
|
||||
num_val = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Data Buffer
|
||||
* @return data bufer (not edidable)
|
||||
*/
|
||||
const std::vector<ull>& GetData() { return val; }
|
||||
/**
|
||||
* Access an element in the list [not edidable]
|
||||
* @return value to access
|
||||
*/
|
||||
const ull& operator[](int i) { return val[smart_idx(i)]; }
|
||||
/**
|
||||
* Get List Lengh
|
||||
* @return Lengh
|
||||
*/
|
||||
const size_t GetLen() { return len; }
|
||||
/**
|
||||
* Get Number of Values
|
||||
* @return number of values
|
||||
*/
|
||||
const size_t GetNumValues() { return num_val; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* Get the Next Position to write to
|
||||
* @param c current position
|
||||
* @return next position
|
||||
*/
|
||||
size_t next(size_t c) const { return (c + 1) % len; }
|
||||
/**
|
||||
* Smart Indexing in for loops to make sure to
|
||||
* not index a value that was not set yet
|
||||
* @param v pos in for loop
|
||||
* @return indexing pos
|
||||
*/
|
||||
size_t smart_idx(size_t v) const { return (idx + len - num_val + v) % len; }
|
||||
|
||||
/** Lengh of the list */
|
||||
int len = 0;
|
||||
/** Value Storage */
|
||||
std::vector<ull> val;
|
||||
int idx = 0;
|
||||
int num_val = 0;
|
||||
};
|
||||
} // namespace amy
|
||||
|
||||
class Trace {
|
||||
public:
|
||||
Trace() { protocol = Stats::New(60); }
|
||||
~Trace() = default;
|
||||
|
||||
AMY_SHARED(Trace);
|
||||
|
||||
void SetID(ksr v) { Name = v; }
|
||||
kstr GetID() { return Name; }
|
||||
void SetStart(ull v) { Start = v; }
|
||||
ull GetStart() { return Start; }
|
||||
void SetEnd(ull v) {
|
||||
End = v;
|
||||
Diff = End - Start;
|
||||
protocol->Add(GetLastDiff());
|
||||
}
|
||||
ull GetEnd() { return End; }
|
||||
ull GetLastDiff() { return Diff; }
|
||||
Stats::Ref GetProtocol() { return protocol; }
|
||||
|
||||
private:
|
||||
str Name;
|
||||
ull Start = 0;
|
||||
ull End = 0;
|
||||
ull Diff = 0;
|
||||
Stats::Ref protocol;
|
||||
};
|
||||
|
||||
/**
|
||||
* Begin a Trace
|
||||
* @param id Name of the Trace
|
||||
*/
|
||||
static void Beg(ksr id);
|
||||
/**
|
||||
* End a Trace
|
||||
* @param id Name of the Trace
|
||||
*/
|
||||
static void End(ksr id);
|
||||
|
||||
/**
|
||||
* Collect Start end end of the trace by tracking
|
||||
* when the Scope object goes out of scope
|
||||
*
|
||||
* Example:
|
||||
* ```cpp
|
||||
* void SomeFunction() {
|
||||
* // Create a Scoped Trace called "SomeFunc"
|
||||
* PD::TT::Scope st("SomeFunc");
|
||||
* // Do your functions stuff
|
||||
* // End at the end it goes out of
|
||||
* // scope which collects the end time
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class Scope {
|
||||
public:
|
||||
/**
|
||||
* Constructor requiring a Name for the Trace
|
||||
* @param id Name of the Trace
|
||||
*/
|
||||
Scope(ksr id) {
|
||||
this->ID = id;
|
||||
GTrace::Beg(id);
|
||||
}
|
||||
/**
|
||||
* Deconstructor getting the end time when going out of scope
|
||||
*/
|
||||
~Scope() { GTrace::End(ID); }
|
||||
|
||||
private:
|
||||
/** Trace Name/ID */
|
||||
str ID;
|
||||
};
|
||||
using TraceMap = std::unordered_map<std::string, Trace::Ref>;
|
||||
static TraceMap& GetTraceMap() { return GetTraceMap(); }
|
||||
static Trace::Ref& GetTraceRef(ksr id) {
|
||||
if (!pTraces.count(id)) {
|
||||
pTraces[id] = Trace::New();
|
||||
pTraces[id]->SetID(id);
|
||||
}
|
||||
return pTraces[id];
|
||||
}
|
||||
static bool TraceExist(ksr id) { return pTraces.count(id); }
|
||||
|
||||
private:
|
||||
static TraceMap pTraces;
|
||||
};
|
||||
} // namespace Amy
|
||||
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <amethyst/types.hpp>
|
||||
#include <amethyst/utils.hpp>
|
||||
|
||||
namespace Amy {
|
||||
class ID {
|
||||
public:
|
||||
constexpr ID(const ui& id) { pID = id; }
|
||||
constexpr ID(std::string name) {
|
||||
pID = Utils::FNV32(name);
|
||||
#ifdef AMY_KEEP_STR_ID
|
||||
pName = name;
|
||||
#endif
|
||||
}
|
||||
constexpr ID(const char* name) {
|
||||
pID = Utils::FNV32(name);
|
||||
#ifdef AMY_KEEP_STR_ID
|
||||
pName = name;
|
||||
#endif
|
||||
}
|
||||
~ID() {}
|
||||
|
||||
ui GetID() { return pID; }
|
||||
std::string GetName() const {
|
||||
#ifdef AMY_KEEP_STR_ID
|
||||
return pName;
|
||||
#else
|
||||
return std::format("hash({:#08x})", pID);
|
||||
#endif
|
||||
}
|
||||
|
||||
operator ui() const { return pID; }
|
||||
operator std::string() const { return GetName(); }
|
||||
|
||||
private:
|
||||
ui pID;
|
||||
#ifdef AMY_KEEP_STR_ID
|
||||
str pName;
|
||||
#endif
|
||||
};
|
||||
} // namespace Amy
|
||||
+32
-31
@@ -2,54 +2,55 @@
|
||||
|
||||
#include <amethyst/types.hpp>
|
||||
|
||||
namespace amy {
|
||||
class image {
|
||||
namespace Amy {
|
||||
class Image {
|
||||
public:
|
||||
enum format {
|
||||
enum Format {
|
||||
RGBA, // bpp == 4
|
||||
RGB, // bpp == 3
|
||||
RGB565, // bpp == 2 (not supported in laoding)
|
||||
BGR, // bpp == 3
|
||||
ABGR, // bpp == 4
|
||||
BGRA, // bpp == 4
|
||||
A8, // bpp == 1 (not supported in laoding)
|
||||
};
|
||||
image() = default;
|
||||
image(cstr& path) { this->load(path); }
|
||||
image(const std::vector<uc>& buf) { this->load(buf); }
|
||||
image(const std::vector<uc>& buf, int w, int h, const format& fmt) {
|
||||
this->copy(buf, w, h, fmt);
|
||||
Image() = default;
|
||||
Image(ksr path) { this->Load(path); }
|
||||
Image(kvr<uc> buf) { this->Load(buf); }
|
||||
Image(kvr<uc> buf, int w, int h, const Format& fmt) {
|
||||
this->Copy(buf, w, h, fmt);
|
||||
}
|
||||
~image() = default;
|
||||
~Image() = default;
|
||||
|
||||
void load(cstr& path);
|
||||
void load(const std::vector<uc>& buf);
|
||||
void copy(const std::vector<uc>& buf, int w, int h, const format& fmt);
|
||||
void Load(ksr path);
|
||||
void Load(kvr<uc> buf);
|
||||
void Copy(kvr<uc> buf, int w, int h, const Format& fmt);
|
||||
|
||||
std::vector<uc>& getBuffer() { return m_buffer; }
|
||||
std::vector<uc> getBuffer() const { return m_buffer; }
|
||||
vec<uc>& GetBuffer() { return pBuffer; }
|
||||
vec<uc> GetBuffer() const { return pBuffer; }
|
||||
|
||||
int width() const { return m_w; }
|
||||
int height() const { return m_h; }
|
||||
int bpp() const { return getBppOfFmt(m_fmt); }
|
||||
format fmt() const { return m_fmt; }
|
||||
void convert(const format& dst) { convert(*this, dst); }
|
||||
void retile(std::function<ui(int x, int y, int w)> src,
|
||||
int Width() const { return pW; }
|
||||
int Height() const { return pH; }
|
||||
int Bpp() const { return GetBppOfFmt(pFmt); }
|
||||
Format Fmt() const { return pFmt; }
|
||||
void Convert(const Format& dst) { Convert(*this, dst); }
|
||||
void Retile(std::function<ui(int x, int y, int w)> src,
|
||||
std::function<ui(int x, int y, int w)> dst) {
|
||||
retile(*this, src, dst);
|
||||
Retile(*this, src, dst);
|
||||
}
|
||||
|
||||
uc& operator[](int idx) { return m_buffer[idx]; }
|
||||
uc operator[](int idx) const { return m_buffer[idx]; }
|
||||
uc& operator[](int idx) { return pBuffer[idx]; }
|
||||
uc operator[](int idx) const { return pBuffer[idx]; }
|
||||
|
||||
static void convert(image& img, const format& dst);
|
||||
static void retile(image& img, std::function<ui(int x, int y, int w)> src,
|
||||
static void Convert(Image& img, const Format& dst);
|
||||
static void Retile(Image& img, std::function<ui(int x, int y, int w)> src,
|
||||
std::function<ui(int x, int y, int w)> dst);
|
||||
static int getBppOfFmt(const format& fmt);
|
||||
static int GetBppOfFmt(const Format& fmt);
|
||||
|
||||
private:
|
||||
std::vector<uc> m_buffer;
|
||||
int m_w = 0;
|
||||
int m_h = 0;
|
||||
format m_fmt = RGBA;
|
||||
vec<uc> pBuffer;
|
||||
int pW = 0;
|
||||
int pH = 0;
|
||||
Format pFmt = RGBA;
|
||||
};
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
+171
-97
@@ -8,157 +8,231 @@
|
||||
#include <amethyst/texture.hpp>
|
||||
#include <amethyst/types.hpp>
|
||||
|
||||
namespace amy {
|
||||
class iron {
|
||||
using AmyTextFlags = Amy::ui;
|
||||
enum AmyTextFlags_ {
|
||||
AmyTextFlags_None = 0, ///< Do nothing
|
||||
AmyTextFlags_AlignRight = 1 << 0, ///< Align Right of position
|
||||
AmyTextFlags_AlignMid = 1 << 1, ///< Align in the middle of pos and box
|
||||
AmyTextFlags_Shaddow = 1 << 2, ///< Draws the text twice to create shaddow
|
||||
AmyTextFlags_Wrap = 1 << 3, ///< Wrap Text: May be runs better with TMS
|
||||
AmyTextFlags_Short = 1 << 4, ///< Short Text: May be runs better with TMS
|
||||
AmyTextFlags_Scroll = 1 << 5, ///< Not implemented [scoll text if to long]
|
||||
};
|
||||
|
||||
namespace Amy {
|
||||
class Iron {
|
||||
public:
|
||||
struct vertex {
|
||||
vertex(float x, float y, float u, float v, ui clr) {
|
||||
struct Vertex {
|
||||
Vertex(float x, float y, float u, float v, ui clr) {
|
||||
pos.x = x;
|
||||
pos.y = y;
|
||||
uv.x = x;
|
||||
uv.y = y;
|
||||
uv.x = u;
|
||||
uv.y = v;
|
||||
color = clr;
|
||||
}
|
||||
vertex(const fvec2& pos, const fvec2& uv, ui clr) {
|
||||
Vertex(const fvec2& pos, const fvec2& uv, ui clr) {
|
||||
this->pos = pos;
|
||||
this->uv = uv;
|
||||
this->color = clr;
|
||||
}
|
||||
vertex() {}
|
||||
Vertex() {}
|
||||
|
||||
amy::fvec2 pos;
|
||||
amy::fvec2 uv;
|
||||
fvec2 pos;
|
||||
fvec2 uv;
|
||||
ui color = 0;
|
||||
};
|
||||
class command {
|
||||
class Command {
|
||||
public:
|
||||
command() = default;
|
||||
using ref = up<command>;
|
||||
command& add(const u16& idx) {
|
||||
indexBuf.push_back(vertexBuf.size() + idx);
|
||||
Command() = default;
|
||||
~Command() = default;
|
||||
AMY_UNIQUE(Command)
|
||||
|
||||
Command& Add(const u16& idx) {
|
||||
IndexBuf.push_back(VertexBuf.size() + idx);
|
||||
return *this;
|
||||
}
|
||||
command& add(const vertex& vtx) {
|
||||
vertexBuf.push_back(std::move(vtx));
|
||||
Command& Add(const Vertex& vtx) {
|
||||
VertexBuf.push_back(std::move(vtx));
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::vector<vertex> vertexBuf;
|
||||
std::vector<u16> indexBuf;
|
||||
ivec4 scissorRect;
|
||||
bool scissorOn = false;
|
||||
int layer;
|
||||
int index;
|
||||
texture* tex;
|
||||
std::vector<Vertex> VertexBuf;
|
||||
std::vector<u16> IndexBuf;
|
||||
ivec4 ScissorRect;
|
||||
bool ScissorOn = false;
|
||||
int Layer = 0;
|
||||
int Index = 0;
|
||||
Texture::Ref Tex = nullptr;
|
||||
};
|
||||
class drawlist {
|
||||
|
||||
class Font : public Asset {
|
||||
public:
|
||||
drawlist() { drawSolid(); }
|
||||
~drawlist() { m_data.clear(); }
|
||||
struct Codepoint {
|
||||
ui Cp = 0;
|
||||
fvec4 Uv;
|
||||
Texture::Ref Tex = nullptr;
|
||||
fvec2 Size;
|
||||
float Offset = 0; // Unused??
|
||||
bool Valid = true;
|
||||
};
|
||||
|
||||
Font() = default;
|
||||
~Font() = default;
|
||||
AMY_SHARED(Font)
|
||||
|
||||
void LoadTTF(ksr path, int pxh = 32);
|
||||
void LoadTTF(kvr<uc> data, int pxh = 32);
|
||||
/**
|
||||
* Bitmap Font BTW
|
||||
*/
|
||||
void LoadBMF(ksr path);
|
||||
|
||||
Codepoint& GetCodepoint(ui c);
|
||||
|
||||
fvec2 GetTextBounds(ksr text, float scale);
|
||||
void CmdTextEx(vec<Command::Ref>& cmds, const fvec2& pos, ui color,
|
||||
float scale, ksr text, AmyTextFlags flags = 0,
|
||||
const fvec2& box = 0);
|
||||
void pMakeAtlas(bool final, vec<uc>& pixels, int size, Texture::Ref tex);
|
||||
|
||||
int PxHeight;
|
||||
int PxFactor = 24;
|
||||
vec<Texture::Ref> Textures;
|
||||
std::map<u32, Codepoint> pCodeMap;
|
||||
};
|
||||
|
||||
class Drawlist {
|
||||
public:
|
||||
Drawlist() { DrawSolid(); }
|
||||
~Drawlist() { pData.clear(); }
|
||||
AMY_SHARED(Drawlist)
|
||||
|
||||
// required due to memory management
|
||||
drawlist(const drawlist&) = delete;
|
||||
drawlist& operator=(const drawlist&) = delete;
|
||||
drawlist(drawlist&&) noexcept = default;
|
||||
drawlist& operator=(drawlist&&) noexcept = default;
|
||||
Drawlist(const Drawlist&) = delete;
|
||||
Drawlist& operator=(const Drawlist&) = delete;
|
||||
Drawlist(Drawlist&&) noexcept = default;
|
||||
Drawlist& operator=(Drawlist&&) noexcept = default;
|
||||
|
||||
std::vector<command::ref>& data() { return m_data; }
|
||||
std::vector<Command::Ref>& Data() { return pData; }
|
||||
|
||||
void merge(drawlist* list);
|
||||
command::ref newCommand();
|
||||
void push(command ::ref cmd);
|
||||
void clear();
|
||||
|
||||
void drawSolid();
|
||||
void drawTex(texture* tex) { m_tex = tex; }
|
||||
void Merge(Drawlist* list);
|
||||
Command::Ref NewCommand();
|
||||
void Push(Command ::Ref cmd);
|
||||
void Clear();
|
||||
|
||||
void DrawSolid();
|
||||
void DrawTex(Texture::Ref tex) { pTex = tex; }
|
||||
void DrawFromAtlas(fvec2 pos, fvec2 size, fvec4 cut_rect,
|
||||
ui color = 0xffffffff);
|
||||
void DrawFromAtlas(fvec2 pos, fvec2 size, fvec4 cut_rect, Texture::Ref tex,
|
||||
ui color = 0xffffffff) {
|
||||
DrawTex(tex);
|
||||
DrawFromAtlas(pos, size, cut_rect, color);
|
||||
DrawSolid();
|
||||
}
|
||||
void SetFont(Font::Ref fnt) { pCurrentFont = fnt; }
|
||||
void SetFontScale(float v) { pFontScale = v; }
|
||||
float GetFontScale() { return pFontScale; }
|
||||
void DefaultFontScale() { pFontScale = 0.7; }
|
||||
/** Draw Api */
|
||||
void drawRect(const fvec2& pos, const fvec2& size, ui color,
|
||||
void DrawRect(const fvec2& pos, const fvec2& size, ui color,
|
||||
int thickness = 1);
|
||||
void drawRectFilled(const fvec2& pos, const fvec2& size, ui color);
|
||||
void drawTriangle(const fvec2& a, const fvec2& b, const fvec2& c, ui color,
|
||||
void DrawRectFilled(const fvec2& pos, const fvec2& size, ui color);
|
||||
void DrawTriangle(const fvec2& a, const fvec2& b, const fvec2& c, ui color,
|
||||
int thickness = 1);
|
||||
void drawTriangleFilled(const fvec2& a, const fvec2& b, const fvec2& c,
|
||||
void DrawTriangleFilled(const fvec2& a, const fvec2& b, const fvec2& c,
|
||||
ui color);
|
||||
void drawCircle(const fvec2& center, float radius, ui color, int segments,
|
||||
void DrawCircle(const fvec2& center, float radius, ui color, int segments,
|
||||
int thickness = 1);
|
||||
void drawCircleFilled(const fvec2& center, float radius, ui color,
|
||||
void DrawCircleFilled(const fvec2& center, float radius, ui color,
|
||||
int segments);
|
||||
void drawText(const fvec2& pos, const std::string& text, ui color);
|
||||
void drawTextEx(const fvec2& pos, const std::string& text, ui color,
|
||||
void DrawText(const fvec2& pos, const std::string& text, ui color);
|
||||
void DrawTextEx(const fvec2& pos, const std::string& text, ui color,
|
||||
ui flags, const fvec2& box = 0);
|
||||
void drawLine(const fvec2& a, const fvec2& b, ui color, int thickness = 1);
|
||||
void drawPolyLine(const std::vector<fvec2>& points, ui color, ui flags = 0,
|
||||
void DrawLine(const fvec2& a, const fvec2& b, ui color, int thickness = 1);
|
||||
void DrawPolyLine(const std::vector<fvec2>& points, ui color, ui flags = 0,
|
||||
int thickness = 1);
|
||||
void drawConvexPolyFilled(const std::vector<fvec2>& points, ui color);
|
||||
void DrawConvexPolyFilled(const std::vector<fvec2>& points, ui color);
|
||||
|
||||
/** Path api */
|
||||
void pathAdd(const fvec2& pos) { m_path.push_back(std::move(pos)); }
|
||||
void pathClear() { m_path.clear(); }
|
||||
void pathReserve(size_t count) { m_path.reserve(m_path.size() + count); }
|
||||
void pathStroke(ui color, int thickness = 1, ui flags = 0) {
|
||||
drawPolyLine(m_path, color, flags, thickness);
|
||||
pathClear();
|
||||
void PathAdd(const fvec2& pos) { pPath.push_back(std::move(pos)); }
|
||||
void PathClear() { pPath.clear(); }
|
||||
void PathReserve(size_t count) { pPath.reserve(pPath.size() + count); }
|
||||
void PathStroke(ui color, int thickness = 1, ui flags = 0) {
|
||||
DrawPolyLine(pPath, color, flags, thickness);
|
||||
PathClear();
|
||||
}
|
||||
void pathFill(ui color) { drawConvexPolyFilled(m_path, color); }
|
||||
void pathArcToN(const fvec2& c, float radius, float a_min, float a_max,
|
||||
void PathFill(ui color) {
|
||||
DrawConvexPolyFilled(pPath, color);
|
||||
PathClear();
|
||||
}
|
||||
void PathArcToN(const fvec2& c, float radius, float a_min, float a_max,
|
||||
int segments);
|
||||
void pathFastArcToN(const fvec2& c, float radius, float a_min, float a_max,
|
||||
void PathFastArcToN(const fvec2& c, float radius, float a_min, float a_max,
|
||||
int segments);
|
||||
void pathRect(const fvec2& a, const fvec2& b, float rounding = 0.f);
|
||||
void pathRectEx(const fvec2& a, const fvec2& b, float rounfing, ui flags);
|
||||
void PathRect(const fvec2& a, const fvec2& b, float rounding = 0.f);
|
||||
void PathRectEx(const fvec2& a, const fvec2& b, float rounfing, ui flags);
|
||||
|
||||
void pushClipRect(const fvec4& clip) { clipRects.push(clip); }
|
||||
void popClipRect() {
|
||||
if (!clipRects.empty()) clipRects.pop();
|
||||
void PushClipRect(const fvec4& clip) { ClipRects.push(clip); }
|
||||
void PopClipRect() {
|
||||
if (!ClipRects.empty()) ClipRects.pop();
|
||||
}
|
||||
|
||||
operator std::vector<command::ref>&() { return m_data; }
|
||||
operator std::vector<Command::Ref>&() { return pData; }
|
||||
|
||||
private:
|
||||
void clipCmd(command* ptr);
|
||||
std::vector<command::ref> m_data;
|
||||
std::vector<fvec2> m_path;
|
||||
texture* m_tex = nullptr;
|
||||
std::stack<fvec4> clipRects;
|
||||
int m_layer = 0;
|
||||
void clipCmd(Command* ptr);
|
||||
std::vector<Command::Ref> pData;
|
||||
std::vector<fvec2> pPath;
|
||||
Texture::Ref pTex = nullptr;
|
||||
std::stack<fvec4> ClipRects;
|
||||
Font::Ref pCurrentFont;
|
||||
int pLayer = 0;
|
||||
float pFontScale = 0.7;
|
||||
};
|
||||
iron() = default;
|
||||
~iron() = default;
|
||||
Iron() = default;
|
||||
~Iron() = default;
|
||||
|
||||
static void init();
|
||||
static void newFrame();
|
||||
static void drawOn(c3d::screen* screen);
|
||||
static void draw(const std::vector<command::ref>& data);
|
||||
static texture* whiteTex() { return m_solid; }
|
||||
static void Init();
|
||||
static void Exit();
|
||||
static void NewFrame();
|
||||
static void DrawOn(C3D::Screen* screen);
|
||||
static void Draw(const std::vector<Command::Ref>& data);
|
||||
static Texture::Ref WhiteTex() { return m_solid; }
|
||||
|
||||
/** Static renderer utility funcs */
|
||||
|
||||
static void rotateCorner(fvec2& pos, float s, float c);
|
||||
static rect primRect(const fvec2& pos, const fvec2& size, float angle = 0.f);
|
||||
static rect primLine(const fvec2& a, const fvec2& b, int thickness = 1);
|
||||
static void cmdQuad(command* cmd, const rect& q, const rect& uv, ui color);
|
||||
static void cmdTriangle(command* cmd, const fvec2& a, const fvec2& b,
|
||||
static void RotateCorner(fvec2& pos, float s, float c);
|
||||
static Rect PrimRect(const fvec2& pos, const fvec2& size, float angle = 0.f);
|
||||
static Rect PrimLine(const fvec2& a, const fvec2& b, int thickness = 1);
|
||||
static void CmdQuad(Command* cmd, const Rect& q, const Rect& uv, ui color);
|
||||
static void CmdTriangle(Command* cmd, const fvec2& a, const fvec2& b,
|
||||
const fvec2& c, ui clr);
|
||||
static void cmdConvexPolyFilled(command* cmd,
|
||||
static void CmdConvexPolyFilled(Command* cmd,
|
||||
const std::vector<fvec2>& points, ui clr,
|
||||
texture* tex);
|
||||
static bool inBox(const fvec2& pos, const fvec2& size, const fvec4& area);
|
||||
static bool inBox(const fvec2& pos, const fvec4& area);
|
||||
static bool inBox(const fvec2& a, const fvec2& b, const fvec2& c,
|
||||
Texture::Ref tex);
|
||||
static bool InBox(const fvec2& pos, const fvec2& size, const fvec4& area);
|
||||
static bool InBox(const fvec2& pos, const fvec4& area);
|
||||
static bool InBox(const fvec2& a, const fvec2& b, const fvec2& c,
|
||||
const fvec4& area);
|
||||
|
||||
private:
|
||||
static void setupShader();
|
||||
static void fragConfig();
|
||||
static void initSolidTex();
|
||||
static ui VerticesDrawn() { return VertexCount; }
|
||||
static ui IndicesDrawn() { return IndexCount; }
|
||||
|
||||
static std::vector<vertex, linearAllocator<vertex>> m_vbuf;
|
||||
static std::vector<u16, linearAllocator<u16>> m_ibuf;
|
||||
private:
|
||||
static void pSetupShader();
|
||||
static void pFragConfig(GPU_TEXCOLOR clr);
|
||||
static void pInitSolidTex();
|
||||
static bool pCheckSize(size_t idx, size_t vtx);
|
||||
|
||||
static std::vector<Vertex, LinearAllocator<Vertex>> m_vbuf;
|
||||
static std::vector<u16, LinearAllocator<u16>> m_ibuf;
|
||||
static int uLocProj;
|
||||
static c3d::shader* m_shader;
|
||||
static C3D::Shader* m_shader;
|
||||
static mat4 m_mtx;
|
||||
static int m_idx, m_vtx;
|
||||
static texture* m_solid;
|
||||
static Texture::Ref m_solid;
|
||||
static ui VertexCount;
|
||||
static ui IndexCount;
|
||||
};
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
|
||||
@@ -9,28 +9,42 @@
|
||||
// based on this guide:
|
||||
// https://johnfarrier.com/custom-allocators-in-c-high-performance-memory-management/
|
||||
|
||||
namespace amy {
|
||||
namespace Amy {
|
||||
template <typename T>
|
||||
class linearAllocator {
|
||||
class LinearAllocator {
|
||||
public:
|
||||
using value_type = T;
|
||||
linearAllocator() = default;
|
||||
LinearAllocator() noexcept = default;
|
||||
template <typename U>
|
||||
constexpr linearAllocator(const linearAllocator<U>&) noexcept {}
|
||||
constexpr LinearAllocator(const LinearAllocator<U>&) noexcept {}
|
||||
|
||||
T* allocate(std::size_t n) {
|
||||
if (n > std::allocator_traits<linearAllocator>::max_size(*this)) {
|
||||
throw std::bad_alloc();
|
||||
if (n > max_size()) {
|
||||
throw std::runtime_error("[Amy] LinearAllocator: Bad alloc!");
|
||||
}
|
||||
return static_cast<T*>(linearAlloc(n * sizeof(T)));
|
||||
}
|
||||
void deallocate(T* p, std::size_t) noexcept { linearFree(p); }
|
||||
|
||||
friend bool operator==(const linearAllocator, const linearAllocator) {
|
||||
template <class U, class... Args>
|
||||
void construct(U* p, Args&&... args) {
|
||||
::new ((void*)p) U(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
void destroy(U* p) {
|
||||
p->~U();
|
||||
}
|
||||
|
||||
friend bool operator==(const LinearAllocator, const LinearAllocator) {
|
||||
return true;
|
||||
}
|
||||
friend bool operator!=(const linearAllocator, const linearAllocator) {
|
||||
friend bool operator!=(const LinearAllocator, const LinearAllocator) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use linearSpace free as max_size to not allocate out of bounds
|
||||
// or to b eable to see a crash report screen.
|
||||
size_t max_size() const noexcept { return linearSpaceFree(); }
|
||||
};
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
@@ -29,11 +29,11 @@ SOFTWARE.
|
||||
#include <cmath>
|
||||
#include <numbers>
|
||||
|
||||
namespace amy {
|
||||
namespace numbers {
|
||||
namespace Amy {
|
||||
namespace Numbers {
|
||||
constexpr float Tau = std::numbers::pi * 2.f;
|
||||
}
|
||||
constexpr float Radians(float v) { return v * (numbers::Tau / 360.0f); }
|
||||
constexpr float Radians(float v) { return v * (Numbers::Tau / 360.0f); }
|
||||
/**
|
||||
* Minimal Mtx4 Lib that precomputes
|
||||
* basic stuff stuff at compiletime
|
||||
@@ -141,4 +141,4 @@ struct mat4 {
|
||||
static mat4 perspective(float fov, float aspect, float n, float f);
|
||||
static mat4 lookAt(const fvec3& pos, const fvec3& center, const fvec3& up);
|
||||
};
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
@@ -36,25 +36,25 @@ SOFTWARE.
|
||||
*/
|
||||
|
||||
template <typename T, typename CharT>
|
||||
struct std::formatter<amy::vec2<T>, CharT> : std::formatter<T, CharT> {
|
||||
struct std::formatter<Amy::vec2<T>, CharT> : std::formatter<T, CharT> {
|
||||
template <typename FormatContext>
|
||||
auto format(const amy::vec2<T> &v, FormatContext &ctx) const {
|
||||
auto format(const Amy::vec2<T>& v, FormatContext& ctx) const {
|
||||
return std::format_to(ctx.out(), "{}, {}", v.x, v.y);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename CharT>
|
||||
struct std::formatter<amy::vec3<T>, CharT> : std::formatter<T, CharT> {
|
||||
struct std::formatter<Amy::vec3<T>, CharT> : std::formatter<T, CharT> {
|
||||
template <typename FormatContext>
|
||||
auto format(const amy::vec3<T> &v, FormatContext &ctx) const {
|
||||
auto format(const Amy::vec3<T>& v, FormatContext& ctx) const {
|
||||
return std::format_to(ctx.out(), "{}, {}, {}", v.x, v.y, v.z);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename CharT>
|
||||
struct std::formatter<amy::vec4<T>, CharT> : std::formatter<T, CharT> {
|
||||
struct std::formatter<Amy::vec4<T>, CharT> : std::formatter<T, CharT> {
|
||||
template <typename FormatContext>
|
||||
auto format(const amy::vec4<T> &v, FormatContext &ctx) const {
|
||||
auto format(const Amy::vec4<T>& v, FormatContext& ctx) const {
|
||||
return std::format_to(ctx.out(), "{}, {}, {}, {}", v.x, v.y, v.z, v.w);
|
||||
}
|
||||
};
|
||||
@@ -27,8 +27,9 @@ SOFTWARE.
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace amy {
|
||||
template <typename T> class vec2 {
|
||||
namespace Amy {
|
||||
template <typename T>
|
||||
class vec2 {
|
||||
public:
|
||||
T x;
|
||||
T y;
|
||||
@@ -36,12 +37,14 @@ public:
|
||||
// Constructors
|
||||
|
||||
constexpr vec2() : x(0), y(0) {}
|
||||
template <typename T1> constexpr vec2(T1 v) {
|
||||
template <typename T1>
|
||||
constexpr vec2(T1 v) {
|
||||
x = (T)v;
|
||||
y = (T)v;
|
||||
}
|
||||
|
||||
template <typename T1> constexpr vec2(const vec2<T1> &v) {
|
||||
template <typename T1>
|
||||
constexpr vec2(const vec2<T1>& v) {
|
||||
x = (T)v.x;
|
||||
y = (T)v.y;
|
||||
}
|
||||
@@ -50,93 +53,111 @@ public:
|
||||
|
||||
// Operations
|
||||
|
||||
template <typename T1> vec2<T> &operator+=(T1 v) {
|
||||
template <typename T1>
|
||||
vec2<T>& operator+=(T1 v) {
|
||||
x += (T)v;
|
||||
y += (T)v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec2<T> &operator+=(const vec2<T1> &v) {
|
||||
template <typename T1>
|
||||
vec2<T>& operator+=(const vec2<T1>& v) {
|
||||
x += (T)v.x;
|
||||
y += (T)v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec2<T> operator+(T1 v) const {
|
||||
template <typename T1>
|
||||
vec2<T> operator+(T1 v) const {
|
||||
return vec2<T>(x + (T)v, y + (T)v);
|
||||
}
|
||||
|
||||
template <typename T1> vec2<T> operator+(const vec2<T1> &v) const {
|
||||
template <typename T1>
|
||||
vec2<T> operator+(const vec2<T1>& v) const {
|
||||
return vec2<T>(x + (T)v.x, y + (T)v.y);
|
||||
}
|
||||
|
||||
template <typename T1> vec2<T> &operator-=(T1 v) {
|
||||
template <typename T1>
|
||||
vec2<T>& operator-=(T1 v) {
|
||||
x -= (T)v;
|
||||
y -= (T)v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec2<T> &operator-=(const vec2<T1> &v) {
|
||||
template <typename T1>
|
||||
vec2<T>& operator-=(const vec2<T1>& v) {
|
||||
x -= (T)v.x;
|
||||
y -= (T)v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec2<T> operator-(T1 v) const {
|
||||
template <typename T1>
|
||||
vec2<T> operator-(T1 v) const {
|
||||
return vec2<T>(x - (T)v, y - (T)v);
|
||||
}
|
||||
|
||||
template <typename T1> vec2<T> operator-(const vec2<T1> &v) const {
|
||||
template <typename T1>
|
||||
vec2<T> operator-(const vec2<T1>& v) const {
|
||||
return vec2<T>(x - (T)v.x, y - (T)v.y);
|
||||
}
|
||||
|
||||
template <typename T1> vec2<T> &operator*=(T1 v) {
|
||||
template <typename T1>
|
||||
vec2<T>& operator*=(T1 v) {
|
||||
x *= (T)v;
|
||||
y *= (T)v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec2<T> &operator*=(const vec2<T1> &v) {
|
||||
template <typename T1>
|
||||
vec2<T>& operator*=(const vec2<T1>& v) {
|
||||
x *= (T)v.x;
|
||||
y *= (T)v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec2<T> operator*(T1 v) const {
|
||||
template <typename T1>
|
||||
vec2<T> operator*(T1 v) const {
|
||||
return vec2<T>(x * (T)v, y * (T)v);
|
||||
}
|
||||
|
||||
template <typename T1> vec2<T> operator*(const vec2<T1> &v) const {
|
||||
template <typename T1>
|
||||
vec2<T> operator*(const vec2<T1>& v) const {
|
||||
return vec2<T>(x * (T)v.x, y * (T)v.y);
|
||||
}
|
||||
|
||||
template <typename T1> vec2<T> &operator/=(T1 v) {
|
||||
template <typename T1>
|
||||
vec2<T>& operator/=(T1 v) {
|
||||
x /= (T)v;
|
||||
y /= (T)v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec2<T> &operator/=(const vec2<T1> &v) {
|
||||
template <typename T1>
|
||||
vec2<T>& operator/=(const vec2<T1>& v) {
|
||||
x /= (T)v.x;
|
||||
y /= (T)v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec2<T> operator/(T1 v) const {
|
||||
template <typename T1>
|
||||
vec2<T> operator/(T1 v) const {
|
||||
return vec2<T>(x / (T)v, y / (T)v);
|
||||
}
|
||||
|
||||
template <typename T1> vec2<T> operator/(const vec2<T1> &v) const {
|
||||
template <typename T1>
|
||||
vec2<T> operator/(const vec2<T1>& v) const {
|
||||
return vec2<T>(x / (T)v.x, y / (T)v.y);
|
||||
}
|
||||
|
||||
// Generic Operations
|
||||
|
||||
vec2 operator-() const { return vec2(-x, -y); }
|
||||
template <typename T1> bool operator==(const vec2<T1> &v) const {
|
||||
template <typename T1>
|
||||
bool operator==(const vec2<T1>& v) const {
|
||||
return x == (T)v.x && y == (T)v.y;
|
||||
}
|
||||
template <typename T1> bool operator!=(const vec2<T1> &v) const {
|
||||
template <typename T1>
|
||||
bool operator!=(const vec2<T1>& v) const {
|
||||
return !(*this == v);
|
||||
}
|
||||
|
||||
@@ -145,7 +166,8 @@ public:
|
||||
double Len() const { return std::sqrt(SqLen()); }
|
||||
double SqLen() const { return x * x + y * y; }
|
||||
|
||||
template <typename T1> double Distance(const vec2<T1> &v) const {
|
||||
template <typename T1>
|
||||
double Distance(const vec2<T1>& v) const {
|
||||
return (*this - v).Len();
|
||||
}
|
||||
|
||||
@@ -157,7 +179,8 @@ public:
|
||||
return *this / (T)l;
|
||||
}
|
||||
|
||||
template <typename T1> T Dot(const vec2<T1> &v) const {
|
||||
template <typename T1>
|
||||
T Dot(const vec2<T1>& v) const {
|
||||
return x * (T)v.x + y * (T)v.y;
|
||||
}
|
||||
|
||||
@@ -171,4 +194,4 @@ public:
|
||||
using fvec2 = vec2<float>;
|
||||
using ivec2 = vec2<int>;
|
||||
using dvec2 = vec2<double>;
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
|
||||
@@ -29,8 +29,9 @@ SOFTWARE.
|
||||
// Extended includes (rename if you use other filenames/paths)
|
||||
#include <amethyst/maths/vec2.hpp>
|
||||
|
||||
namespace amy {
|
||||
template <typename T> class vec3 {
|
||||
namespace Amy {
|
||||
template <typename T>
|
||||
class vec3 {
|
||||
public:
|
||||
T x;
|
||||
T y;
|
||||
@@ -39,13 +40,15 @@ public:
|
||||
// Constructors
|
||||
|
||||
constexpr vec3() : x(0), y(0), z(0) {}
|
||||
template <typename T1> constexpr vec3(T1 v) {
|
||||
template <typename T1>
|
||||
constexpr vec3(T1 v) {
|
||||
x = (T)v;
|
||||
y = (T)v;
|
||||
z = (T)v;
|
||||
}
|
||||
|
||||
template <typename T1> constexpr vec3(const vec3<T1> &v) {
|
||||
template <typename T1>
|
||||
constexpr vec3(const vec3<T1>& v) {
|
||||
x = (T)v.x;
|
||||
y = (T)v.y;
|
||||
z = (T)v.z;
|
||||
@@ -54,7 +57,8 @@ public:
|
||||
constexpr explicit vec3(T x, T y, T z) : x(x), y(y), z(z) {}
|
||||
|
||||
// Extended Constructors
|
||||
template <typename T1> constexpr explicit vec3(const vec2<T1> &xy, T1 z) {
|
||||
template <typename T1>
|
||||
constexpr explicit vec3(const vec2<T1>& xy, T1 z) {
|
||||
{
|
||||
x = (T)xy.x;
|
||||
y = (T)xy.y;
|
||||
@@ -64,101 +68,119 @@ public:
|
||||
|
||||
// Operations
|
||||
|
||||
template <typename T1> vec3<T> &operator+=(T1 v) {
|
||||
template <typename T1>
|
||||
vec3<T>& operator+=(T1 v) {
|
||||
x += (T)v;
|
||||
y += (T)v;
|
||||
z += (T)v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec3<T> &operator+=(const vec3<T1> &v) {
|
||||
template <typename T1>
|
||||
vec3<T>& operator+=(const vec3<T1>& v) {
|
||||
x += (T)v.x;
|
||||
y += (T)v.y;
|
||||
z += (T)v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec3<T> operator+(T1 v) const {
|
||||
template <typename T1>
|
||||
vec3<T> operator+(T1 v) const {
|
||||
return vec3<T>(x + (T)v, y + (T)v, z + (T)v);
|
||||
}
|
||||
|
||||
template <typename T1> vec3<T> operator+(const vec3<T1> &v) const {
|
||||
template <typename T1>
|
||||
vec3<T> operator+(const vec3<T1>& v) const {
|
||||
return vec3<T>(x + (T)v.x, y + (T)v.y, z + (T)v.z);
|
||||
}
|
||||
|
||||
template <typename T1> vec3<T> &operator-=(T1 v) {
|
||||
template <typename T1>
|
||||
vec3<T>& operator-=(T1 v) {
|
||||
x -= (T)v;
|
||||
y -= (T)v;
|
||||
z -= (T)v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec3<T> &operator-=(const vec3<T1> &v) {
|
||||
template <typename T1>
|
||||
vec3<T>& operator-=(const vec3<T1>& v) {
|
||||
x -= (T)v.x;
|
||||
y -= (T)v.y;
|
||||
z -= (T)v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec3<T> operator-(T1 v) const {
|
||||
template <typename T1>
|
||||
vec3<T> operator-(T1 v) const {
|
||||
return vec3<T>(x - (T)v, y - (T)v, z - (T)v);
|
||||
}
|
||||
|
||||
template <typename T1> vec3<T> operator-(const vec3<T1> &v) const {
|
||||
template <typename T1>
|
||||
vec3<T> operator-(const vec3<T1>& v) const {
|
||||
return vec3<T>(x - (T)v.x, y - (T)v.y, z - (T)v.z);
|
||||
}
|
||||
|
||||
template <typename T1> vec3<T> &operator*=(T1 v) {
|
||||
template <typename T1>
|
||||
vec3<T>& operator*=(T1 v) {
|
||||
x *= (T)v;
|
||||
y *= (T)v;
|
||||
z *= (T)v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec3<T> &operator*=(const vec3<T1> &v) {
|
||||
template <typename T1>
|
||||
vec3<T>& operator*=(const vec3<T1>& v) {
|
||||
x *= (T)v.x;
|
||||
y *= (T)v.y;
|
||||
z *= (T)v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec3<T> operator*(T1 v) const {
|
||||
template <typename T1>
|
||||
vec3<T> operator*(T1 v) const {
|
||||
return vec3<T>(x * (T)v, y * (T)v, z * (T)v);
|
||||
}
|
||||
|
||||
template <typename T1> vec3<T> operator*(const vec3<T1> &v) const {
|
||||
template <typename T1>
|
||||
vec3<T> operator*(const vec3<T1>& v) const {
|
||||
return vec3<T>(x * (T)v.x, y * (T)v.y, z * (T)v.z);
|
||||
}
|
||||
|
||||
template <typename T1> vec3<T> &operator/=(T1 v) {
|
||||
template <typename T1>
|
||||
vec3<T>& operator/=(T1 v) {
|
||||
x /= (T)v;
|
||||
y /= (T)v;
|
||||
z /= (T)v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec3<T> &operator/=(const vec3<T1> &v) {
|
||||
template <typename T1>
|
||||
vec3<T>& operator/=(const vec3<T1>& v) {
|
||||
x /= (T)v.x;
|
||||
y /= (T)v.y;
|
||||
z /= (T)v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec3<T> operator/(T1 v) const {
|
||||
template <typename T1>
|
||||
vec3<T> operator/(T1 v) const {
|
||||
return vec3<T>(x / (T)v, y / (T)v, z / (T)v);
|
||||
}
|
||||
|
||||
template <typename T1> vec3<T> operator/(const vec3<T1> &v) const {
|
||||
template <typename T1>
|
||||
vec3<T> operator/(const vec3<T1>& v) const {
|
||||
return vec3<T>(x / (T)v.x, y / (T)v.y, z / (T)v.z);
|
||||
}
|
||||
|
||||
// Generic Operations
|
||||
|
||||
vec3 operator-() const { return vec3(-x, -y, -z); }
|
||||
template <typename T1> bool operator==(const vec3<T1> &v) const {
|
||||
template <typename T1>
|
||||
bool operator==(const vec3<T1>& v) const {
|
||||
return x == (T)v.x && y == (T)v.y && z == (T)v.z;
|
||||
}
|
||||
template <typename T1> bool operator!=(const vec3<T1> &v) const {
|
||||
template <typename T1>
|
||||
bool operator!=(const vec3<T1>& v) const {
|
||||
return !(*this == v);
|
||||
}
|
||||
|
||||
@@ -167,7 +189,8 @@ public:
|
||||
double Len() const { return std::sqrt(SqLen()); }
|
||||
double SqLen() const { return x * x + y * y + z * z; }
|
||||
|
||||
template <typename T1> double Distance(const vec3<T1> &v) const {
|
||||
template <typename T1>
|
||||
double Distance(const vec3<T1>& v) const {
|
||||
return (*this - v).Len();
|
||||
}
|
||||
|
||||
@@ -179,11 +202,13 @@ public:
|
||||
return *this / (T)l;
|
||||
}
|
||||
|
||||
template <typename T1> T Dot(const vec3<T1> &v) const {
|
||||
template <typename T1>
|
||||
T Dot(const vec3<T1>& v) const {
|
||||
return x * (T)v.x + y * (T)v.y + z * (T)v.z;
|
||||
}
|
||||
|
||||
template <typename T1> vec3<T> Cross(const vec3<T1> &v) const {
|
||||
template <typename T1>
|
||||
vec3<T> Cross(const vec3<T1>& v) const {
|
||||
return vec3<T>(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
|
||||
}
|
||||
|
||||
@@ -207,4 +232,4 @@ public:
|
||||
using fvec3 = vec3<float>;
|
||||
using ivec3 = vec3<int>;
|
||||
using dvec3 = vec3<double>;
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
|
||||
@@ -30,8 +30,9 @@ SOFTWARE.
|
||||
#include <amethyst/maths/vec2.hpp>
|
||||
#include <amethyst/maths/vec3.hpp>
|
||||
|
||||
namespace amy {
|
||||
template <typename T> class vec4 {
|
||||
namespace Amy {
|
||||
template <typename T>
|
||||
class vec4 {
|
||||
public:
|
||||
T x;
|
||||
T y;
|
||||
@@ -41,14 +42,16 @@ public:
|
||||
// Constructors
|
||||
|
||||
constexpr vec4() : x(0), y(0), z(0), w(0) {}
|
||||
template <typename T1> constexpr vec4(T1 v) {
|
||||
template <typename T1>
|
||||
constexpr vec4(T1 v) {
|
||||
x = (T)v;
|
||||
y = (T)v;
|
||||
z = (T)v;
|
||||
w = (T)v;
|
||||
}
|
||||
|
||||
template <typename T1> constexpr vec4(const vec4<T1> &v) {
|
||||
template <typename T1>
|
||||
constexpr vec4(const vec4<T1>& v) {
|
||||
x = (T)v.x;
|
||||
y = (T)v.y;
|
||||
z = (T)v.z;
|
||||
@@ -68,7 +71,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1> constexpr explicit vec4(const vec3<T1> &xyz, T1 w) {
|
||||
template <typename T1>
|
||||
constexpr explicit vec4(const vec3<T1>& xyz, T1 w) {
|
||||
{
|
||||
x = (T)xyz.x;
|
||||
y = (T)xyz.y;
|
||||
@@ -79,7 +83,8 @@ public:
|
||||
|
||||
// Operations
|
||||
|
||||
template <typename T1> vec4<T> &operator+=(T1 v) {
|
||||
template <typename T1>
|
||||
vec4<T>& operator+=(T1 v) {
|
||||
x += (T)v;
|
||||
y += (T)v;
|
||||
z += (T)v;
|
||||
@@ -87,7 +92,8 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec4<T> &operator+=(const vec4<T1> &v) {
|
||||
template <typename T1>
|
||||
vec4<T>& operator+=(const vec4<T1>& v) {
|
||||
x += (T)v.x;
|
||||
y += (T)v.y;
|
||||
z += (T)v.z;
|
||||
@@ -95,15 +101,18 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec4<T> operator+(T1 v) const {
|
||||
template <typename T1>
|
||||
vec4<T> operator+(T1 v) const {
|
||||
return vec4<T>(x + (T)v, y + (T)v, z + (T)v, w + (T)v);
|
||||
}
|
||||
|
||||
template <typename T1> vec4<T> operator+(const vec4<T1> &v) const {
|
||||
template <typename T1>
|
||||
vec4<T> operator+(const vec4<T1>& v) const {
|
||||
return vec4<T>(x + (T)v.x, y + (T)v.y, z + (T)v.z, w + (T)v.w);
|
||||
}
|
||||
|
||||
template <typename T1> vec4<T> &operator-=(T1 v) {
|
||||
template <typename T1>
|
||||
vec4<T>& operator-=(T1 v) {
|
||||
x -= (T)v;
|
||||
y -= (T)v;
|
||||
z -= (T)v;
|
||||
@@ -111,7 +120,8 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec4<T> &operator-=(const vec4<T1> &v) {
|
||||
template <typename T1>
|
||||
vec4<T>& operator-=(const vec4<T1>& v) {
|
||||
x -= (T)v.x;
|
||||
y -= (T)v.y;
|
||||
z -= (T)v.z;
|
||||
@@ -119,15 +129,18 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec4<T> operator-(T1 v) const {
|
||||
template <typename T1>
|
||||
vec4<T> operator-(T1 v) const {
|
||||
return vec4<T>(x - (T)v, y - (T)v, z - (T)v, w - (T)v);
|
||||
}
|
||||
|
||||
template <typename T1> vec4<T> operator-(const vec4<T1> &v) const {
|
||||
template <typename T1>
|
||||
vec4<T> operator-(const vec4<T1>& v) const {
|
||||
return vec4<T>(x - (T)v.x, y - (T)v.y, z - (T)v.z, w - (T)v.w);
|
||||
}
|
||||
|
||||
template <typename T1> vec4<T> &operator*=(T1 v) {
|
||||
template <typename T1>
|
||||
vec4<T>& operator*=(T1 v) {
|
||||
x *= (T)v;
|
||||
y *= (T)v;
|
||||
z *= (T)v;
|
||||
@@ -135,7 +148,8 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec4<T> &operator*=(const vec4<T1> &v) {
|
||||
template <typename T1>
|
||||
vec4<T>& operator*=(const vec4<T1>& v) {
|
||||
x *= (T)v.x;
|
||||
y *= (T)v.y;
|
||||
z *= (T)v.z;
|
||||
@@ -143,15 +157,18 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec4<T> operator*(T1 v) const {
|
||||
template <typename T1>
|
||||
vec4<T> operator*(T1 v) const {
|
||||
return vec4<T>(x * (T)v, y * (T)v, z * (T)v, w * (T)v);
|
||||
}
|
||||
|
||||
template <typename T1> vec4<T> operator*(const vec4<T1> &v) const {
|
||||
template <typename T1>
|
||||
vec4<T> operator*(const vec4<T1>& v) const {
|
||||
return vec4<T>(x * (T)v.x, y * (T)v.y, z * (T)v.z, w * (T)v.w);
|
||||
}
|
||||
|
||||
template <typename T1> vec4<T> &operator/=(T1 v) {
|
||||
template <typename T1>
|
||||
vec4<T>& operator/=(T1 v) {
|
||||
x /= (T)v;
|
||||
y /= (T)v;
|
||||
z /= (T)v;
|
||||
@@ -159,7 +176,8 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec4<T> &operator/=(const vec4<T1> &v) {
|
||||
template <typename T1>
|
||||
vec4<T>& operator/=(const vec4<T1>& v) {
|
||||
x /= (T)v.x;
|
||||
y /= (T)v.y;
|
||||
z /= (T)v.z;
|
||||
@@ -167,21 +185,25 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T1> vec4<T> operator/(T1 v) const {
|
||||
template <typename T1>
|
||||
vec4<T> operator/(T1 v) const {
|
||||
return vec4<T>(x / (T)v, y / (T)v, z / (T)v, w / (T)v);
|
||||
}
|
||||
|
||||
template <typename T1> vec4<T> operator/(const vec4<T1> &v) const {
|
||||
template <typename T1>
|
||||
vec4<T> operator/(const vec4<T1>& v) const {
|
||||
return vec4<T>(x / (T)v.x, y / (T)v.y, z / (T)v.z, w / (T)v.w);
|
||||
}
|
||||
|
||||
// Generic Operations
|
||||
|
||||
vec4 operator-() const { return vec4(-x, -y, -z, -w); }
|
||||
template <typename T1> bool operator==(const vec4<T1> &v) const {
|
||||
template <typename T1>
|
||||
bool operator==(const vec4<T1>& v) const {
|
||||
return x == (T)v.x && y == (T)v.y && z == (T)v.z && w == (T)v.w;
|
||||
}
|
||||
template <typename T1> bool operator!=(const vec4<T1> &v) const {
|
||||
template <typename T1>
|
||||
bool operator!=(const vec4<T1>& v) const {
|
||||
return !(*this == v);
|
||||
}
|
||||
|
||||
@@ -190,7 +212,8 @@ public:
|
||||
double Len() const { return std::sqrt(SqLen()); }
|
||||
double SqLen() const { return x * x + y * y + z * z + w * w; }
|
||||
|
||||
template <typename T1> double Distance(const vec4<T1> &v) const {
|
||||
template <typename T1>
|
||||
double Distance(const vec4<T1>& v) const {
|
||||
return (*this - v).Len();
|
||||
}
|
||||
|
||||
@@ -202,7 +225,8 @@ public:
|
||||
return *this / (T)l;
|
||||
}
|
||||
|
||||
template <typename T1> T Dot(const vec4<T1> &v) const {
|
||||
template <typename T1>
|
||||
T Dot(const vec4<T1>& v) const {
|
||||
return x * (T)v.x + y * (T)v.y + z * (T)v.z + w * (T)v.w;
|
||||
}
|
||||
|
||||
@@ -241,4 +265,4 @@ public:
|
||||
using fvec4 = vec4<float>;
|
||||
using ivec4 = vec4<int>;
|
||||
using dvec4 = vec4<double>;
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
|
||||
+37
-37
@@ -2,60 +2,60 @@
|
||||
|
||||
#include <amethyst/types.hpp>
|
||||
|
||||
namespace amy {
|
||||
class rect {
|
||||
namespace Amy {
|
||||
class Rect {
|
||||
public:
|
||||
rect() : m_top(0), m_bot(0) {}
|
||||
~rect() = default;
|
||||
rect(const fvec4& t, const fvec4& b) : m_top(t), m_bot(b) {}
|
||||
rect(const fvec2& tl, const fvec2& tr, const fvec2& bl, const fvec2& br)
|
||||
: m_top(tl, tr), m_bot(bl, br) {}
|
||||
rect(const fvec4& duv)
|
||||
: m_top(duv.x, duv.y, duv.z, duv.y), m_bot(duv.x, duv.w, duv.z, duv.w) {}
|
||||
Rect() : pTop(0), pBot(0) {}
|
||||
~Rect() = default;
|
||||
Rect(const fvec4& t, const fvec4& b) : pTop(t), pBot(b) {}
|
||||
Rect(const fvec2& tl, const fvec2& tr, const fvec2& bl, const fvec2& br)
|
||||
: pTop(tl, tr), pBot(bl, br) {}
|
||||
Rect(const fvec4& duv)
|
||||
: pTop(duv.x, duv.y, duv.z, duv.y), pBot(duv.x, duv.w, duv.z, duv.w) {}
|
||||
|
||||
fvec2 topLeft() const { return fvec2(m_top.x, m_top.y); }
|
||||
fvec2 topRight() const { return fvec2(m_top.z, m_top.w); }
|
||||
fvec2 botLeft() const { return fvec2(m_bot.x, m_bot.y); }
|
||||
fvec2 botRight() const { return fvec2(m_bot.z, m_bot.w); }
|
||||
fvec2 TopLeft() const { return fvec2(pTop.x, pTop.y); }
|
||||
fvec2 TopRight() const { return fvec2(pTop.z, pTop.w); }
|
||||
fvec2 BotLeft() const { return fvec2(pBot.x, pBot.y); }
|
||||
fvec2 BotRight() const { return fvec2(pBot.z, pBot.w); }
|
||||
|
||||
fvec4 top() const { return m_top; }
|
||||
fvec4& top() { return m_top; }
|
||||
fvec4 bot() const { return m_bot; }
|
||||
fvec4& bot() { return m_bot; }
|
||||
fvec4 Top() const { return pTop; }
|
||||
fvec4& Top() { return pTop; }
|
||||
fvec4 Bot() const { return pBot; }
|
||||
fvec4& Bot() { return pBot; }
|
||||
|
||||
rect& topLeft(const fvec2& v) {
|
||||
m_top.x = v.x;
|
||||
m_top.y = v.y;
|
||||
Rect& TopLeft(const fvec2& v) {
|
||||
pTop.x = v.x;
|
||||
pTop.y = v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rect& topRight(const fvec2& v) {
|
||||
m_top.z = v.x;
|
||||
m_top.w = v.y;
|
||||
Rect& TopRight(const fvec2& v) {
|
||||
pTop.z = v.x;
|
||||
pTop.w = v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rect& botLeft(const fvec2& v) {
|
||||
m_bot.x = v.x;
|
||||
m_bot.y = v.y;
|
||||
Rect& BotLeft(const fvec2& v) {
|
||||
pBot.x = v.x;
|
||||
pBot.y = v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rect& botRight(const fvec2& v) {
|
||||
m_bot.z = v.x;
|
||||
m_bot.w = v.y;
|
||||
Rect& BotRight(const fvec2& v) {
|
||||
pBot.z = v.x;
|
||||
pBot.w = v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swapVec2XY() {
|
||||
m_top.SwapXY();
|
||||
m_top.SwapZW();
|
||||
m_bot.SwapXY();
|
||||
m_bot.SwapZW();
|
||||
void SwapVec2XY() {
|
||||
pTop.SwapXY();
|
||||
pTop.SwapZW();
|
||||
pBot.SwapXY();
|
||||
pBot.SwapZW();
|
||||
}
|
||||
|
||||
private:
|
||||
fvec4 m_top;
|
||||
fvec4 m_bot;
|
||||
fvec4 pTop;
|
||||
fvec4 pBot;
|
||||
};
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
@@ -1,9 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
namespace amy {
|
||||
namespace Amy {
|
||||
class Renderer {
|
||||
public:
|
||||
Renderer();
|
||||
~Renderer();
|
||||
};
|
||||
} // namespace amys
|
||||
} // namespace Amy
|
||||
@@ -7,33 +7,47 @@
|
||||
#include <amethyst/rect.hpp>
|
||||
#include <amethyst/types.hpp>
|
||||
|
||||
namespace amy {
|
||||
class texture : public asset {
|
||||
namespace Amy {
|
||||
class Texture : public Asset {
|
||||
public:
|
||||
texture() = default;
|
||||
texture(cstr& path);
|
||||
~texture();
|
||||
void load(cstr& path);
|
||||
void load(const std::vector<uc>& pixels, int w, int h, int bpp = 4,
|
||||
image::format fmt = image::RGBA);
|
||||
void unload();
|
||||
Texture() = default;
|
||||
Texture(ksr path);
|
||||
Texture(C3D_Tex* tex, const ivec2& size, const Rect& uv) {
|
||||
Load(tex, size, uv);
|
||||
}
|
||||
~Texture();
|
||||
AMY_SHARED(Texture);
|
||||
|
||||
int w() const { return m_size.x; }
|
||||
int& w() { return m_size.x; }
|
||||
int h() const { return m_size.y; }
|
||||
int& h() { return m_size.y; }
|
||||
ivec2 size() const { return m_size; }
|
||||
ivec2& size() { return m_size; }
|
||||
rect& uv() { return m_uv; }
|
||||
void Load(ksr path);
|
||||
void Load(kvr<uc> pixels, int w, int h, int bpp = 4,
|
||||
Image::Format fmt = Image::RGBA);
|
||||
void Load(C3D_Tex* tex, const ivec2& size, const Rect& uv) {
|
||||
Unload();
|
||||
pTex = tex;
|
||||
pSize = size;
|
||||
pUv = uv;
|
||||
// Dont set as loaded as only the root tex can be loaded
|
||||
}
|
||||
void Unload();
|
||||
void Unloadable(bool v) { pLoaded = v; }
|
||||
bool Unloadable() { return pLoaded; }
|
||||
|
||||
C3D_Tex* ptr() { return m_loaded ? &m_tex : nullptr; }
|
||||
int W() const { return pSize.x; }
|
||||
int& W() { return pSize.x; }
|
||||
int H() const { return pSize.y; }
|
||||
int& H() { return pSize.y; }
|
||||
ivec2 Size() const { return pSize; }
|
||||
ivec2& Size() { return pSize; }
|
||||
Rect& Uv() { return pUv; }
|
||||
|
||||
void bind(int reg = 0);
|
||||
C3D_Tex* Ptr() { return pTex; }
|
||||
|
||||
void Bind(int reg = 0);
|
||||
|
||||
private:
|
||||
C3D_Tex m_tex;
|
||||
ivec2 m_size;
|
||||
rect m_uv;
|
||||
bool m_loaded = false;
|
||||
C3D_Tex* pTex = nullptr;
|
||||
ivec2 pSize;
|
||||
Rect pUv = fvec4(0, 1, 1, 0);
|
||||
bool pLoaded = false;
|
||||
};
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <amethyst/maths/vec.hpp>
|
||||
#include <chrono>
|
||||
#include <cinttypes>
|
||||
#include <format>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@@ -12,18 +14,44 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace amy {
|
||||
#define AMY_SHARED(x) \
|
||||
using Ref = std::shared_ptr<x>; \
|
||||
template <typename... Args> \
|
||||
static Ref New(Args&&... args) { \
|
||||
return std::make_shared<x>(std::forward<Args>(args)...); \
|
||||
}
|
||||
|
||||
#define AMY_UNIQUE(x) \
|
||||
using Ref = std::unique_ptr<x>; \
|
||||
template <typename... Args> \
|
||||
static Ref New(Args&&... args) { \
|
||||
return std::make_unique<x>(std::forward<Args>(args)...); \
|
||||
}
|
||||
|
||||
namespace Amy {
|
||||
using uc = unsigned char;
|
||||
using us = unsigned short;
|
||||
using ui = unsigned int;
|
||||
using ull = unsigned long long;
|
||||
// string
|
||||
using str = std::string;
|
||||
using cstr = const std::string;
|
||||
// const string
|
||||
using kstr = const std::string;
|
||||
// const string reference
|
||||
using ksr = const std::string&;
|
||||
// vector
|
||||
template <typename T>
|
||||
using vec = std::vector<T>;
|
||||
// const vector reference
|
||||
template <typename T>
|
||||
using cvec = const std::vector<T>;
|
||||
using kvr = const std::vector<T>&;
|
||||
// const vector
|
||||
template <typename T>
|
||||
using kvec = const std::vector<T>;
|
||||
// unique pointer
|
||||
template <typename T>
|
||||
using up = std::unique_ptr<T>;
|
||||
} // namespace amy
|
||||
// shared pointer
|
||||
template <typename T>
|
||||
using sp = std::shared_ptr<T>;
|
||||
} // namespace Amy
|
||||
+61
-14
@@ -2,17 +2,64 @@
|
||||
|
||||
#include <amethyst/types.hpp>
|
||||
|
||||
namespace amy {
|
||||
namespace utils {
|
||||
ui fastHash(cstr& s);
|
||||
vec<uc> loadFile2Mem(cstr& path);
|
||||
ui hashMemory(cvec<uc>& data);
|
||||
ui nextPow2(ui v);
|
||||
bool isSingleBitNum(ui v);
|
||||
namespace image {
|
||||
void reverseBuf(vec<uc>& buf, int w, int h, int c);
|
||||
void removeAlphaChannel(vec<uc>& buf, int w, int h);
|
||||
void addAlphaChannel(vec<uc>& buf, int w, int h);
|
||||
} // namespace image
|
||||
} // namespace utils
|
||||
} // namespace amy
|
||||
namespace Amy {
|
||||
class Error : public std::runtime_error {
|
||||
public:
|
||||
Error(ksr str) : std::runtime_error("[amy] " + str) {}
|
||||
};
|
||||
namespace Utils {
|
||||
constexpr int HexChar2Int(char c) {
|
||||
/** Imagine man hat ne lookup table dafür verwendet :/ */
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
if (c >= 'a' && c <= 'f') return 10 + (c - 'a');
|
||||
if (c >= 'A' && c <= 'F') return 10 + (c - 'A');
|
||||
return -1; // Error
|
||||
}
|
||||
vec<uc> LoadFile2Mem(ksr path);
|
||||
str FormatBytes(ull bytes);
|
||||
ui HashMemory(kvr<uc> data);
|
||||
ui NextPow2(ui v);
|
||||
bool IsSingleBitNum(ui v);
|
||||
ull GetTimeNano();
|
||||
ull GetTimeMicro();
|
||||
ull GetTimeMilli();
|
||||
void String2U16(us* res, ksr src, size_t max);
|
||||
std::string U16toU8(us* in, size_t max);
|
||||
/**
|
||||
* Generate a Formatted String by an Nanoseconds Input
|
||||
* @param nanos Nanoseconds Input
|
||||
* @return Result String
|
||||
*/
|
||||
kstr FormatNanos(ull nanos);
|
||||
/**
|
||||
* Generate a Formatted String by an Milliseconds Input
|
||||
* @param millis Milliseconds Input
|
||||
* @return Result String
|
||||
*/
|
||||
kstr FormatMillis(ull millis);
|
||||
/**
|
||||
* Create a formatted String by an input bytes value
|
||||
* @param bytes value in bytes
|
||||
* @result Formatted String for example `2.5MB`
|
||||
*/
|
||||
/**
|
||||
* FNV Hash functiom (32 Bit)
|
||||
* https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
|
||||
* Able to run at compile time btw
|
||||
*/
|
||||
constexpr ui FNV32(std::string_view str) {
|
||||
ui ret = 0x811C9DC5;
|
||||
for (char it : str) {
|
||||
ret ^= static_cast<ui>(it);
|
||||
ret *= 16777619;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
namespace Image {
|
||||
void ReverseBuf(vec<uc>& buf, int w, int h, int c);
|
||||
void RemoveAlphaChannel(vec<uc>& buf, int w, int h);
|
||||
void AddAlphaChannel(vec<uc>& buf, int w, int h);
|
||||
} // namespace Image
|
||||
} // namespace Utils
|
||||
} // namespace Amy
|
||||
+123
-3
@@ -1,6 +1,10 @@
|
||||
#include <amethyst.hpp>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#define TRACK_NEW_DELETE
|
||||
|
||||
#ifdef AMY_3DS
|
||||
#include <3ds.h>
|
||||
@@ -26,10 +30,126 @@ void NpiD7CxxExceptionHandler() {
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace amy {
|
||||
void registerCxxExceptionHandler() {
|
||||
static Amy::Memory::MemMetrics metrics;
|
||||
|
||||
#ifdef TRACK_NEW_DELETE
|
||||
|
||||
constexpr uint32_t MemDBGMagic = 0x774733d7;
|
||||
|
||||
struct MemDBGHeader {
|
||||
MemDBGHeader(size_t s) {
|
||||
Magic = MemDBGMagic;
|
||||
Size = s;
|
||||
}
|
||||
uint32_t Magic = MemDBGMagic;
|
||||
size_t Size = 0;
|
||||
};
|
||||
|
||||
void *MemDBGAllocate(size_t size) {
|
||||
void *ptr = malloc(size + sizeof(MemDBGHeader));
|
||||
if (!ptr) return reinterpret_cast<void *>(ptr);
|
||||
MemDBGHeader *hdr = reinterpret_cast<MemDBGHeader *>(ptr);
|
||||
hdr->Magic = MemDBGMagic;
|
||||
hdr->Size = size;
|
||||
metrics.Allocated.fetch_add(hdr->Size, std::memory_order_relaxed);
|
||||
metrics.Current.fetch_add(hdr->Size, std::memory_order_relaxed);
|
||||
metrics.Allocations.fetch_add(1, std::memory_order_relaxed);
|
||||
return reinterpret_cast<void *>(hdr + 1);
|
||||
}
|
||||
|
||||
void MemDBGFree(void *ptr) {
|
||||
if (!ptr) return;
|
||||
MemDBGHeader *hdr = reinterpret_cast<MemDBGHeader *>(ptr) - 1;
|
||||
if (hdr->Magic == MemDBGMagic) {
|
||||
hdr->Magic = 0;
|
||||
size_t szs = hdr->Size;
|
||||
metrics.Deleted.fetch_add(szs, std::memory_order_relaxed);
|
||||
metrics.Current.fetch_sub(szs, std::memory_order_relaxed);
|
||||
metrics.Allocations.fetch_sub(1, std::memory_order_relaxed);
|
||||
free(reinterpret_cast<void *>(hdr));
|
||||
} else {
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
void *operator new(size_t size) { return MemDBGAllocate(size); }
|
||||
void *operator new[](size_t size) { return MemDBGAllocate(size); }
|
||||
void operator delete(void *ptr) noexcept { MemDBGFree(ptr); }
|
||||
void operator delete(void *ptr, size_t) noexcept { MemDBGFree(ptr); }
|
||||
void operator delete[](void *ptr) noexcept { MemDBGFree(ptr); }
|
||||
void operator delete[](void *ptr, size_t) noexcept { MemDBGFree(ptr); }
|
||||
void *operator new(size_t size, const std::nothrow_t &) noexcept {
|
||||
return MemDBGAllocate(size);
|
||||
}
|
||||
void *operator new[](size_t size, const std::nothrow_t &) noexcept {
|
||||
return MemDBGAllocate(size);
|
||||
}
|
||||
void operator delete(void *ptr, const std::nothrow_t &) noexcept {
|
||||
MemDBGFree(ptr);
|
||||
}
|
||||
void operator delete[](void *ptr, const std::nothrow_t &) noexcept {
|
||||
MemDBGFree(ptr);
|
||||
}
|
||||
void *operator new(size_t size, std::align_val_t) {
|
||||
return MemDBGAllocate(size);
|
||||
}
|
||||
void *operator new[](size_t size, std::align_val_t) {
|
||||
return MemDBGAllocate(size);
|
||||
}
|
||||
|
||||
void operator delete(void *ptr, std::align_val_t) noexcept { MemDBGFree(ptr); }
|
||||
void operator delete[](void *ptr, std::align_val_t) noexcept {
|
||||
MemDBGFree(ptr);
|
||||
}
|
||||
void *operator new(size_t size, std::align_val_t,
|
||||
const std::nothrow_t &) noexcept {
|
||||
return MemDBGAllocate(size);
|
||||
}
|
||||
void *operator new[](size_t size, std::align_val_t,
|
||||
const std::nothrow_t &) noexcept {
|
||||
return MemDBGAllocate(size);
|
||||
}
|
||||
void operator delete(void *ptr, size_t, std::align_val_t) noexcept {
|
||||
MemDBGFree(ptr);
|
||||
}
|
||||
|
||||
void operator delete[](void *ptr, size_t, std::align_val_t) noexcept {
|
||||
MemDBGFree(ptr);
|
||||
}
|
||||
void operator delete(void *ptr, size_t, std::align_val_t,
|
||||
const std::nothrow_t &) noexcept {
|
||||
MemDBGFree(ptr);
|
||||
}
|
||||
|
||||
void operator delete[](void *ptr, size_t, std::align_val_t,
|
||||
const std::nothrow_t &) noexcept {
|
||||
MemDBGFree(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace Amy {
|
||||
|
||||
void RegisterCxxExceptionHandler() {
|
||||
#ifdef AMY_3DS
|
||||
std::set_terminate(NpiD7CxxExceptionHandler);
|
||||
#endif
|
||||
}
|
||||
} // namespace amy
|
||||
void *Malloc(size_t size) {
|
||||
#ifdef TRACK_NEW_DELETE
|
||||
return MemDBGAllocate(size);
|
||||
#else
|
||||
return malloc(size);
|
||||
#endif
|
||||
}
|
||||
void Free(void *ptr) {
|
||||
#ifdef TRACK_NEW_DELETE
|
||||
MemDBGFree(ptr);
|
||||
#else
|
||||
free(ptr);
|
||||
#endif
|
||||
}
|
||||
ull Memory::GetTotalAllocated() { return metrics.Allocated; }
|
||||
ull Memory::GetTotalFreed() { return metrics.Deleted; }
|
||||
ull Memory::GetCurrent() { return metrics.CurrentlyAllocated(); }
|
||||
ull Memory::GetAllocationCount() { return metrics.Allocations; }
|
||||
} // namespace Amy
|
||||
|
||||
+13
-9
@@ -1,15 +1,19 @@
|
||||
#include <3ds.h>
|
||||
|
||||
#include <amethyst/app.hpp>
|
||||
#include <amethyst/ctru.hpp>
|
||||
#include <amethyst/utils.hpp>
|
||||
|
||||
namespace amy {
|
||||
void app::run() {
|
||||
while (aptMainLoop()) {
|
||||
ull c = ctru::getTime();
|
||||
m_delta = static_cast<double>(c) - static_cast<float>(m_last);
|
||||
m_last = c;
|
||||
main();
|
||||
namespace Amy {
|
||||
void App::Run() {
|
||||
pLast = Utils::GetTimeNano();
|
||||
while (aptMainLoop() && !pExit) {
|
||||
ull c = Utils::GetTimeNano();
|
||||
pDelta = static_cast<double>(static_cast<double>(c) -
|
||||
static_cast<double>(pLast)) *
|
||||
0.000001;
|
||||
pTime += pDelta * 0.001;
|
||||
pLast = c;
|
||||
Main();
|
||||
}
|
||||
}
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
@@ -0,0 +1,26 @@
|
||||
#include <amethyst/assets.hpp>
|
||||
#include <amethyst/c3d.hpp>
|
||||
#include <amethyst/iron.hpp>
|
||||
#include <amethyst/texture.hpp>
|
||||
|
||||
namespace Amy {
|
||||
void AssetMgr::AutoLoad(const ID& id, ksr path) {
|
||||
if (path.ends_with(".png") || path.ends_with(".jpg") ||
|
||||
path.ends_with(".bmp")) {
|
||||
auto tex = Texture::New();
|
||||
tex->Load(path);
|
||||
Add(id, tex);
|
||||
} else if (path.ends_with(".shbin")) {
|
||||
auto shader = C3D::Shader::New();
|
||||
shader->Load(path);
|
||||
Add(id, shader);
|
||||
} else if (path.ends_with(".ttf")) {
|
||||
auto font = Iron::Font::New();
|
||||
font->LoadTTF(path);
|
||||
Add(id, font);
|
||||
} else {
|
||||
throw std::runtime_error("[amy]: assets: " + id.GetName() + " (" + path +
|
||||
") is unsupported for AssetMgr::AutoLoad!");
|
||||
}
|
||||
}
|
||||
} // namespace Amy
|
||||
+65
-58
@@ -4,131 +4,138 @@
|
||||
#include <amethyst/utils.hpp>
|
||||
#include <pica.hpp>
|
||||
|
||||
namespace amy {
|
||||
namespace Amy {
|
||||
|
||||
const auto DISPLAY_TRANSFER_FLAGS =
|
||||
GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) |
|
||||
GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) |
|
||||
GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) |
|
||||
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO);
|
||||
C3D_TexEnv* c3d::frag::m_env = nullptr;
|
||||
int c3d::m_drawcalls = 0;
|
||||
int c3d::m__dc__ = 0;
|
||||
C3D_TexEnv* C3D::Frag::pEnv = nullptr;
|
||||
int C3D::pDrawcalls = 0;
|
||||
int C3D::p__dc__ = 0;
|
||||
|
||||
void c3d::init() { C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); }
|
||||
void C3D::Init() { C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); }
|
||||
|
||||
void c3d::deinit() { C3D_Fini(); }
|
||||
void C3D::Deinit() { C3D_Fini(); }
|
||||
|
||||
void c3d::startFrame(bool sync) {
|
||||
void C3D::StartFrame(bool sync) {
|
||||
C3D_FrameBegin(sync ? C3D_FRAME_SYNCDRAW : C3D_FRAME_NONBLOCK);
|
||||
m__dc__ = 0;
|
||||
p__dc__ = 0;
|
||||
}
|
||||
|
||||
void c3d::endFrame() {
|
||||
void C3D::EndFrame() {
|
||||
C3D_FrameEnd(0);
|
||||
m_drawcalls = m__dc__;
|
||||
pDrawcalls = p__dc__;
|
||||
}
|
||||
|
||||
c3d::screen* c3d::createScreen(gfxScreen_t screen, gfx3dSide_t side) {
|
||||
C3D::Screen* C3D::CreateScreen(gfxScreen_t screen, gfx3dSide_t side) {
|
||||
auto t = C3D_RenderTargetCreate(240, screen == GFX_TOP ? 400 : 320,
|
||||
GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
|
||||
C3D_RenderTargetSetOutput(t, screen, side, DISPLAY_TRANSFER_FLAGS);
|
||||
return new c3d::screen(t);
|
||||
return new C3D::Screen(t);
|
||||
}
|
||||
|
||||
void c3d::deleteScreen(c3d::screen* screen) { delete screen; }
|
||||
void C3D::DeleteScreen(C3D::Screen* screen) { delete screen; }
|
||||
|
||||
c3d::shader::shader(const std::string& path) { load(path); }
|
||||
C3D::Shader::Shader(const std::string& path) { Load(path); }
|
||||
|
||||
c3d::shader::~shader() {}
|
||||
C3D::Shader::~Shader() {
|
||||
if (pCode) {
|
||||
shaderProgramFree(&pProgram);
|
||||
DVLB_Free(pCode);
|
||||
pCode = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void c3d::shader::load(const std::string& path) {
|
||||
auto code = utils::loadFile2Mem(path);
|
||||
void C3D::Shader::Load(const std::string& path) {
|
||||
auto code = Utils::LoadFile2Mem(path);
|
||||
if (!code.size()) {
|
||||
throw std::runtime_error(
|
||||
std::format("[amy] unsable to load shader ({})", path));
|
||||
std::format("[amy] unable to load shader ({})", path));
|
||||
}
|
||||
load(code);
|
||||
Load(code);
|
||||
}
|
||||
|
||||
void c3d::shader::load(const std::vector<uc>& data) {
|
||||
m_code = DVLB_ParseFile((u32*)&data[0], data.size());
|
||||
shaderProgramInit(&m_program);
|
||||
shaderProgramSetVsh(&m_program, &m_code->DVLE[0]);
|
||||
C3D_BindProgram(&m_program);
|
||||
AttrInfo_Init(&m_info);
|
||||
void C3D::Shader::Load(const std::vector<uc>& data) {
|
||||
if (!data.size()) {
|
||||
throw std::runtime_error("[amy] unable to load shader from data!");
|
||||
}
|
||||
pRawData = data;
|
||||
pCode = DVLB_ParseFile((u32*)&pRawData[0], pRawData.size());
|
||||
shaderProgramInit(&pProgram);
|
||||
shaderProgramSetVsh(&pProgram, &pCode->DVLE[0]);
|
||||
AttrInfo_Init(&pInfo);
|
||||
}
|
||||
|
||||
void c3d::shader::compile(const std::string& code) {
|
||||
auto ret = Pica::AssembleCode(code.c_str());
|
||||
load(ret);
|
||||
void C3D::Shader::Compile(const std::string& code) {
|
||||
Load(Pica::AssembleCode(code.c_str()));
|
||||
}
|
||||
|
||||
void c3d::shader::use() {
|
||||
C3D_BindProgram(&m_program);
|
||||
// for some reason i need both ???
|
||||
void C3D::Shader::Use() {
|
||||
// code works perfectly without C3D_BindProgram
|
||||
// but nor withour shaderProgramUse ...
|
||||
shaderProgramUse(&m_program);
|
||||
C3D_SetAttrInfo(&m_info);
|
||||
// but nor without shaderProgramUse ...
|
||||
shaderProgramUse(&pProgram);
|
||||
C3D_BindProgram(&pProgram);
|
||||
C3D_SetAttrInfo(&pInfo);
|
||||
}
|
||||
|
||||
void c3d::shader::setMat4(int loc, C3D_Mtx* m) {
|
||||
void C3D::Shader::SetMat4(int loc, C3D_Mtx* m) {
|
||||
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, loc, m);
|
||||
}
|
||||
|
||||
void c3d::shader::setMat4(int loc, const mat4& m) {
|
||||
void C3D::Shader::SetMat4(int loc, const mat4& m) {
|
||||
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, loc, (const C3D_Mtx*)&m);
|
||||
}
|
||||
|
||||
int c3d::shader::loc(const std::string& name) {
|
||||
return shaderInstanceGetUniformLocation(m_program.vertexShader, name.c_str());
|
||||
int C3D::Shader::loc(const std::string& name) {
|
||||
return shaderInstanceGetUniformLocation(pProgram.vertexShader, name.c_str());
|
||||
}
|
||||
|
||||
void c3d::shader::input(int reg, GPU_FORMATS f, int num) {
|
||||
AttrInfo_AddLoader(&m_info, reg, f, num);
|
||||
void C3D::Shader::Input(int reg, GPU_FORMATS f, int num) {
|
||||
AttrInfo_AddLoader(&pInfo, reg, f, num);
|
||||
}
|
||||
|
||||
void c3d::frag::src(C3D_TexEnvMode mode, GPU_TEVSRC s1, GPU_TEVSRC s2,
|
||||
void C3D::Frag::Src(C3D_TexEnvMode mode, GPU_TEVSRC s1, GPU_TEVSRC s2,
|
||||
GPU_TEVSRC s3) {
|
||||
C3D_TexEnvSrc(m_env, mode, s1, s2, s3);
|
||||
C3D_TexEnvSrc(pEnv, mode, s1, s2, s3);
|
||||
}
|
||||
void c3d::frag::func(C3D_TexEnvMode mode, GPU_COMBINEFUNC func) {
|
||||
C3D_TexEnvFunc(m_env, mode, func);
|
||||
void C3D::Frag::Func(C3D_TexEnvMode mode, GPU_COMBINEFUNC func) {
|
||||
C3D_TexEnvFunc(pEnv, mode, func);
|
||||
}
|
||||
void c3d::frag::edit(int id) {
|
||||
m_env = C3D_GetTexEnv(id);
|
||||
C3D_TexEnvInit(m_env);
|
||||
void C3D::Frag::Edit(int id) {
|
||||
pEnv = C3D_GetTexEnv(id);
|
||||
C3D_TexEnvInit(pEnv);
|
||||
}
|
||||
|
||||
void c3d::drawArrays(int start, int count, GPU_Primitive_t prim) {
|
||||
void C3D::DrawArrays(int start, int count, GPU_Primitive_t prim) {
|
||||
C3D_DrawArrays(prim, start, count);
|
||||
m__dc__++;
|
||||
p__dc__++;
|
||||
}
|
||||
|
||||
void c3d::drawElements(int count, const void* idx_ptr, int type,
|
||||
void C3D::DrawElements(int count, const void* idx_ptr, int type,
|
||||
GPU_Primitive_t prim) {
|
||||
C3D_DrawElements(prim, count, type, idx_ptr);
|
||||
m__dc__++;
|
||||
p__dc__++;
|
||||
}
|
||||
|
||||
void c3d::depthTest(bool on, GPU_TESTFUNC func, GPU_WRITEMASK mask) {
|
||||
void C3D::DepthTest(bool on, GPU_TESTFUNC func, GPU_WRITEMASK mask) {
|
||||
C3D_DepthTest(on, func, mask);
|
||||
}
|
||||
|
||||
void c3d::disableScissor() { C3D_SetScissor(GPU_SCISSOR_DISABLE, 0, 0, 0, 0); }
|
||||
void C3D::DisableScissor() { C3D_SetScissor(GPU_SCISSOR_DISABLE, 0, 0, 0, 0); }
|
||||
|
||||
void c3d::enableScissor(const ivec4 rect) {
|
||||
void C3D::EnableScissor(const ivec4 rect) {
|
||||
C3D_SetScissor(GPU_SCISSOR_NORMAL, rect.x, rect.y, rect.z, rect.w);
|
||||
}
|
||||
|
||||
void c3d::bufCfg(void* ptr, int stride, int shader_attribs, u64 permutation) {
|
||||
void C3D::BufCfg(void* ptr, int stride, int shader_attribs, u64 permutation) {
|
||||
auto buf = C3D_GetBufInfo();
|
||||
BufInfo_Init(buf);
|
||||
BufInfo_Add(buf, ptr, stride, shader_attribs, permutation);
|
||||
}
|
||||
|
||||
void c3d::bufCfg(void* ptr, int stride, int shader_attribs) {
|
||||
bufCfg(ptr, stride, shader_attribs, permutation(shader_attribs));
|
||||
void C3D::BufCfg(void* ptr, int stride, int shader_attribs) {
|
||||
BufCfg(ptr, stride, shader_attribs, pPermutation(shader_attribs));
|
||||
}
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <amethyst/color.hpp>
|
||||
|
||||
namespace Amy {
|
||||
std::string Color::Hex(bool rgba) const {
|
||||
/** Need to int cast (so it is used as num and not char...) */
|
||||
std::stringstream s;
|
||||
s << "#";
|
||||
s << std::hex << std::setw(2) << std::setfill('0') << (int)r;
|
||||
s << std::hex << std::setw(2) << std::setfill('0') << (int)g;
|
||||
s << std::hex << std::setw(2) << std::setfill('0') << (int)b;
|
||||
if (rgba) {
|
||||
s << std::hex << std::setw(2) << std::setfill('0') << (int)a;
|
||||
}
|
||||
return s.str();
|
||||
}
|
||||
} // namespace Amy
|
||||
@@ -1,17 +0,0 @@
|
||||
#include <3ds.h>
|
||||
|
||||
#include <amethyst/ctru.hpp>
|
||||
|
||||
namespace amy {
|
||||
namespace ctru {
|
||||
void init(unsigned int srvs) {
|
||||
if (srvs & romfs) {
|
||||
romfsInit();
|
||||
}
|
||||
if (srvs & gfx_def) {
|
||||
gfxInitDefault();
|
||||
}
|
||||
}
|
||||
ull getTime() { return osGetTime(); }
|
||||
} // namespace ctru
|
||||
} // namespace amy
|
||||
@@ -0,0 +1,14 @@
|
||||
#include <amethyst/godtrace.hpp>
|
||||
#include <amethyst/utils.hpp>
|
||||
|
||||
Amy::GTrace::TraceMap Amy::GTrace::pTraces;
|
||||
|
||||
void Amy::GTrace::Beg(ksr id) {
|
||||
auto trace = GetTraceRef(id);
|
||||
trace->SetStart(Amy::Utils::GetTimeNano());
|
||||
}
|
||||
|
||||
void Amy::GTrace::End(ksr id) {
|
||||
auto trace = GetTraceRef(id);
|
||||
trace->SetEnd(Amy::Utils::GetTimeNano());
|
||||
}
|
||||
+84
-67
@@ -2,67 +2,70 @@
|
||||
#include <amethyst/utils.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
// #define STB_IMAGE_IMPLEMENTATION
|
||||
// Only include stb Code if we need it
|
||||
// Otherwise we just build the header
|
||||
#ifdef AMY_STB_IMAGE
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#endif
|
||||
#include <stb_image.h>
|
||||
|
||||
namespace amy {
|
||||
void image::load(cstr& path) {
|
||||
namespace Amy {
|
||||
void Image::Load(ksr path) {
|
||||
int c = 0;
|
||||
uc* buf = stbi_load(path.c_str(), &m_w, &m_h, &c, 4);
|
||||
uc* buf = stbi_load(path.c_str(), &pW, &pH, &c, 4);
|
||||
if (c == 3) {
|
||||
// Releoading the Image with tree channels requestet
|
||||
// Still need to find a better way for this :(
|
||||
stbi_image_free(buf);
|
||||
buf = stbi_load(path.c_str(), &m_w, &m_h, &c, 3);
|
||||
m_buffer.assign(buf, buf + (m_w * m_h * 3));
|
||||
m_fmt = RGB;
|
||||
buf = stbi_load(path.c_str(), &pW, &pH, &c, 3);
|
||||
pBuffer.assign(buf, buf + (pW * pH * 3));
|
||||
pFmt = RGB;
|
||||
stbi_image_free(buf);
|
||||
} else if (c == 4) {
|
||||
m_buffer.assign(buf, buf + (m_w * m_h * 4));
|
||||
m_fmt = RGBA;
|
||||
pBuffer.assign(buf, buf + (pW * pH * 4));
|
||||
pFmt = RGBA;
|
||||
stbi_image_free(buf);
|
||||
} else {
|
||||
throw std::runtime_error(path + " is using an unsupported image format!");
|
||||
}
|
||||
}
|
||||
|
||||
void image::load(const std::vector<uc>& data) {
|
||||
void Image::Load(const std::vector<uc>& data) {
|
||||
int c = 0;
|
||||
uc* buf = stbi_load_from_memory(data.data(), data.size(), &m_w, &m_h, &c, 4);
|
||||
uc* buf = stbi_load_from_memory(data.data(), data.size(), &pW, &pH, &c, 4);
|
||||
if (c == 3) {
|
||||
// Releoading the Image with tree channels requestet
|
||||
// Still need to find a better way for this :(
|
||||
stbi_image_free(buf);
|
||||
buf = stbi_load_from_memory(data.data(), data.size(), &m_w, &m_h, &c, 3);
|
||||
m_buffer.assign(buf, buf + (m_w * m_h * 3));
|
||||
m_fmt = RGB;
|
||||
buf = stbi_load_from_memory(data.data(), data.size(), &pW, &pH, &c, 3);
|
||||
pBuffer.assign(buf, buf + (pW * pH * 3));
|
||||
pFmt = RGB;
|
||||
stbi_image_free(buf);
|
||||
} else if (m_fmt == 4) {
|
||||
m_buffer.assign(buf, buf + (m_w * m_h * 4));
|
||||
m_fmt = RGBA;
|
||||
} else if (pFmt == 4) {
|
||||
pBuffer.assign(buf, buf + (pW * pH * 4));
|
||||
pFmt = RGBA;
|
||||
stbi_image_free(buf);
|
||||
} else {
|
||||
throw std::runtime_error("image mem using an unsupported image format!");
|
||||
}
|
||||
}
|
||||
|
||||
void image::copy(const std::vector<uc>& pixels, int w, int h,
|
||||
const format& fmt) {
|
||||
int f = getBppOfFmt(fmt);
|
||||
void Image::Copy(kvr<uc> pixels, int w, int h, const Format& fmt) {
|
||||
int f = GetBppOfFmt(fmt);
|
||||
if (pixels.size() != static_cast<size_t>(w * h * f)) {
|
||||
throw std::runtime_error("Connot copy image due to size error!");
|
||||
}
|
||||
m_fmt = fmt;
|
||||
m_w = w;
|
||||
m_h = h;
|
||||
m_buffer.clear();
|
||||
m_buffer.resize(w * h * f);
|
||||
for (size_t i = 0; i < m_buffer.size(); i++) {
|
||||
m_buffer[i] = pixels[i];
|
||||
pFmt = fmt;
|
||||
pW = w;
|
||||
pH = h;
|
||||
pBuffer.clear();
|
||||
pBuffer.resize(w * h * f);
|
||||
for (size_t i = 0; i < pBuffer.size(); i++) {
|
||||
pBuffer[i] = pixels[i];
|
||||
}
|
||||
}
|
||||
|
||||
int image::getBppOfFmt(const image::format& fmt) {
|
||||
int Image::GetBppOfFmt(const Image::Format& fmt) {
|
||||
switch (fmt) {
|
||||
case RGBA:
|
||||
case ABGR:
|
||||
@@ -76,6 +79,9 @@ int image::getBppOfFmt(const image::format& fmt) {
|
||||
case RGB565:
|
||||
return 2;
|
||||
break;
|
||||
case A8:
|
||||
return 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0; // Unknown
|
||||
@@ -83,28 +89,39 @@ int image::getBppOfFmt(const image::format& fmt) {
|
||||
}
|
||||
}
|
||||
|
||||
void image::convert(image& img, const format& dst) {
|
||||
if (img.m_fmt == dst) {
|
||||
void Image::Convert(Image& img, const Format& dst) {
|
||||
if (img.pFmt == dst) {
|
||||
return;
|
||||
} else if (img.m_fmt == RGB && dst == BGR) {
|
||||
utils::image::reverseBuf(img.m_buffer, img.m_w, img.m_h, 3);
|
||||
img.m_fmt = BGR;
|
||||
} else if (img.m_fmt == RGB && dst == RGBA) {
|
||||
utils::image::addAlphaChannel(img.m_buffer, img.m_w, img.m_h);
|
||||
img.m_fmt = RGBA;
|
||||
} else if (img.m_fmt == RGBA && dst == RGB) {
|
||||
utils::image::removeAlphaChannel(img.m_buffer, img.m_w, img.m_h);
|
||||
img.m_fmt = RGB;
|
||||
} else if (img.m_fmt == RGBA && dst == ABGR) {
|
||||
utils::image::reverseBuf(img.m_buffer, img.m_w, img.m_h, 4);
|
||||
img.m_fmt = ABGR;
|
||||
} else if (img.m_fmt == RGB && dst == ABGR) {
|
||||
convert(img, RGBA);
|
||||
convert(img, ABGR);
|
||||
} else if (img.m_fmt == RGBA && dst == RGB565) {
|
||||
convert(img, RGB);
|
||||
convert(img, RGB565);
|
||||
} else if (img.m_fmt == RGB && dst == RGB565) {
|
||||
} else if (img.pFmt == RGBA && dst == A8) {
|
||||
std::vector<uc> cpy = img.pBuffer;
|
||||
img.pBuffer.resize(img.pW * img.pH);
|
||||
for (int y = 0; y < img.pH; y++) {
|
||||
for (int x = 0; x < img.pW; x++) {
|
||||
int src = (y * img.pW + x) * 4;
|
||||
int dst = (y * img.pW + x);
|
||||
img.pBuffer[dst] = cpy[src + 3];
|
||||
}
|
||||
}
|
||||
img.pFmt = A8;
|
||||
} else if (img.pFmt == RGB && dst == BGR) {
|
||||
Utils::Image::ReverseBuf(img.pBuffer, img.pW, img.pH, 3);
|
||||
img.pFmt = BGR;
|
||||
} else if (img.pFmt == RGB && dst == RGBA) {
|
||||
Utils::Image::AddAlphaChannel(img.pBuffer, img.pW, img.pH);
|
||||
img.pFmt = RGBA;
|
||||
} else if (img.pFmt == RGBA && dst == RGB) {
|
||||
Utils::Image::RemoveAlphaChannel(img.pBuffer, img.pW, img.pH);
|
||||
img.pFmt = RGB;
|
||||
} else if (img.pFmt == RGBA && dst == ABGR) {
|
||||
Utils::Image::ReverseBuf(img.pBuffer, img.pW, img.pH, 4);
|
||||
img.pFmt = ABGR;
|
||||
} else if (img.pFmt == RGB && dst == ABGR) {
|
||||
Convert(img, RGBA);
|
||||
Convert(img, ABGR);
|
||||
} else if (img.pFmt == RGBA && dst == RGB565) {
|
||||
Convert(img, RGB);
|
||||
Convert(img, RGB565);
|
||||
} else if (img.pFmt == RGB && dst == RGB565) {
|
||||
// Inlined make pixel 565 func
|
||||
auto f = [](uc r, uc g, uc b) -> unsigned short {
|
||||
unsigned short _r = (r >> 3);
|
||||
@@ -112,35 +129,35 @@ void image::convert(image& img, const format& dst) {
|
||||
unsigned short _b = (b >> 3);
|
||||
return (_r << 11) | (_g << 5) | _b;
|
||||
};
|
||||
std::vector<uc> cpy = img.m_buffer;
|
||||
img.m_buffer.resize(img.m_w * img.m_h * 2);
|
||||
for (int y = 0; y < img.m_w; y++) {
|
||||
for (int x = 0; x < img.m_h; x++) {
|
||||
int src = (y * img.m_w + x) * 3;
|
||||
int dst = (y * img.m_w + x) * 2;
|
||||
std::vector<uc> cpy = img.pBuffer;
|
||||
img.pBuffer.resize(img.pW * img.pH * 2);
|
||||
for (int y = 0; y < img.pW; y++) {
|
||||
for (int x = 0; x < img.pH; x++) {
|
||||
int src = (y * img.pW + x) * 3;
|
||||
int dst = (y * img.pW + x) * 2;
|
||||
unsigned short new_px = f(cpy[src + 0], cpy[src + 1], cpy[src + 2]);
|
||||
img.m_buffer[dst + 0] = new_px >> 8;
|
||||
img.m_buffer[dst + 1] = new_px & 0xff;
|
||||
img.pBuffer[dst + 0] = new_px >> 8;
|
||||
img.pBuffer[dst + 1] = new_px & 0xff;
|
||||
}
|
||||
}
|
||||
img.m_fmt = RGB565;
|
||||
img.pFmt = RGB565;
|
||||
}
|
||||
}
|
||||
|
||||
void image::retile(image& img, std::function<ui(int x, int y, int w)> src,
|
||||
void Image::Retile(Image& img, std::function<ui(int x, int y, int w)> src,
|
||||
std::function<ui(int x, int y, int w)> dst) {
|
||||
std::vector<uc> cpy = img.m_buffer;
|
||||
std::vector<uc> cpy = img.pBuffer;
|
||||
/** could use fmt here but for 565 that woulnt work as it is not supported by
|
||||
* file loading where fmt is used */
|
||||
int bpp = img.bpp();
|
||||
for (int y = 0; y < img.m_h; y++) {
|
||||
for (int x = 0; x < img.m_w; x++) {
|
||||
int src_idx = src(x, y, img.m_w);
|
||||
int dst_idx = dst(x, y, img.m_w);
|
||||
int bpp = img.Bpp();
|
||||
for (int y = 0; y < img.pH; y++) {
|
||||
for (int x = 0; x < img.pW; x++) {
|
||||
int src_idx = src(x, y, img.pW);
|
||||
int dst_idx = dst(x, y, img.pW);
|
||||
for (int i = 0; i < bpp; i++) {
|
||||
img.m_buffer[dst_idx + i] = cpy[src_idx + i];
|
||||
img.pBuffer[dst_idx + i] = cpy[src_idx + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
Executable → Regular
File diff suppressed because it is too large
Load Diff
+125
-108
@@ -1,7 +1,7 @@
|
||||
#include <amethyst/iron.hpp>
|
||||
|
||||
/** Setup for everything (oder so) */
|
||||
enum LiPathRectFlags_ : amy::ui {
|
||||
enum LiPathRectFlags_ : Amy::ui {
|
||||
LiPathRectFlags_None = 0,
|
||||
LiPathRectFlags_KeepTopLeft = (1 << 0),
|
||||
LiPathRectFlags_KeepTopRight = (1 << 1),
|
||||
@@ -13,69 +13,75 @@ enum LiPathRectFlags_ : amy::ui {
|
||||
LiPathRectFlags_KeepRight = (1 << 1) | (1 << 2),
|
||||
};
|
||||
|
||||
namespace amy {
|
||||
namespace Amy {
|
||||
constexpr auto __pi = std::numbers::pi;
|
||||
|
||||
void iron::drawlist::merge(iron::drawlist* list) {
|
||||
for (size_t i = 0; i < list->m_data.size(); i++) {
|
||||
m_data.push_back(std::move(list->m_data[i]));
|
||||
void Iron::Drawlist::Merge(Iron::Drawlist* list) {
|
||||
for (size_t i = 0; i < list->pData.size(); i++) {
|
||||
pData.push_back(std::move(list->pData[i]));
|
||||
}
|
||||
list->clear();
|
||||
list->Clear();
|
||||
}
|
||||
|
||||
void iron::drawlist::clear() { m_data.clear(); }
|
||||
|
||||
iron::command::ref iron::drawlist::newCommand() {
|
||||
auto ret = std::make_unique<command>();
|
||||
ret->layer = m_layer;
|
||||
ret->index = m_data.size();
|
||||
ret->tex = m_tex;
|
||||
return ret;
|
||||
void Iron::Drawlist::Clear() {
|
||||
pData.clear();
|
||||
pPath.clear();
|
||||
DrawSolid();
|
||||
while (!ClipRects.empty()) {
|
||||
ClipRects.pop();
|
||||
}
|
||||
pLayer = 0;
|
||||
}
|
||||
|
||||
void iron::drawlist::clipCmd(command* ptr) {
|
||||
if (!clipRects.empty()) {
|
||||
ptr->scissorOn = true;
|
||||
ptr->scissorRect = ivec4(clipRects.top());
|
||||
Iron::Command::Ref Iron::Drawlist::NewCommand() {
|
||||
auto ret = Command::New();
|
||||
ret->Layer = pLayer;
|
||||
ret->Index = pData.size();
|
||||
ret->Tex = pTex;
|
||||
return std::move(ret);
|
||||
}
|
||||
|
||||
void Iron::Drawlist::clipCmd(Command* ptr) {
|
||||
if (!ClipRects.empty()) {
|
||||
ptr->ScissorOn = true;
|
||||
ptr->ScissorRect = ivec4(ClipRects.top());
|
||||
}
|
||||
}
|
||||
|
||||
void iron::drawlist::push(command::ref cmd) {
|
||||
m_data.push_back(std::move(cmd));
|
||||
}
|
||||
void Iron::Drawlist::Push(Command::Ref cmd) { pData.push_back(std::move(cmd)); }
|
||||
|
||||
void iron::drawlist::drawSolid() { m_tex = iron::whiteTex(); }
|
||||
void Iron::Drawlist::DrawSolid() { pTex = Iron::WhiteTex(); }
|
||||
|
||||
void iron::drawlist::pathArcToN(const fvec2& c, float radius, float a_min,
|
||||
void Iron::Drawlist::PathArcToN(const fvec2& c, float radius, float a_min,
|
||||
float a_max, int segments) {
|
||||
// pathAdd(c)
|
||||
pathReserve(segments + 1);
|
||||
PathReserve(segments + 1);
|
||||
for (int i = 0; i < segments; i++) {
|
||||
float a = a_min + ((float)i / (float)segments) * (a_max - a_min);
|
||||
pathAdd(fvec2(c.x + std::cos(a) * radius, c.y + std::sin(a) * radius));
|
||||
PathAdd(fvec2(c.x + std::cos(a) * radius, c.y + std::sin(a) * radius));
|
||||
}
|
||||
}
|
||||
|
||||
void iron::drawlist::pathFastArcToN(const fvec2& c, float r, float amin,
|
||||
void Iron::Drawlist::PathFastArcToN(const fvec2& c, float r, float amin,
|
||||
float amax, int s) {
|
||||
/**
|
||||
* Funcion with less division overhead
|
||||
* Usefull for stuff where a lot of calculations are required
|
||||
*/
|
||||
float d = (amax - amin) / s;
|
||||
pathReserve(s + 1);
|
||||
PathReserve(s + 1);
|
||||
for (int i = 0; i <= s; i++) {
|
||||
float a = amin + i * d;
|
||||
pathAdd(fvec2(c.x + std::cos(a) * r, c.y + std::sin(a) * r));
|
||||
PathAdd(fvec2(c.x + std::cos(a) * r, c.y + std::sin(a) * r));
|
||||
}
|
||||
}
|
||||
|
||||
void iron::drawlist::pathRect(const fvec2& a, const fvec2& b, float rounding) {
|
||||
void Iron::Drawlist::PathRect(const fvec2& a, const fvec2& b, float rounding) {
|
||||
if (rounding == 0.f) {
|
||||
pathAdd(a);
|
||||
pathAdd(fvec2(b.x, a.y));
|
||||
pathAdd(b);
|
||||
pathAdd(fvec2(a.x, b.y));
|
||||
PathAdd(a);
|
||||
PathAdd(fvec2(b.x, a.y));
|
||||
PathAdd(b);
|
||||
PathAdd(fvec2(a.x, b.y));
|
||||
} else {
|
||||
float r = std::min({rounding, (b.x - a.x) * 0.5f, (b.y - a.y) * 0.5f});
|
||||
/** Calculate Optimal segment count automatically */
|
||||
@@ -87,28 +93,28 @@ void iron::drawlist::pathRect(const fvec2& a, const fvec2& b, float rounding) {
|
||||
* The Commands need to be setup clockwise
|
||||
*/
|
||||
/** Top Left */
|
||||
pathAdd(fvec2(a.x + r, a.y));
|
||||
pathFastArcToN(fvec2(b.x - r, a.y + r), r, -__pi / 2.0f, 0.0f, segments);
|
||||
PathAdd(fvec2(a.x + r, a.y));
|
||||
PathFastArcToN(fvec2(b.x - r, a.y + r), r, -__pi / 2.0f, 0.0f, segments);
|
||||
/** Top Right */
|
||||
pathAdd(fvec2(b.x, b.y - r));
|
||||
pathFastArcToN(fvec2(b.x - r, b.y - r), r, 0.0f, __pi / 2.0f, segments);
|
||||
PathAdd(fvec2(b.x, b.y - r));
|
||||
PathFastArcToN(fvec2(b.x - r, b.y - r), r, 0.0f, __pi / 2.0f, segments);
|
||||
/** Bottom Right */
|
||||
pathAdd(fvec2(a.x + r, b.y));
|
||||
pathFastArcToN(fvec2(a.x + r, b.y - r), r, __pi / 2.0f, __pi, segments);
|
||||
PathAdd(fvec2(a.x + r, b.y));
|
||||
PathFastArcToN(fvec2(a.x + r, b.y - r), r, __pi / 2.0f, __pi, segments);
|
||||
/** Bottom Left */
|
||||
pathAdd(fvec2(a.x, a.y + r));
|
||||
pathFastArcToN(fvec2(a.x + r, a.y + r), r, __pi, 3.0f * __pi / 2.0f,
|
||||
PathAdd(fvec2(a.x, a.y + r));
|
||||
PathFastArcToN(fvec2(a.x + r, a.y + r), r, __pi, 3.0f * __pi / 2.0f,
|
||||
segments);
|
||||
}
|
||||
}
|
||||
|
||||
void iron::drawlist::pathRectEx(const fvec2& a, const fvec2& b, float rounding,
|
||||
void Iron::Drawlist::PathRectEx(const fvec2& a, const fvec2& b, float rounding,
|
||||
ui flags) {
|
||||
if (rounding == 0.f) {
|
||||
pathAdd(a);
|
||||
pathAdd(fvec2(b.x, a.y));
|
||||
pathAdd(b);
|
||||
pathAdd(fvec2(a.x, b.y));
|
||||
PathAdd(a);
|
||||
PathAdd(fvec2(b.x, a.y));
|
||||
PathAdd(b);
|
||||
PathAdd(fvec2(a.x, b.y));
|
||||
} else {
|
||||
float r = std::min({rounding, (b.x - a.x) * 0.5f, (b.y - a.y) * 0.5f});
|
||||
/** Calculate Optimal segment count automatically */
|
||||
@@ -121,95 +127,106 @@ void iron::drawlist::pathRectEx(const fvec2& a, const fvec2& b, float rounding,
|
||||
*/
|
||||
/** Top Left */
|
||||
if (flags & LiPathRectFlags_KeepTopLeft) {
|
||||
pathAdd(a);
|
||||
PathAdd(a);
|
||||
} else {
|
||||
pathAdd(fvec2(a.x + r, a.y));
|
||||
pathFastArcToN(fvec2(b.x - r, a.y + r), r, -__pi / 2.0f, 0.0f, segments);
|
||||
PathAdd(fvec2(a.x + r, a.y));
|
||||
PathFastArcToN(fvec2(b.x - r, a.y + r), r, -__pi / 2.0f, 0.0f, segments);
|
||||
}
|
||||
|
||||
/** Top Right */
|
||||
if (flags & LiPathRectFlags_KeepTopRight) {
|
||||
pathAdd(fvec2(b.x, a.y));
|
||||
PathAdd(fvec2(b.x, a.y));
|
||||
} else {
|
||||
pathAdd(fvec2(b.x, b.y - r));
|
||||
pathFastArcToN(fvec2(b.x - r, b.y - r), r, 0.0f, __pi / 2.0f, segments);
|
||||
PathAdd(fvec2(b.x, b.y - r));
|
||||
PathFastArcToN(fvec2(b.x - r, b.y - r), r, 0.0f, __pi / 2.0f, segments);
|
||||
}
|
||||
/** Bottom Right */
|
||||
if (flags & LiPathRectFlags_KeepBotRight) {
|
||||
pathAdd(b);
|
||||
PathAdd(b);
|
||||
} else {
|
||||
pathAdd(fvec2(a.x + r, b.y));
|
||||
pathFastArcToN(fvec2(a.x + r, b.y - r), r, __pi / 2.0f, __pi, segments);
|
||||
PathAdd(fvec2(a.x + r, b.y));
|
||||
PathFastArcToN(fvec2(a.x + r, b.y - r), r, __pi / 2.0f, __pi, segments);
|
||||
}
|
||||
/** Bottom Left */
|
||||
if (flags & LiPathRectFlags_KeepBotLeft) {
|
||||
pathAdd(fvec2(a.x, b.y));
|
||||
PathAdd(fvec2(a.x, b.y));
|
||||
} else {
|
||||
pathAdd(fvec2(a.x, a.y + r));
|
||||
pathFastArcToN(fvec2(a.x + r, a.y + r), r, __pi, 3.0f * __pi / 2.0f,
|
||||
PathAdd(fvec2(a.x, a.y + r));
|
||||
PathFastArcToN(fvec2(a.x + r, a.y + r), r, __pi, 3.0f * __pi / 2.0f,
|
||||
segments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void iron::drawlist::drawRect(const fvec2& pos, const fvec2& size, ui color,
|
||||
void Iron::Drawlist::DrawRect(const fvec2& pos, const fvec2& size, ui color,
|
||||
int thickness) {
|
||||
pathRect(pos, pos + size);
|
||||
pathStroke(color, thickness, 1);
|
||||
PathRect(pos, pos + size);
|
||||
PathStroke(color, thickness, 1);
|
||||
}
|
||||
|
||||
void iron::drawlist::drawRectFilled(const fvec2& pos, const fvec2& size,
|
||||
void Iron::Drawlist::DrawRectFilled(const fvec2& pos, const fvec2& size,
|
||||
ui color) {
|
||||
pathRect(pos, pos + size);
|
||||
pathFill(color);
|
||||
PathRect(pos, pos + size);
|
||||
PathFill(color);
|
||||
}
|
||||
|
||||
void iron::drawlist::drawTriangle(const fvec2& a, const fvec2& b,
|
||||
void Iron::Drawlist::DrawTriangle(const fvec2& a, const fvec2& b,
|
||||
const fvec2& c, ui color, int thickness) {
|
||||
pathAdd(a);
|
||||
pathAdd(b);
|
||||
pathAdd(c);
|
||||
pathStroke(color, thickness, 1);
|
||||
PathAdd(a);
|
||||
PathAdd(b);
|
||||
PathAdd(c);
|
||||
PathStroke(color, thickness, 1);
|
||||
}
|
||||
|
||||
void iron::drawlist::drawTriangleFilled(const fvec2& a, const fvec2& b,
|
||||
void Iron::Drawlist::DrawTriangleFilled(const fvec2& a, const fvec2& b,
|
||||
const fvec2& c, ui color) {
|
||||
pathAdd(a);
|
||||
pathAdd(b);
|
||||
pathAdd(c);
|
||||
pathFill(color);
|
||||
PathAdd(a);
|
||||
PathAdd(b);
|
||||
PathAdd(c);
|
||||
PathFill(color);
|
||||
}
|
||||
|
||||
void iron::drawlist::drawCircle(const fvec2& center, float rad, ui color,
|
||||
void Iron::Drawlist::DrawCircle(const fvec2& center, float rad, ui color,
|
||||
int segments, int thickness) {
|
||||
if (segments <= 0) {
|
||||
// Auto Segment
|
||||
} else {
|
||||
float am = (__pi * 2.0f) * ((float)segments) / (float)segments;
|
||||
pathArcToN(center, rad, 0.f, am, segments);
|
||||
PathArcToN(center, rad, 0.f, am, segments);
|
||||
}
|
||||
drawSolid(); // Only Solid Color Supported
|
||||
pathStroke(color, thickness, 1);
|
||||
DrawSolid(); // Only Solid Color Supported
|
||||
PathStroke(color, thickness, 1);
|
||||
}
|
||||
|
||||
void iron::drawlist::drawCircleFilled(const fvec2& center, float rad, ui color,
|
||||
void Iron::Drawlist::DrawCircleFilled(const fvec2& center, float rad, ui color,
|
||||
int segments) {
|
||||
if (segments <= 0) {
|
||||
// Auto Segment
|
||||
} else {
|
||||
float am = (__pi * 2.0f) * ((float)segments) / (float)segments;
|
||||
pathArcToN(center, rad, 0.f, am, segments);
|
||||
PathArcToN(center, rad, 0.f, am, segments);
|
||||
}
|
||||
pathFill(color);
|
||||
PathFill(color);
|
||||
}
|
||||
|
||||
void iron::drawlist::drawPolyLine(const std::vector<fvec2>& points, ui clr,
|
||||
void Iron::Drawlist::DrawFromAtlas(fvec2 pos, fvec2 size, fvec4 cut_rect,
|
||||
ui color) {
|
||||
auto r = Iron::PrimRect(pos, size);
|
||||
auto cmd = NewCommand();
|
||||
auto uv = cut_rect / fvec4(pTex->Size(), pTex->Size());
|
||||
uv.y = 1.f - uv.y;
|
||||
uv.w = 1.f - uv.w;
|
||||
Iron::CmdQuad(cmd.get(), r, uv, color);
|
||||
Push(std::move(cmd));
|
||||
}
|
||||
|
||||
void Iron::Drawlist::DrawPolyLine(const std::vector<fvec2>& points, ui clr,
|
||||
ui flags, int thickness) {
|
||||
if (points.size() < 2) {
|
||||
return;
|
||||
}
|
||||
drawSolid();
|
||||
auto cmd = newCommand();
|
||||
DrawSolid();
|
||||
auto cmd = NewCommand();
|
||||
bool close = (flags & (1 << 0));
|
||||
int num_points = close ? (int)points.size() : (int)points.size() - 1;
|
||||
if (flags & (1 << 1)) {
|
||||
@@ -218,54 +235,54 @@ void iron::drawlist::drawPolyLine(const std::vector<fvec2>& points, ui clr,
|
||||
// Non antialiased lines look awful when rendering with thickness != 1
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
int j = (i + 1) == (int)points.size() ? 0 : (i + 1);
|
||||
auto line = primLine(points[i], points[j], thickness);
|
||||
cmdQuad(cmd.get(), line, fvec4(0.f, 1.f, 1.f, 0.f), clr);
|
||||
auto line = PrimLine(points[i], points[j], thickness);
|
||||
CmdQuad(cmd.get(), line, fvec4(0.f, 1.f, 1.f, 0.f), clr);
|
||||
}
|
||||
}
|
||||
push(std::move(cmd));
|
||||
Push(std::move(cmd));
|
||||
}
|
||||
|
||||
void iron::drawlist::drawConvexPolyFilled(const std::vector<fvec2>& points,
|
||||
void Iron::Drawlist::DrawConvexPolyFilled(const std::vector<fvec2>& points,
|
||||
ui clr) {
|
||||
if (points.size() < 3) {
|
||||
return; // Need at least three points
|
||||
}
|
||||
auto cmd = newCommand();
|
||||
cmdConvexPolyFilled(cmd.get(), points, clr, m_tex);
|
||||
push(std::move(cmd));
|
||||
auto cmd = NewCommand();
|
||||
CmdConvexPolyFilled(cmd.get(), points, clr, pTex);
|
||||
Push(std::move(cmd));
|
||||
}
|
||||
|
||||
void iron::drawlist::drawText(const fvec2& pos, const std::string& text,
|
||||
void Iron::Drawlist::DrawText(const fvec2& pos, const std::string& text,
|
||||
ui color) {
|
||||
/*if (!pCurrentFont) {
|
||||
if (!pCurrentFont) {
|
||||
return;
|
||||
}
|
||||
std::vector<Command::Ref> cmds;
|
||||
pCurrentFont->CmdTextEx(cmds, pos, color, pFontScale, text);
|
||||
for (size_t i = 0; i < cmds.size(); i++) {
|
||||
cmds[i]->Index = pDrawList.size();
|
||||
cmds[i]->Layer = Layer;
|
||||
AddCommand(std::move(cmds[i]));
|
||||
}*/
|
||||
cmds[i]->Index = pData.size();
|
||||
cmds[i]->Layer = pLayer;
|
||||
Push(std::move(cmds[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void iron::drawlist::drawTextEx(const fvec2& p, const std::string& text,
|
||||
void Iron::Drawlist::DrawTextEx(const fvec2& p, const std::string& text,
|
||||
ui color, ui flags, const fvec2& box) {
|
||||
/*if (!pCurrentFont) {
|
||||
if (!pCurrentFont) {
|
||||
return;
|
||||
}
|
||||
std::vector<Command::Ref> cmds;
|
||||
pCurrentFont->CmdTextEx(cmds, p, color, pFontScale, text, flags, box);
|
||||
for (size_t i = 0; i < cmds.size(); i++) {
|
||||
cmds[i]->Index = pDrawList.size();
|
||||
cmds[i]->Layer = Layer;
|
||||
AddCommand(std::move(cmds[i]));
|
||||
}*/
|
||||
cmds[i]->Index = pData.size();
|
||||
cmds[i]->Layer = pLayer;
|
||||
Push(std::move(cmds[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void iron::drawlist::drawLine(const fvec2& a, const fvec2& b, ui color, int t) {
|
||||
pathAdd(a);
|
||||
pathAdd(b);
|
||||
pathStroke(color, t);
|
||||
void Iron::Drawlist::DrawLine(const fvec2& a, const fvec2& b, ui color, int t) {
|
||||
PathAdd(a);
|
||||
PathAdd(b);
|
||||
PathStroke(color, t);
|
||||
}
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
@@ -0,0 +1,307 @@
|
||||
#include <amethyst/iron.hpp>
|
||||
#include <amethyst/utils.hpp>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
//#ifdef AMY_STB_TT
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
//#endif
|
||||
#include <stb_truetype.h>
|
||||
|
||||
namespace Amy {
|
||||
// Dont read this code please ... tnaks
|
||||
void Iron::Font::LoadBMF(ksr path) {
|
||||
Image img(path);
|
||||
img.Convert(Image::A8);
|
||||
if (img.Width() != img.Height() || img.Bpp() != 1 || img.Width() <= 0 ||
|
||||
img.Height() <= 0) {
|
||||
throw std::runtime_error(
|
||||
"[Amy] Font: BMF is not in rgba or not 1x1 dimensioned!");
|
||||
}
|
||||
auto base = Amy::Texture::New();
|
||||
base->Load(img.GetBuffer(), img.Width(), img.Height(), img.Bpp(), img.Fmt());
|
||||
base->Unloadable(false);
|
||||
PxHeight = img.Height() / 16;
|
||||
for (int i = 0; i < img.Height(); i += PxHeight) {
|
||||
for (int j = 0; j < img.Width(); j += PxHeight) {
|
||||
int maxw = 0;
|
||||
Amy::Texture::Ref tex = Amy::Texture::New();
|
||||
for (int y = i; y < i + PxHeight; y++) {
|
||||
for (int x = j; x < j + PxHeight; x++) {
|
||||
if (img.GetBuffer()[y * img.Width() + x] != 0) {
|
||||
maxw = std::max(maxw, x - j);
|
||||
}
|
||||
}
|
||||
}
|
||||
Codepoint cp;
|
||||
cp.Valid = maxw != 0;
|
||||
cp.Cp = (i / PxHeight) * 16 + (j / PxHeight);
|
||||
cp.Offset = 0.f;
|
||||
if (cp.Valid) {
|
||||
tex->Load(base->Ptr(), base->Size(), base->Uv());
|
||||
cp.Size = fvec2(maxw + 1, PxHeight);
|
||||
cp.Tex = tex;
|
||||
cp.Uv = fvec4(float(j) / float(img.Width()),
|
||||
1.f - float(i) / float(img.Height()),
|
||||
float(j + maxw + 1) / float(img.Width()),
|
||||
1.f - float(i + PxHeight) / float(img.Height()));
|
||||
Textures.push_back(tex);
|
||||
}
|
||||
pCodeMap[(i / PxHeight) * 16 + (j / PxHeight)] = cp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Iron::Font::LoadTTF(ksr path, int size) {
|
||||
auto data = Amy::Utils::LoadFile2Mem(path);
|
||||
LoadTTF(data, size);
|
||||
}
|
||||
|
||||
void Iron::Font::LoadTTF(const vec<uc>& data, int size) {
|
||||
/**
|
||||
* Some additional Info:
|
||||
* Removed the stbtt get bitmapbox as we dont need to place
|
||||
* the glyps nicely in the tex. next step would be using the free
|
||||
* space on the y axis to get mor glyphs inside
|
||||
*/
|
||||
PxHeight = size;
|
||||
int texszs = Amy::Utils::NextPow2(PxHeight * 16);
|
||||
if (texszs > 1024) {
|
||||
texszs = 1024; // Max size
|
||||
}
|
||||
|
||||
stbtt_fontinfo inf;
|
||||
if (!stbtt_InitFont(&inf, data.data(), 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
float scale = stbtt_ScaleForPixelHeight(&inf, PxHeight);
|
||||
|
||||
int ascent, descent, lineGap;
|
||||
stbtt_GetFontVMetrics(&inf, &ascent, &descent, &lineGap);
|
||||
int baseline = static_cast<int>(ascent * scale);
|
||||
|
||||
// Cache to not render same codepoint tex twice
|
||||
std::map<u32, int> buf_cache;
|
||||
|
||||
std::vector<u8> font_tex(texszs * texszs, 0);
|
||||
auto tex = Texture::New();
|
||||
fvec2 off;
|
||||
|
||||
bool empty = true;
|
||||
|
||||
for (u32 ii = 0x0000; ii <= 0xFFFF; ii++) {
|
||||
int gi = stbtt_FindGlyphIndex(&inf, ii);
|
||||
if (gi == 0) continue;
|
||||
if (stbtt_IsGlyphEmpty(&inf, gi)) continue;
|
||||
|
||||
int w = 0, h = 0, xo = 0, yo = 0;
|
||||
unsigned char* bitmap =
|
||||
stbtt_GetCodepointBitmap(&inf, scale, scale, ii, &w, &h, &xo, &yo);
|
||||
if (!bitmap || w <= 0 || h <= 0) {
|
||||
if (bitmap) free(bitmap);
|
||||
continue;
|
||||
}
|
||||
|
||||
u32 hashed_map =
|
||||
Utils::HashMemory(std::vector<u8>(bitmap, bitmap + (w * h)));
|
||||
if (buf_cache.find(hashed_map) != buf_cache.end()) {
|
||||
Codepoint c = GetCodepoint(buf_cache[hashed_map]);
|
||||
c.Cp = ii;
|
||||
pCodeMap[ii] = c;
|
||||
free(bitmap);
|
||||
continue;
|
||||
} else {
|
||||
buf_cache[hashed_map] = ii;
|
||||
}
|
||||
|
||||
// Next row
|
||||
if (off.x + w > texszs) {
|
||||
off.y += PxHeight;
|
||||
off.x = 0.0f;
|
||||
}
|
||||
// Bake cause we go out of the tex
|
||||
if (off.y + PxHeight > texszs) {
|
||||
pMakeAtlas(false, font_tex, texszs, tex);
|
||||
tex = Texture::New();
|
||||
off = 0;
|
||||
std::fill(font_tex.begin(), font_tex.end(), 0);
|
||||
empty = true;
|
||||
}
|
||||
|
||||
// UVs & Codepoint
|
||||
Codepoint c;
|
||||
fvec4 uvs;
|
||||
// cast the ints to floats and not the floats...
|
||||
// dont know where my mind was when creating the code
|
||||
uvs.x = off.x / static_cast<float>(texszs);
|
||||
uvs.y = off.y / static_cast<float>(texszs);
|
||||
uvs.z = (off.x + w) / static_cast<float>(texszs);
|
||||
uvs.w = (off.y + h) / static_cast<float>(texszs);
|
||||
// Flip (too lazy to place it into the seq at top)
|
||||
uvs.y = 1.f - uvs.y;
|
||||
uvs.w = 1.f - uvs.w;
|
||||
c.Uv = uvs;
|
||||
c.Tex = tex;
|
||||
c.Size = fvec2(w, h);
|
||||
c.Offset = baseline + yo;
|
||||
c.Cp = ii;
|
||||
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
int map_pos = ((static_cast<int>(off.y) + y) * texszs +
|
||||
(static_cast<int>(off.x) + x));
|
||||
font_tex[map_pos] = bitmap[x + y * w];
|
||||
}
|
||||
}
|
||||
|
||||
empty = false;
|
||||
pCodeMap[ii] = c;
|
||||
free(bitmap);
|
||||
|
||||
// offset by 1 (prevents visual glitches i had)
|
||||
off.x += w + 1;
|
||||
}
|
||||
|
||||
if (!empty) {
|
||||
pMakeAtlas(true, font_tex, texszs, tex);
|
||||
}
|
||||
}
|
||||
|
||||
void Iron::Font::pMakeAtlas(bool final, vec<uc>& font_tex, int texszs,
|
||||
Texture::Ref tex) {
|
||||
tex->Load(font_tex, texszs, texszs, 1, Amy::Image::A8);
|
||||
Textures.push_back(tex);
|
||||
}
|
||||
|
||||
Iron::Font::Codepoint& Iron::Font::GetCodepoint(ui cp) {
|
||||
// Check if codepoijt exist or return a static invalid one
|
||||
auto res = pCodeMap.find(cp);
|
||||
if (res == pCodeMap.end()) {
|
||||
static Codepoint invalid;
|
||||
invalid.Valid = false;
|
||||
return invalid;
|
||||
}
|
||||
return res->second;
|
||||
}
|
||||
|
||||
fvec2 Iron::Font::GetTextBounds(ksr text, float scale) {
|
||||
// Use wstring for exemple for german äöü
|
||||
auto wtext = std::filesystem::path(text).wstring();
|
||||
// Create a temp position and offset as [0, 0]
|
||||
fvec2 res;
|
||||
float x = 0;
|
||||
// Curent Font Scale
|
||||
float cfs = (PxFactor * scale) / (float)PxHeight;
|
||||
float lh = (float)PxHeight * cfs;
|
||||
size_t index = 0;
|
||||
for (auto& it : wtext) {
|
||||
if (it == L'\0') {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
auto cp = GetCodepoint(it);
|
||||
if (!cp.Valid && it != '\n' && it != '\t' && it != ' ') {
|
||||
continue;
|
||||
}
|
||||
switch (it) {
|
||||
case L'\n':
|
||||
res.y += lh;
|
||||
res.x = std::max(res.x, x);
|
||||
x = 0.f;
|
||||
break;
|
||||
case L'\t':
|
||||
x += 16 * cfs;
|
||||
break;
|
||||
case L' ':
|
||||
x += 4 * cfs;
|
||||
// Fall trough here to get the same result as in
|
||||
// TextCommand if/else Section
|
||||
default:
|
||||
x += cp.Size.x * cfs;
|
||||
if (index != wtext.size()) {
|
||||
x += 2 * cfs;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
res.x = std::max(res.x, x);
|
||||
res.y += lh;
|
||||
return res;
|
||||
}
|
||||
|
||||
void Iron::Font::CmdTextEx(vec<Command::Ref>& cmds, const fvec2& pos, ui color,
|
||||
float scale, const std::string& text,
|
||||
AmyTextFlags flags, const fvec2& box) {
|
||||
fvec2 off;
|
||||
float cfs = (PxFactor * scale) / (float)PxHeight;
|
||||
float lh = (float)PxHeight * cfs;
|
||||
fvec2 td;
|
||||
fvec2 rpos = pos;
|
||||
fvec2 rbox = box;
|
||||
if (flags & (AmyTextFlags_AlignMid | AmyTextFlags_AlignRight)) {
|
||||
td = GetTextBounds(text, scale);
|
||||
}
|
||||
if (flags & AmyTextFlags_AlignMid) {
|
||||
rpos = rbox * 0.5 - td * 0.5 + pos;
|
||||
}
|
||||
if (flags & AmyTextFlags_AlignRight) {
|
||||
rpos.x = rpos.x - td.x;
|
||||
}
|
||||
|
||||
std::vector<std::string> lines;
|
||||
std::istringstream iss(text);
|
||||
std::string tmp;
|
||||
while (std::getline(iss, tmp)) {
|
||||
lines.push_back(tmp);
|
||||
}
|
||||
|
||||
for (auto& it : lines) {
|
||||
/*if (flags & AmyTextFlags_Short) {
|
||||
fvec2 tmp_dim;
|
||||
it = ShortText(it, box.x() - pos.x(), tmp_dim);
|
||||
}*/
|
||||
// Bitte nicht nachmachen... Also ernsthaft jz, bitte macht das nicht
|
||||
auto wline = std::filesystem::path(it).wstring();
|
||||
auto cmd = Command::New();
|
||||
auto Tex = GetCodepoint(wline[0]).Tex;
|
||||
cmd->Tex = Tex;
|
||||
for (auto& jt : wline) {
|
||||
auto cp = GetCodepoint(jt);
|
||||
if ((!cp.Valid && jt != L' ' && jt != L'\n' && jt != L'\t') &&
|
||||
jt != L'\r') {
|
||||
continue;
|
||||
}
|
||||
if (Tex != cp.Tex) {
|
||||
cmds.push_back(std::move(cmd));
|
||||
cmd = Command::New();
|
||||
Tex = cp.Tex;
|
||||
cmd->Tex = Tex;
|
||||
}
|
||||
if (jt == L'\t') {
|
||||
off.x += 16 * cfs;
|
||||
} else {
|
||||
if (jt != L' ') {
|
||||
if (flags & AmyTextFlags_Shaddow) {
|
||||
// Draw
|
||||
Rect rec = Iron::PrimRect(
|
||||
rpos + vec2(off.x + 1, off.y + (cp.Offset * cfs)) + 1,
|
||||
cp.Size * cfs, 0.f);
|
||||
Iron::CmdQuad(cmd.get(), rec, cp.Uv, 0xff111111);
|
||||
}
|
||||
// Draw
|
||||
Rect rec = Iron::PrimRect(rpos + off + fvec2(0, (cp.Offset * cfs)),
|
||||
cp.Size * cfs, 0.f);
|
||||
Iron::CmdQuad(cmd.get(), rec, cp.Uv, color);
|
||||
off.x += cp.Size.x * cfs + 2 * cfs;
|
||||
} else {
|
||||
off.x += 4 * cfs;
|
||||
}
|
||||
}
|
||||
}
|
||||
cmds.push_back(std::move(cmd));
|
||||
off.y += lh;
|
||||
off.x = 0;
|
||||
}
|
||||
}
|
||||
} // namespace Amy
|
||||
+118
-103
@@ -1,20 +1,9 @@
|
||||
#include <amethyst/iron.hpp>
|
||||
#include <amethyst/utils.hpp>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#define catch2() \
|
||||
; \
|
||||
({ \
|
||||
std::cout << std::format("{}:{}", __FILE__, __LINE__) << std::endl; \
|
||||
while (aptMainLoop()) { \
|
||||
hidScanInput(); \
|
||||
if (hidKeysDown() & KEY_A) { \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
})
|
||||
|
||||
namespace amy {
|
||||
namespace Amy {
|
||||
const char* __ironshader__ = R"(; LI7 Shader
|
||||
; Constants
|
||||
.constf myconst(0.0, 1.0, 0.00392156862745, 0.0)
|
||||
@@ -50,128 +39,153 @@ const char* __ironshader__ = R"(; LI7 Shader
|
||||
end
|
||||
.end)";
|
||||
|
||||
// clang-format off
|
||||
unsigned char li_shader[] = {
|
||||
0x44, 0x56, 0x4c, 0x42, 0x1, 0x0, 0x0, 0x0, 0xa4, 0x0, 0x0, 0x0, 0x44, 0x56, 0x4c, 0x50, 0x0, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x98, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4e, 0x1, 0xf0, 0x7, 0x4e, 0x2, 0x8, 0x2, 0x8, 0x3, 0x18, 0x2, 0x8, 0x4, 0x28, 0x2, 0x8, 0x5, 0x38, 0x2, 0x8, 0x6, 0x10, 0x40, 0x4c, 0x7, 0xf1, 0x27, 0x22, 0x8, 0x10, 0x21, 0x4c, 0x0, 0x0, 0x0, 0x88, 0xac, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa1, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0xc3, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64, 0xc3, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x62, 0xc3, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x61, 0xc3, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0xaf, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f, 0xd5, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x44, 0x56, 0x4c, 0x45, 0x2, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x54, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x54, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x6c, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x74, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x2, 0x0, 0x5f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x0, 0x1, 0x1, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, 0x2, 0x0, 0x1, 0x0, 0xf, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x13, 0x0, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0, 0x0,
|
||||
};
|
||||
// clang-format on
|
||||
size_t li_shader_size = 0x124;
|
||||
std::vector<iron::vertex, linearAllocator<iron::vertex>> iron::m_vbuf;
|
||||
std::vector<u16, linearAllocator<u16>> iron::m_ibuf;
|
||||
int iron::uLocProj = 0;
|
||||
c3d::shader* iron::m_shader = nullptr;
|
||||
mat4 iron::m_mtx;
|
||||
int iron::m_idx = 0, iron::m_vtx = 0;
|
||||
texture* iron::m_solid = nullptr;
|
||||
std::vector<Iron::Vertex, LinearAllocator<Iron::Vertex>> Iron::m_vbuf;
|
||||
std::vector<u16, LinearAllocator<u16>> Iron::m_ibuf;
|
||||
int Iron::uLocProj = 0;
|
||||
C3D::Shader* Iron::m_shader = nullptr;
|
||||
mat4 Iron::m_mtx;
|
||||
int Iron::m_idx = 0, Iron::m_vtx = 0;
|
||||
Texture::Ref Iron::m_solid = nullptr;
|
||||
ui Iron::VertexCount = 0;
|
||||
ui Iron::IndexCount = 0;
|
||||
|
||||
void iron::init() {
|
||||
setupShader();
|
||||
void Iron::Init() {
|
||||
pSetupShader();
|
||||
m_vbuf.resize(4 * 4096);
|
||||
m_ibuf.resize(6 * 4096);
|
||||
initSolidTex();
|
||||
pInitSolidTex();
|
||||
}
|
||||
|
||||
void iron::newFrame() {
|
||||
void Iron::Exit() {
|
||||
m_solid.reset();
|
||||
delete m_shader;
|
||||
m_vbuf.clear();
|
||||
m_ibuf.clear();
|
||||
}
|
||||
|
||||
void Iron::NewFrame() {
|
||||
VertexCount = m_vtx;
|
||||
IndexCount = m_idx;
|
||||
m_idx = 0;
|
||||
m_vtx = 0;
|
||||
}
|
||||
|
||||
C3D_Mtx m;
|
||||
|
||||
void iron::drawOn(c3d::screen* screen) {
|
||||
m_shader->use();
|
||||
Mtx_Identity(&m);
|
||||
Mtx_OrthoTilt(&m, 0.f, (float)screen->width(), (float)screen->height(), 0.f,
|
||||
1.f, -1.f, false);
|
||||
m_mtx = mat4::ortho(0.f, (float)screen->width(), (float)screen->height(), 0.f,
|
||||
void Iron::DrawOn(C3D::Screen* screen) {
|
||||
m_shader->Use();
|
||||
m_mtx = mat4::ortho(0.f, (float)screen->Width(), (float)screen->Height(), 0.f,
|
||||
1.f, -1.f);
|
||||
m_shader->setMat4(uLocProj, &m);
|
||||
m_shader->SetMat4(uLocProj, m_mtx);
|
||||
}
|
||||
|
||||
void iron::draw(const std::vector<iron::command::ref>& data) {
|
||||
void Iron::Draw(const std::vector<Iron::Command::Ref>& data) {
|
||||
// disable depthtest cause we have no z buffer
|
||||
c3d::depthTest(false);
|
||||
fragConfig();
|
||||
C3D::DepthTest(false);
|
||||
size_t i = 0;
|
||||
while (i < data.size()) {
|
||||
texture* tex = data[i]->tex;
|
||||
if (!tex) {
|
||||
Texture::Ref tex = data[i]->Tex;
|
||||
if (!tex || !tex->Ptr()) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
auto scissorOn = data[i]->scissorOn;
|
||||
auto scissor = data[i]->scissorRect;
|
||||
auto start = i;
|
||||
pFragConfig(tex->Ptr()->fmt);
|
||||
auto scissorOn = data[i]->ScissorOn;
|
||||
auto scissor = data[i]->ScissorRect;
|
||||
auto start = m_idx;
|
||||
|
||||
// Loop until a statgechange and copy all data into vertex/index buf
|
||||
while (i < data.size() && scissorOn == data[i]->scissorOn &&
|
||||
scissor == data[i]->scissorRect && tex == data[i]->tex) {
|
||||
// Loop until a statgechange and copy all data into Vertex/index buf
|
||||
while (i < data.size() && scissorOn == data[i]->ScissorOn &&
|
||||
scissor == data[i]->ScissorRect && tex == data[i]->Tex) {
|
||||
auto c = data[i].get();
|
||||
|
||||
for (int j = 0; j < c->indexBuf.size(); j++) {
|
||||
m_ibuf[m_idx++] = m_vtx + c->indexBuf[j];
|
||||
if (!pCheckSize(c->IndexBuf.size(), c->VertexBuf.size())) {
|
||||
throw Error("iron: too much draw data!!!" +
|
||||
std::format("\nIdx: {}\nVtx: {}", c->IndexBuf.size(),
|
||||
c->VertexBuf.size()));
|
||||
}
|
||||
for (int j = 0; j < c->vertexBuf.size(); j++) {
|
||||
m_vbuf[m_vtx++] = c->vertexBuf[j];
|
||||
|
||||
for (int j = 0; j < c->IndexBuf.size(); j++) {
|
||||
m_ibuf[m_idx++] = m_vtx + c->IndexBuf[j];
|
||||
}
|
||||
for (int j = 0; j < c->VertexBuf.size(); j++) {
|
||||
m_vbuf[m_vtx++] = std::move(c->VertexBuf[j]);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
///// SCISSOR LOGIC BEG /////
|
||||
///// SCISSOR LOGIC END /////
|
||||
tex->bind();
|
||||
c3d::bufCfg<3>(m_vbuf.data(), sizeof(vertex));
|
||||
c3d::drawElements(i - start, m_ibuf.data() + start);
|
||||
tex->Bind();
|
||||
C3D::BufCfg<3>(m_vbuf.data(), sizeof(Vertex));
|
||||
C3D::DrawElements(m_idx - start, m_ibuf.data() + start);
|
||||
}
|
||||
c3d::depthTest(true);
|
||||
C3D::DepthTest(true);
|
||||
}
|
||||
|
||||
void iron::setupShader() {
|
||||
m_shader = new c3d::shader();
|
||||
m_shader->load("romfs:/shaders/lithium.shbin");
|
||||
// m_shader->compile(__ironshader__);
|
||||
m_shader->input(GPU_FLOAT, 2); // pos
|
||||
m_shader->input(GPU_FLOAT, 2); // uv
|
||||
m_shader->input(GPU_UNSIGNED_BYTE, 4); // color
|
||||
bool Iron::pCheckSize(size_t idx, size_t vtx) {
|
||||
return idx < m_ibuf.size() && vtx < m_vbuf.size();
|
||||
}
|
||||
|
||||
void Iron::pSetupShader() {
|
||||
m_shader = new C3D::Shader();
|
||||
m_shader->Compile(__ironshader__);
|
||||
m_shader->Input(GPU_FLOAT, 2); // pos
|
||||
m_shader->Input(GPU_FLOAT, 2); // uv
|
||||
m_shader->Input(GPU_UNSIGNED_BYTE, 4); // color
|
||||
uLocProj = m_shader->loc("projection");
|
||||
}
|
||||
|
||||
void iron::fragConfig() {
|
||||
c3d::frag::edit();
|
||||
c3d::frag::src(C3D_Both, GPU_TEXTURE0);
|
||||
c3d::frag::func(C3D_Both, GPU_MODULATE);
|
||||
void Iron::pFragConfig(GPU_TEXCOLOR clr) {
|
||||
C3D::Frag::Edit();
|
||||
switch (clr) {
|
||||
case GPU_A4:
|
||||
case GPU_A8:
|
||||
case GPU_L4:
|
||||
case GPU_L8:
|
||||
C3D::Frag::Src(C3D_Alpha, GPU_TEXTURE0);
|
||||
C3D::Frag::Func(C3D_RGB, GPU_REPLACE);
|
||||
C3D::Frag::Func(C3D_Alpha, GPU_MODULATE);
|
||||
break;
|
||||
|
||||
default:
|
||||
C3D::Frag::Src(C3D_Both, GPU_TEXTURE0);
|
||||
C3D::Frag::Func(C3D_Both, GPU_MODULATE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void iron::initSolidTex() {
|
||||
void Iron::pInitSolidTex() {
|
||||
// i know there is a lot of memory wasted :(
|
||||
std::vector<uc> pixels(16 * 16 * 4, 0xff);
|
||||
m_solid = new texture();
|
||||
m_solid->load(pixels, 16, 16);
|
||||
std::vector<uc> pixels(16 * 16, 0xff);
|
||||
m_solid = Texture::New();
|
||||
m_solid->Load(pixels, 16, 16, 1, Amy::Image::A8);
|
||||
if (!m_solid->Ptr()) {
|
||||
throw Error("white tex failed to load!");
|
||||
}
|
||||
}
|
||||
|
||||
bool iron::inBox(const fvec2& pos, const fvec2& size, const fvec4& area) {
|
||||
bool Iron::InBox(const fvec2& pos, const fvec2& size, const fvec4& area) {
|
||||
return (pos.x + size.x >= area.x && pos.y + size.y >= area.y &&
|
||||
pos.x <= area.z && pos.y <= area.w);
|
||||
}
|
||||
|
||||
bool iron::inBox(const fvec2& pos, const fvec4& area) {
|
||||
bool Iron::InBox(const fvec2& pos, const fvec4& area) {
|
||||
return (pos.x > area.x && pos.x < area.x + area.z && pos.y > area.y &&
|
||||
pos.y < area.y + area.w);
|
||||
}
|
||||
|
||||
bool iron::inBox(const fvec2& a, const fvec2& b, const fvec2& c,
|
||||
bool Iron::InBox(const fvec2& a, const fvec2& b, const fvec2& c,
|
||||
const fvec4& area) {
|
||||
return ((a.x < area.z && b.x < area.z && c.x < area.z) ||
|
||||
(a.y < area.w && b.y < area.w && c.y < area.w) ||
|
||||
(a.x > 0 && b.x > 0 && c.x > 0) || (a.y > 0 && b.y > 0 && c.y > 0));
|
||||
}
|
||||
|
||||
void iron::rotateCorner(fvec2& pos, float s, float c) {
|
||||
void Iron::RotateCorner(fvec2& pos, float s, float c) {
|
||||
float x = pos.x * c - pos.y * s;
|
||||
float y = pos.y * c - pos.x * s;
|
||||
pos = fvec2(x, y);
|
||||
}
|
||||
|
||||
rect iron::primRect(const fvec2& pos, const fvec2& size, float angle) {
|
||||
Rect Iron::PrimRect(const fvec2& pos, const fvec2& size, float angle) {
|
||||
fvec2 c = size * 0.5f; // Center
|
||||
fvec2 corner[4] = {
|
||||
fvec2(-c.x, -c.y),
|
||||
@@ -185,16 +199,16 @@ rect iron::primRect(const fvec2& pos, const fvec2& size, float angle) {
|
||||
float s = std::sin(angle);
|
||||
float co = std::cos(angle);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
rotateCorner(corner[i], s, co);
|
||||
RotateCorner(corner[i], s, co);
|
||||
}
|
||||
}
|
||||
|
||||
// Return Result
|
||||
return rect(corner[0] + pos + c, corner[1] + pos + c, corner[2] + pos + c,
|
||||
return Rect(corner[0] + pos + c, corner[1] + pos + c, corner[2] + pos + c,
|
||||
corner[3] + pos + c);
|
||||
}
|
||||
|
||||
rect iron::primLine(const fvec2& a, const fvec2& b, int thickness) {
|
||||
Rect Iron::PrimLine(const fvec2& a, const fvec2& b, int thickness) {
|
||||
// Using the vec maths api makes the code as short as it is
|
||||
fvec2 dir = a - b;
|
||||
float len = dir.Len();
|
||||
@@ -202,35 +216,36 @@ rect iron::primLine(const fvec2& a, const fvec2& b, int thickness) {
|
||||
fvec2 perpendicular(-unit_dir.y, unit_dir.x);
|
||||
fvec2 off = perpendicular * ((float)thickness * 0.5f);
|
||||
|
||||
return rect(a + off, b + off, a - off, b - off);
|
||||
return Rect(a + off, b + off, a - off, b - off);
|
||||
}
|
||||
|
||||
void iron::cmdQuad(command* cmd, const rect& q, const rect& uv, ui color) {
|
||||
cmd->add(0).add(1).add(2);
|
||||
cmd->add(0).add(2).add(3);
|
||||
cmd->add(vertex(q.botRight(), uv.botRight(), color));
|
||||
cmd->add(vertex(q.topRight(), uv.topRight(), color));
|
||||
cmd->add(vertex(q.topLeft(), uv.topLeft(), color));
|
||||
cmd->add(vertex(q.botLeft(), uv.botLeft(), color));
|
||||
void Iron::CmdQuad(Command* cmd, const Rect& q, const Rect& uv, ui color) {
|
||||
cmd->Add(0).Add(1).Add(2);
|
||||
cmd->Add(0).Add(2).Add(3);
|
||||
cmd->Add(Vertex(q.BotRight(), uv.BotRight(), color));
|
||||
cmd->Add(Vertex(q.TopRight(), uv.TopRight(), color));
|
||||
cmd->Add(Vertex(q.TopLeft(), uv.TopLeft(), color));
|
||||
cmd->Add(Vertex(q.BotLeft(), uv.BotLeft(), color));
|
||||
}
|
||||
|
||||
void iron::cmdTriangle(command* cmd, const fvec2& a, const fvec2& b,
|
||||
void Iron::CmdTriangle(Command* cmd, const fvec2& a, const fvec2& b,
|
||||
const fvec2& c, ui color) {
|
||||
cmd->add(2).add(1).add(0); // reverse cause otherwise invisible
|
||||
cmd->add(vertex(a, fvec2(0, 1), color));
|
||||
cmd->add(vertex(b, fvec2(1, 1), color));
|
||||
cmd->add(vertex(c, fvec2(1, 0), color));
|
||||
cmd->Add(2).Add(1).Add(0); // reverse cause otherwise invisible
|
||||
cmd->Add(Vertex(a, fvec2(0, 1), color));
|
||||
cmd->Add(Vertex(b, fvec2(1, 1), color));
|
||||
cmd->Add(Vertex(c, fvec2(1, 0), color));
|
||||
}
|
||||
|
||||
void iron::cmdConvexPolyFilled(command* cmd, const std::vector<fvec2>& points,
|
||||
ui color, texture* tex) {
|
||||
void Iron::CmdConvexPolyFilled(Command* cmd, const std::vector<fvec2>& points,
|
||||
ui color, Texture::Ref tex) {
|
||||
if (points.size() < 3 || tex == nullptr) {
|
||||
#ifdef AMY_GOD_DEV
|
||||
return;
|
||||
#else
|
||||
throw std::runtime_error("[amy] iron: trying to render convex poly with " +
|
||||
std::to_string(points.size()) +
|
||||
" points and texture " + std::to_string((ui)tex));
|
||||
" points and Texture " +
|
||||
std::to_string((ui)tex.get()));
|
||||
#endif
|
||||
}
|
||||
// Support for Custom Textures (UV calculation)
|
||||
@@ -245,13 +260,13 @@ void iron::cmdConvexPolyFilled(command* cmd, const std::vector<fvec2>& points,
|
||||
}
|
||||
// Get Short defines for UV
|
||||
// (Bottom Right is not required)
|
||||
auto uv_tl = tex->uv().topLeft();
|
||||
auto uv_tr = tex->uv().topRight();
|
||||
auto uv_bl = tex->uv().botLeft();
|
||||
auto uv_tl = tex->Uv().TopLeft();
|
||||
auto uv_tr = tex->Uv().TopRight();
|
||||
auto uv_bl = tex->Uv().BotLeft();
|
||||
|
||||
// Render
|
||||
for (int i = 2; i < (int)points.size(); i++) {
|
||||
cmd->add(0).add(i).add(i - 1);
|
||||
cmd->Add(0).Add(i).Add(i - 1);
|
||||
}
|
||||
for (int i = 0; i < (int)points.size(); i++) {
|
||||
// Calculate U and V coords
|
||||
@@ -259,7 +274,7 @@ void iron::cmdConvexPolyFilled(command* cmd, const std::vector<fvec2>& points,
|
||||
uv_tl.x + ((points[i].x - minX) / (maxX - minX)) * (uv_tr.x - uv_tl.x);
|
||||
float v =
|
||||
uv_tl.y + ((points[i].y - minY) / (maxY - minY)) * (uv_bl.y - uv_tl.y);
|
||||
cmd->add(vertex(points[i], fvec2(u, v), color));
|
||||
cmd->Add(Vertex(points[i], fvec2(u, v), color));
|
||||
}
|
||||
}
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
@@ -24,7 +24,7 @@ SOFTWARE.
|
||||
|
||||
#include <amethyst/maths/mat.hpp>
|
||||
|
||||
namespace amy {
|
||||
namespace Amy {
|
||||
mat4 mat4::rotateX(float a) {
|
||||
float c = std::cos(a);
|
||||
float s = std::sin(a);
|
||||
@@ -118,4 +118,4 @@ mat4 mat4::lookAt(const fvec3& pos, const fvec3& center, const fvec3& up) {
|
||||
ret(2, 3) = f.Dot(pos);
|
||||
return ret;
|
||||
}
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
#include <amethyst/renderer.hpp>
|
||||
|
||||
namespace amy {
|
||||
namespace Amy {
|
||||
Renderer::Renderer() {}
|
||||
|
||||
Renderer::~Renderer() {}
|
||||
} // namespace amy
|
||||
} // namespace Amy
|
||||
+44
-41
@@ -6,88 +6,91 @@
|
||||
#include <amethyst/utils.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace amy {
|
||||
namespace Amy {
|
||||
ui tile3dsTex(int x, int y, int w) {
|
||||
return ((((y >> 3) * ((int)w >> 3) + (x >> 3)) << 6) +
|
||||
((x & 1) | ((y & 1) << 1) | ((x & 2) << 1) | ((y & 2) << 2) |
|
||||
((x & 4) << 2) | ((y & 4) << 3)));
|
||||
}
|
||||
|
||||
GPU_TEXCOLOR image2TexFmt(const image::format& fmt) {
|
||||
GPU_TEXCOLOR image2TexFmt(const Image::Format& fmt) {
|
||||
switch (fmt) {
|
||||
case image::RGB:
|
||||
case Image::RGB:
|
||||
return GPU_RGB8;
|
||||
break;
|
||||
case image::RGBA:
|
||||
case Image::RGBA:
|
||||
return GPU_RGBA8;
|
||||
break;
|
||||
case image::RGB565:
|
||||
case Image::RGB565:
|
||||
return GPU_RGB565;
|
||||
break;
|
||||
case Image::A8:
|
||||
return GPU_A8;
|
||||
break;
|
||||
default:
|
||||
// Dummy
|
||||
return GPU_A4;
|
||||
throw std::runtime_error(
|
||||
"[amy] texture: Unsupported texture format used!");
|
||||
"[amy] texture: Unsupported texture Format used!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
texture::texture(cstr& path) { load(path); }
|
||||
Texture::Texture(ksr path) { Load(path); }
|
||||
|
||||
texture::~texture() { unload(); }
|
||||
Texture::~Texture() { Unload(); }
|
||||
|
||||
void texture::unload() {
|
||||
if (m_loaded) {
|
||||
C3D_TexDelete(&m_tex);
|
||||
m_loaded = false;
|
||||
void Texture::Unload() {
|
||||
if (pLoaded) {
|
||||
C3D_TexDelete(pTex);
|
||||
delete pTex;
|
||||
pTex = nullptr;
|
||||
pLoaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
void texture::load(cstr& path) {
|
||||
image img(path);
|
||||
if (img.width() > 1024 || img.height() > 1024) {
|
||||
throw std::runtime_error("Max Texture Size is 1024x1024!");
|
||||
}
|
||||
load(img.getBuffer(), img.width(), img.height(), img.bpp(), img.fmt());
|
||||
void Texture::Load(ksr path) {
|
||||
Image img(path);
|
||||
Load(img.GetBuffer(), img.Width(), img.Height(), img.Bpp(), img.Fmt());
|
||||
}
|
||||
|
||||
void texture::load(const std::vector<uc>& pixels, int w, int h, int bpp,
|
||||
image::format fmt) {
|
||||
void Texture::Load(kvr<uc> pixels, int w, int h, int bpp, Image::Format fmt) {
|
||||
if (w > 1024 || h > 1024) {
|
||||
throw std::runtime_error("Max Texture Size is 1024x1024!");
|
||||
throw std::runtime_error("[amy] texture: Max Texture Size is 1024x1024!");
|
||||
}
|
||||
unload();
|
||||
Unload();
|
||||
|
||||
m_size.x = w;
|
||||
if (utils::isSingleBitNum(m_size.x)) {
|
||||
m_size.x = utils::nextPow2(m_size.x);
|
||||
pSize.x = w;
|
||||
if (!Utils::IsSingleBitNum(pSize.x)) {
|
||||
pSize.x = Utils::NextPow2(pSize.x);
|
||||
}
|
||||
m_size.y = h;
|
||||
if (utils::isSingleBitNum(m_size.y)) {
|
||||
m_size.y = utils::nextPow2(m_size.y);
|
||||
pSize.y = h;
|
||||
if (!Utils::IsSingleBitNum(pSize.y)) {
|
||||
pSize.y = Utils::NextPow2(pSize.y);
|
||||
}
|
||||
pUv = Amy::fvec4(0, 1.f, (float)w / (float)pSize.x,
|
||||
1.f - ((float)h / (float)pSize.y));
|
||||
auto filter = GPU_NEAREST;
|
||||
auto format = image2TexFmt(fmt);
|
||||
C3D_TexInit(&m_tex, (u16)m_size.x, (u16)m_size.y, format);
|
||||
C3D_TexSetFilter(&m_tex, filter, filter);
|
||||
auto Format = image2TexFmt(fmt);
|
||||
pTex = new C3D_Tex;
|
||||
C3D_TexInit(pTex, (u16)pSize.x, (u16)pSize.y, Format);
|
||||
C3D_TexSetFilter(pTex, filter, filter);
|
||||
// Using std::fill_n instead cause i hate this error lines
|
||||
// under the memset func in my editor
|
||||
std::fill_n((unsigned char*)m_tex.data, m_tex.size, 0);
|
||||
std::fill_n((uc*)pTex->data, pTex->size, 0);
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int dst_pos = tile3dsTex(x, y, m_size.x) * bpp;
|
||||
int dst_pos = tile3dsTex(x, y, pSize.x) * bpp;
|
||||
int src_pos = (y * w + x) * bpp;
|
||||
/// Best idea i had
|
||||
for (int i = 0; i < bpp; i++) {
|
||||
((u8*)m_tex.data)[dst_pos + bpp - 1 - i] = pixels[src_pos + i];
|
||||
((u8*)pTex->data)[dst_pos + bpp - 1 - i] = pixels[src_pos + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
C3D_TexFlush(&m_tex);
|
||||
m_tex.border = 0x00000000;
|
||||
C3D_TexSetWrap(&m_tex, GPU_REPEAT, GPU_REPEAT);
|
||||
m_loaded = true;
|
||||
C3D_TexFlush(pTex);
|
||||
pTex->border = 0x00000000;
|
||||
C3D_TexSetWrap(pTex, GPU_REPEAT, GPU_REPEAT);
|
||||
pLoaded = true;
|
||||
}
|
||||
|
||||
void texture::bind(int reg) { C3D_TexBind(reg, &m_tex); }
|
||||
} // namespace amy
|
||||
void Texture::Bind(int reg) { C3D_TexBind(reg, pTex); }
|
||||
} // namespace Amy
|
||||
+155
-21
@@ -1,17 +1,9 @@
|
||||
#include <amethyst/utils.hpp>
|
||||
#include <fstream>
|
||||
|
||||
namespace amy {
|
||||
namespace utils {
|
||||
ui fastHash(cstr& s) {
|
||||
ui hash = 5381;
|
||||
for (auto& it : s) {
|
||||
hash = (hash * 33) + static_cast<uc>(it);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
vec<uc> loadFile2Mem(cstr& path) {
|
||||
namespace Amy {
|
||||
namespace Utils {
|
||||
vec<uc> LoadFile2Mem(ksr path) {
|
||||
std::ifstream iff(path, std::ios::binary);
|
||||
if (!iff) {
|
||||
return vec<uc>();
|
||||
@@ -25,7 +17,23 @@ vec<uc> loadFile2Mem(cstr& path) {
|
||||
return res;
|
||||
}
|
||||
|
||||
ui hashMemory(cvec<uc>& data) {
|
||||
str FormatBytes(ull bytes) {
|
||||
static const vec<str> endings = {
|
||||
"B", "KB", "MB", "GB", "TB", "Unk",
|
||||
};
|
||||
int i = 0;
|
||||
double b = bytes;
|
||||
while (b > 1024) {
|
||||
i++;
|
||||
b /= 1024;
|
||||
}
|
||||
if (i >= (int)endings.size()) {
|
||||
i = (int)endings.size() - 1;
|
||||
}
|
||||
return std::format("{:.1f} {}", b, endings[i]);
|
||||
}
|
||||
|
||||
ui HashMemory(kvr<uc> data) {
|
||||
ui hash = 4477;
|
||||
for (auto& it : data) {
|
||||
hash = (hash * 33) + it;
|
||||
@@ -33,7 +41,7 @@ ui hashMemory(cvec<uc>& data) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
ui nextPow2(ui v) {
|
||||
ui NextPow2(ui v) {
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
@@ -44,10 +52,136 @@ ui nextPow2(ui v) {
|
||||
return (v >= 64 ? v : 64);
|
||||
}
|
||||
|
||||
bool isSingleBitNum(ui v) { return v && !(v & (v - 1)); }
|
||||
bool IsSingleBitNum(ui v) { return v && !(v & (v - 1)); }
|
||||
|
||||
namespace image {
|
||||
void reverseBuf(vec<uc>& buf, int w, int h, int c) {
|
||||
ull GetTimeNano() {
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::steady_clock::now().time_since_epoch())
|
||||
.count();
|
||||
}
|
||||
ull GetTimeMicro() {
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now().time_since_epoch())
|
||||
.count();
|
||||
}
|
||||
ull GetTimeMilli() {
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::steady_clock::now().time_since_epoch())
|
||||
.count();
|
||||
}
|
||||
|
||||
void String2U16(us* res, ksr src, size_t max) {
|
||||
/// GOT FORCED TO REPLACE std::wstring_convert by some
|
||||
/// manual work as it got removed in cxx20
|
||||
/// TODO ///
|
||||
/// ADD SOME ERROR API IN HERE
|
||||
if (max == 0) return;
|
||||
size_t len = 0;
|
||||
size_t i = 0;
|
||||
while (i < src.size() && len < max) {
|
||||
uc c = src[i];
|
||||
|
||||
if (c < 0x80) {
|
||||
// 1byte
|
||||
res[len++] = c;
|
||||
i++;
|
||||
} else if ((c >> 5) == 0x6) {
|
||||
// 2byte
|
||||
if (i + 1 >= src.size())
|
||||
throw std::invalid_argument("Invalid UTF-8 sequence");
|
||||
res[len++] = ((c & 0x1F) << 6) | (src[i + 1] & 0x3F);
|
||||
i += 2;
|
||||
} else if ((c >> 4) == 0xE) {
|
||||
// 3byte
|
||||
if (i + 2 >= src.size())
|
||||
throw std::invalid_argument("Invalid UTF-8 sequence");
|
||||
res[len++] =
|
||||
((c & 0x0F) << 12) | ((src[i + 1] & 0x3F) << 6) | (src[i + 2] & 0x3F);
|
||||
i += 3;
|
||||
} else if ((c >> 3) == 0x1E) {
|
||||
// 4byte
|
||||
if (i + 3 >= src.size())
|
||||
throw std::invalid_argument("Invalid UTF-8 sequence");
|
||||
ui codepoint = ((c & 0x07) << 18) | ((src[i + 1] & 0x3F) << 12) |
|
||||
((src[i + 2] & 0x3F) << 6) | (src[i + 3] & 0x3F);
|
||||
codepoint -= 0x10000;
|
||||
res[len++] = 0xD800 | ((codepoint >> 10) & 0x3FF);
|
||||
res[len++] = 0xDC00 | (codepoint & 0x3FF);
|
||||
i += 4;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string U16toU8(us* in, size_t max) {
|
||||
/// GOT FORCED TO REPLACE std::wstring_convert by some
|
||||
/// manual work as it got removed in cxx20
|
||||
if (!in || max == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string result;
|
||||
result.reserve(max * 3);
|
||||
|
||||
for (size_t i = 0; i < max; i++) {
|
||||
uint16_t c = in[i];
|
||||
|
||||
if (c < 0x80) {
|
||||
result.push_back(static_cast<char>(c));
|
||||
} else if (c < 0x800) {
|
||||
result.push_back(static_cast<char>(0xC0 | (c >> 6)));
|
||||
result.push_back(static_cast<char>(0x80 | (c & 0x3F)));
|
||||
} else if (c < 0x10000) {
|
||||
result.push_back(static_cast<char>(0xE0 | (c >> 12)));
|
||||
result.push_back(static_cast<char>(0x80 | ((c >> 6) & 0x3F)));
|
||||
result.push_back(static_cast<char>(0x80 | (c & 0x3F)));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
kstr FormatNanos(ull nanos) {
|
||||
// Based on some code of my minecraft plugins
|
||||
if (nanos < 1000) {
|
||||
return std::format("{}ns", nanos);
|
||||
} else if (nanos < 1000000) {
|
||||
ull micros = nanos / 1000;
|
||||
return std::format("{}us {}ns", micros, nanos % 1000);
|
||||
} else if (nanos < 1000000000) {
|
||||
ull millis = nanos / 1000000;
|
||||
return std::format("{}ms {}us", millis, (nanos % 1000000) / 1000);
|
||||
} else if (nanos < 60000000000ULL) {
|
||||
ull seconds = nanos / 1000000000;
|
||||
return std::format("{}s {}ms", seconds, (nanos % 1000000000) / 1000000);
|
||||
} else {
|
||||
ull minutes = nanos / 60000000000ULL;
|
||||
ull seconds = (nanos % 60000000000ULL) / 1000000000;
|
||||
return std::format("{}m {}s", minutes, seconds);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
kstr FormatMillis(ull millis) {
|
||||
// Original Code can be found in some of my mc plugins
|
||||
if (millis < 1000) {
|
||||
return std::format("{}ms", millis);
|
||||
} else if (millis < 60000) {
|
||||
ull seconds = millis / 1000;
|
||||
return std::format("{}s {}ms", seconds, (millis % 1000));
|
||||
} else {
|
||||
ull minutes = millis / 60000;
|
||||
ull seconds = (millis % 60000) / 1000;
|
||||
return std::format("{}m {}s {}ms", minutes, seconds, (millis % 1000));
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
namespace Image {
|
||||
void ReverseBuf(vec<uc>& buf, int w, int h, int c) {
|
||||
vec<uc> cpy = buf;
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
@@ -59,7 +193,7 @@ void reverseBuf(vec<uc>& buf, int w, int h, int c) {
|
||||
}
|
||||
}
|
||||
|
||||
void removeAlphaChannel(vec<uc>& buf, int w, int h) {
|
||||
void RemoveAlphaChannel(vec<uc>& buf, int w, int h) {
|
||||
vec<uc> cpy = buf;
|
||||
buf.resize(w * h * 3);
|
||||
for (int y = 0; y < h; y++) {
|
||||
@@ -73,7 +207,7 @@ void removeAlphaChannel(vec<uc>& buf, int w, int h) {
|
||||
}
|
||||
}
|
||||
|
||||
void addAlphaChannel(vec<uc>& buf, int w, int h) {
|
||||
void AddAlphaChannel(vec<uc>& buf, int w, int h) {
|
||||
vec<uc> cpy = buf;
|
||||
buf.resize(w * h * 4);
|
||||
for (int y = 0; y < h; y++) {
|
||||
@@ -87,6 +221,6 @@ void addAlphaChannel(vec<uc>& buf, int w, int h) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace image
|
||||
} // namespace utils
|
||||
} // namespace amy
|
||||
} // namespace Image
|
||||
} // namespace Utils
|
||||
} // namespace Amy
|
||||
Reference in New Issue
Block a user