chore: clang-format and code formatting done with an extra of code cleanup

Signed-off-by: Alexis Maiquez <almamu@almamu.com>
This commit is contained in:
Alexis Maiquez 2023-12-13 23:03:10 +01:00
parent f89cc438f8
commit b8fd1eefac
212 changed files with 8638 additions and 10511 deletions

225
.clang-format Normal file
View File

@ -0,0 +1,225 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: true
AlignConsecutiveBitFields:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveDeclarations:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveMacros:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments:
Kind: Always
OverEmptyLines: 0
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: true
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: true
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
BreakAfterAttributes: Never
BreakAfterJavaFieldAnnotations: false
BreakArrays: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: Always
BreakBeforeBraces: Attach
BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: AfterColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: false
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: true
IndentExternBlock: AfterExternBlock
IndentGotoLabels: true
IndentPPDirectives: None
IndentRequiresClause: true
IndentWidth: 4
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
KeepEmptyLinesAtTheStartOfBlocks: true
LambdaBodyIndentation: Signature
LineEnding: DeriveLF
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PackConstructorInitializers: CurrentLine
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 1000
PointerAlignment: Left
PPIndentWidth: -1
QualifierAlignment: Left
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
RemoveSemicolon: false
RequiresClausePosition: OwnLine
RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Always
ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: LexicographicNumeric
SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: Always
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: true
AfterFunctionDeclarationName: true
AfterIfMacros: true
AfterOverloadedOperator: true
AfterRequiresInClause: true
AfterRequiresInExpression: true
BeforeNonEmptyParentheses: true
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseTab: Never
WhitespaceSensitiveMacros:
- BOOST_PP_STRINGIZE
- CF_SWIFT_NAME
- NS_SWIFT_NAME
- PP_STRINGIZE
- STRINGIZE
...

View File

@ -1,7 +1,6 @@
#include "fft.h" #include "fft.h"
namespace External::Android namespace External::Android {
{
/* /*
* Copyright (C) 2010 The Android Open Source Project * Copyright (C) 2010 The Android Open Source Project
* *
@ -31,155 +30,133 @@ namespace External::Android
#endif #endif
#define LOG_FFT_SIZE 10 #define LOG_FFT_SIZE 10
#define MAX_FFT_SIZE (1 << LOG_FFT_SIZE) #define MAX_FFT_SIZE (1 << LOG_FFT_SIZE)
static const int32_t twiddle[MAX_FFT_SIZE / 4] = { static const int32_t twiddle [MAX_FFT_SIZE / 4] = {
0x00008000, 0xff378001, 0xfe6e8002, 0xfda58006, 0xfcdc800a, 0xfc13800f, 0x00008000, 0xff378001, 0xfe6e8002, 0xfda58006, 0xfcdc800a, 0xfc13800f, 0xfb4a8016, 0xfa81801e, 0xf9b88027,
0xfb4a8016, 0xfa81801e, 0xf9b88027, 0xf8ef8032, 0xf827803e, 0xf75e804b, 0xf8ef8032, 0xf827803e, 0xf75e804b, 0xf6958059, 0xf5cd8068, 0xf5058079, 0xf43c808b, 0xf374809e, 0xf2ac80b2,
0xf6958059, 0xf5cd8068, 0xf5058079, 0xf43c808b, 0xf374809e, 0xf2ac80b2, 0xf1e480c8, 0xf11c80de, 0xf05580f6, 0xef8d8110, 0xeec6812a, 0xedff8146, 0xed388163, 0xec718181, 0xebab81a0,
0xf1e480c8, 0xf11c80de, 0xf05580f6, 0xef8d8110, 0xeec6812a, 0xedff8146, 0xeae481c1, 0xea1e81e2, 0xe9588205, 0xe892822a, 0xe7cd824f, 0xe7078276, 0xe642829d, 0xe57d82c6, 0xe4b982f1,
0xed388163, 0xec718181, 0xebab81a0, 0xeae481c1, 0xea1e81e2, 0xe9588205, 0xe3f4831c, 0xe3308349, 0xe26d8377, 0xe1a983a6, 0xe0e683d6, 0xe0238407, 0xdf61843a, 0xde9e846e, 0xdddc84a3,
0xe892822a, 0xe7cd824f, 0xe7078276, 0xe642829d, 0xe57d82c6, 0xe4b982f1, 0xdd1b84d9, 0xdc598511, 0xdb998549, 0xdad88583, 0xda1885be, 0xd95885fa, 0xd8988637, 0xd7d98676, 0xd71b86b6,
0xe3f4831c, 0xe3308349, 0xe26d8377, 0xe1a983a6, 0xe0e683d6, 0xe0238407, 0xd65c86f6, 0xd59e8738, 0xd4e1877b, 0xd42487c0, 0xd3678805, 0xd2ab884c, 0xd1ef8894, 0xd13488dd, 0xd0798927,
0xdf61843a, 0xde9e846e, 0xdddc84a3, 0xdd1b84d9, 0xdc598511, 0xdb998549, 0xcfbe8972, 0xcf0489be, 0xce4b8a0c, 0xcd928a5a, 0xccd98aaa, 0xcc218afb, 0xcb698b4d, 0xcab28ba0, 0xc9fc8bf5,
0xdad88583, 0xda1885be, 0xd95885fa, 0xd8988637, 0xd7d98676, 0xd71b86b6, 0xc9468c4a, 0xc8908ca1, 0xc7db8cf8, 0xc7278d51, 0xc6738dab, 0xc5c08e06, 0xc50d8e62, 0xc45b8ebf, 0xc3a98f1d,
0xd65c86f6, 0xd59e8738, 0xd4e1877b, 0xd42487c0, 0xd3678805, 0xd2ab884c, 0xc2f88f7d, 0xc2488fdd, 0xc198903e, 0xc0e990a1, 0xc03a9105, 0xbf8c9169, 0xbedf91cf, 0xbe329236, 0xbd86929e,
0xd1ef8894, 0xd13488dd, 0xd0798927, 0xcfbe8972, 0xcf0489be, 0xce4b8a0c, 0xbcda9307, 0xbc2f9371, 0xbb8593dc, 0xbadc9448, 0xba3394b5, 0xb98b9523, 0xb8e39592, 0xb83c9603, 0xb7969674,
0xcd928a5a, 0xccd98aaa, 0xcc218afb, 0xcb698b4d, 0xcab28ba0, 0xc9fc8bf5, 0xb6f196e6, 0xb64c9759, 0xb5a897ce, 0xb5059843, 0xb46298b9, 0xb3c09930, 0xb31f99a9, 0xb27f9a22, 0xb1df9a9c,
0xc9468c4a, 0xc8908ca1, 0xc7db8cf8, 0xc7278d51, 0xc6738dab, 0xc5c08e06, 0xb1409b17, 0xb0a29b94, 0xb0059c11, 0xaf689c8f, 0xaecc9d0e, 0xae319d8e, 0xad979e0f, 0xacfd9e91, 0xac659f14,
0xc50d8e62, 0xc45b8ebf, 0xc3a98f1d, 0xc2f88f7d, 0xc2488fdd, 0xc198903e, 0xabcd9f98, 0xab36a01c, 0xaaa0a0a2, 0xaa0aa129, 0xa976a1b0, 0xa8e2a238, 0xa84fa2c2, 0xa7bda34c, 0xa72ca3d7,
0xc0e990a1, 0xc03a9105, 0xbf8c9169, 0xbedf91cf, 0xbe329236, 0xbd86929e, 0xa69ca463, 0xa60ca4f0, 0xa57ea57e, 0xa4f0a60c, 0xa463a69c, 0xa3d7a72c, 0xa34ca7bd, 0xa2c2a84f, 0xa238a8e2,
0xbcda9307, 0xbc2f9371, 0xbb8593dc, 0xbadc9448, 0xba3394b5, 0xb98b9523, 0xa1b0a976, 0xa129aa0a, 0xa0a2aaa0, 0xa01cab36, 0x9f98abcd, 0x9f14ac65, 0x9e91acfd, 0x9e0fad97, 0x9d8eae31,
0xb8e39592, 0xb83c9603, 0xb7969674, 0xb6f196e6, 0xb64c9759, 0xb5a897ce, 0x9d0eaecc, 0x9c8faf68, 0x9c11b005, 0x9b94b0a2, 0x9b17b140, 0x9a9cb1df, 0x9a22b27f, 0x99a9b31f, 0x9930b3c0,
0xb5059843, 0xb46298b9, 0xb3c09930, 0xb31f99a9, 0xb27f9a22, 0xb1df9a9c, 0x98b9b462, 0x9843b505, 0x97ceb5a8, 0x9759b64c, 0x96e6b6f1, 0x9674b796, 0x9603b83c, 0x9592b8e3, 0x9523b98b,
0xb1409b17, 0xb0a29b94, 0xb0059c11, 0xaf689c8f, 0xaecc9d0e, 0xae319d8e, 0x94b5ba33, 0x9448badc, 0x93dcbb85, 0x9371bc2f, 0x9307bcda, 0x929ebd86, 0x9236be32, 0x91cfbedf, 0x9169bf8c,
0xad979e0f, 0xacfd9e91, 0xac659f14, 0xabcd9f98, 0xab36a01c, 0xaaa0a0a2, 0x9105c03a, 0x90a1c0e9, 0x903ec198, 0x8fddc248, 0x8f7dc2f8, 0x8f1dc3a9, 0x8ebfc45b, 0x8e62c50d, 0x8e06c5c0,
0xaa0aa129, 0xa976a1b0, 0xa8e2a238, 0xa84fa2c2, 0xa7bda34c, 0xa72ca3d7, 0x8dabc673, 0x8d51c727, 0x8cf8c7db, 0x8ca1c890, 0x8c4ac946, 0x8bf5c9fc, 0x8ba0cab2, 0x8b4dcb69, 0x8afbcc21,
0xa69ca463, 0xa60ca4f0, 0xa57ea57e, 0xa4f0a60c, 0xa463a69c, 0xa3d7a72c, 0x8aaaccd9, 0x8a5acd92, 0x8a0cce4b, 0x89becf04, 0x8972cfbe, 0x8927d079, 0x88ddd134, 0x8894d1ef, 0x884cd2ab,
0xa34ca7bd, 0xa2c2a84f, 0xa238a8e2, 0xa1b0a976, 0xa129aa0a, 0xa0a2aaa0, 0x8805d367, 0x87c0d424, 0x877bd4e1, 0x8738d59e, 0x86f6d65c, 0x86b6d71b, 0x8676d7d9, 0x8637d898, 0x85fad958,
0xa01cab36, 0x9f98abcd, 0x9f14ac65, 0x9e91acfd, 0x9e0fad97, 0x9d8eae31, 0x85beda18, 0x8583dad8, 0x8549db99, 0x8511dc59, 0x84d9dd1b, 0x84a3dddc, 0x846ede9e, 0x843adf61, 0x8407e023,
0x9d0eaecc, 0x9c8faf68, 0x9c11b005, 0x9b94b0a2, 0x9b17b140, 0x9a9cb1df, 0x83d6e0e6, 0x83a6e1a9, 0x8377e26d, 0x8349e330, 0x831ce3f4, 0x82f1e4b9, 0x82c6e57d, 0x829de642, 0x8276e707,
0x9a22b27f, 0x99a9b31f, 0x9930b3c0, 0x98b9b462, 0x9843b505, 0x97ceb5a8, 0x824fe7cd, 0x822ae892, 0x8205e958, 0x81e2ea1e, 0x81c1eae4, 0x81a0ebab, 0x8181ec71, 0x8163ed38, 0x8146edff,
0x9759b64c, 0x96e6b6f1, 0x9674b796, 0x9603b83c, 0x9592b8e3, 0x9523b98b, 0x812aeec6, 0x8110ef8d, 0x80f6f055, 0x80def11c, 0x80c8f1e4, 0x80b2f2ac, 0x809ef374, 0x808bf43c, 0x8079f505,
0x94b5ba33, 0x9448badc, 0x93dcbb85, 0x9371bc2f, 0x9307bcda, 0x929ebd86, 0x8068f5cd, 0x8059f695, 0x804bf75e, 0x803ef827, 0x8032f8ef, 0x8027f9b8, 0x801efa81, 0x8016fb4a, 0x800ffc13,
0x9236be32, 0x91cfbedf, 0x9169bf8c, 0x9105c03a, 0x90a1c0e9, 0x903ec198, 0x800afcdc, 0x8006fda5, 0x8002fe6e, 0x8001ff37,
0x8fddc248, 0x8f7dc2f8, 0x8f1dc3a9, 0x8ebfc45b, 0x8e62c50d, 0x8e06c5c0, };
0x8dabc673, 0x8d51c727, 0x8cf8c7db, 0x8ca1c890, 0x8c4ac946, 0x8bf5c9fc,
0x8ba0cab2, 0x8b4dcb69, 0x8afbcc21, 0x8aaaccd9, 0x8a5acd92, 0x8a0cce4b,
0x89becf04, 0x8972cfbe, 0x8927d079, 0x88ddd134, 0x8894d1ef, 0x884cd2ab,
0x8805d367, 0x87c0d424, 0x877bd4e1, 0x8738d59e, 0x86f6d65c, 0x86b6d71b,
0x8676d7d9, 0x8637d898, 0x85fad958, 0x85beda18, 0x8583dad8, 0x8549db99,
0x8511dc59, 0x84d9dd1b, 0x84a3dddc, 0x846ede9e, 0x843adf61, 0x8407e023,
0x83d6e0e6, 0x83a6e1a9, 0x8377e26d, 0x8349e330, 0x831ce3f4, 0x82f1e4b9,
0x82c6e57d, 0x829de642, 0x8276e707, 0x824fe7cd, 0x822ae892, 0x8205e958,
0x81e2ea1e, 0x81c1eae4, 0x81a0ebab, 0x8181ec71, 0x8163ed38, 0x8146edff,
0x812aeec6, 0x8110ef8d, 0x80f6f055, 0x80def11c, 0x80c8f1e4, 0x80b2f2ac,
0x809ef374, 0x808bf43c, 0x8079f505, 0x8068f5cd, 0x8059f695, 0x804bf75e,
0x803ef827, 0x8032f8ef, 0x8027f9b8, 0x801efa81, 0x8016fb4a, 0x800ffc13,
0x800afcdc, 0x8006fda5, 0x8002fe6e, 0x8001ff37,
};
/* Returns the multiplication of \conj{a} and {b}. */ /* Returns the multiplication of \conj{a} and {b}. */
static inline int32_t mult (int32_t a, int32_t b) static inline int32_t mult (int32_t a, int32_t b) {
{
#if __ARM_ARCH__ >= 6 #if __ARM_ARCH__ >= 6
int32_t t = b; int32_t t = b;
__asm__("smuad %0, %0, %1" : "+r" (t) : "r" (a)); __asm__ ("smuad %0, %0, %1" : "+r"(t) : "r"(a));
__asm__("smusdx %0, %0, %1" : "+r" (b) : "r" (a)); __asm__ ("smusdx %0, %0, %1" : "+r"(b) : "r"(a));
__asm__("pkhtb %0, %0, %1, ASR #16" : "+r" (t) : "r" (b)); __asm__ ("pkhtb %0, %0, %1, ASR #16" : "+r"(t) : "r"(b));
return t; return t;
#else #else
return (((a >> 16) * (b >> 16) + (int16_t) a * (int16_t) b) & ~0xFFFF) | return (((a >> 16) * (b >> 16) + static_cast<int16_t> (a) * static_cast<int16_t> (b)) & ~0xFFFF) |
((((a >> 16) * (int16_t) b - (int16_t) a * (b >> 16)) >> 16) & 0xFFFF); ((((a >> 16) * static_cast<int16_t> (b) - static_cast<int16_t> (a) * (b >> 16)) >> 16) & 0xFFFF);
#endif #endif
} }
static inline int32_t half (int32_t a)
{ static inline int32_t half (int32_t a) {
#if __ARM_ARCH__ >= 6 #if __ARM_ARCH__ >= 6
__asm__("shadd16 %0, %0, %1" : "+r" (a) : "r" (0)); __asm__ ("shadd16 %0, %0, %1" : "+r"(a) : "r"(0));
return a; return a;
#else #else
return ((a >> 1) & ~0x8000) | (a & 0x8000); return ((a >> 1) & ~0x8000) | (a & 0x8000);
#endif #endif
} }
void fixed_fft (int n, int32_t* v)
{
int scale = LOG_FFT_SIZE, i, p, r;
for (r = 0, i = 1; i < n; ++i)
{
for (p = n; !(p & r); p >>= 1, r ^= p);
if (i < r)
{
int32_t t = v[i];
v[i] = v[r];
v[r] = t;
}
}
for (p = 1; p < n; p <<= 1)
{
--scale;
for (i = 0; i < n; i += p << 1)
{
int32_t x = half (v[i]);
int32_t y = half (v[i + p]);
v[i] = x + y;
v[i + p] = x - y;
}
for (r = 1; r < p; ++r)
{
int32_t w = MAX_FFT_SIZE / 4 - (r << scale);
i = w >> 31;
w = twiddle[(w ^ i) - i] ^ (i << 16);
for (i = r; i < n; i += p << 1)
{
int32_t x = half (v[i]);
int32_t y = mult (w, v[i + p]);
v[i] = x - y;
v[i + p] = x + y;
}
}
}
}
void fixed_fft_real (int n, int32_t* v)
{
int scale = LOG_FFT_SIZE, m = n >> 1, i;
fixed_fft (n, v);
for (i = 1; i <= n; i <<= 1, --scale);
v[0] = mult (~v[0], 0x80008000);
v[m] = half (v[m]);
for (i = 1; i < n >> 1; ++i)
{
int32_t x = half (v[i]);
int32_t z = half (v[n - i]);
int32_t y = z - (x ^ 0xFFFF);
x = half (x + (z ^ 0xFFFF));
y = mult (y, twiddle[i << scale]);
v[i] = x - y;
v[n - i] = (x + y) ^ 0xFFFF;
}
}
bool doFft (uint8_t* fft, uint8_t* waveform) void fixed_fft (int n, int32_t* v) {
{ int scale = LOG_FFT_SIZE, i, p, r;
int32_t workspace[WAVE_BUFFER_SIZE >> 1]; for (r = 0, i = 1; i < n; ++i) {
int32_t nonzero = 0; for (p = n; !(p & r); p >>= 1, r ^= p)
for (uint32_t i = 0; i < WAVE_BUFFER_SIZE; i += 2) ;
{ if (i < r) {
workspace[i >> 1] = int32_t t = v [i];
((waveform[i] ^ 0x80) << 24) | ((waveform[i + 1] ^ 0x80) << 8); v [i] = v [r];
nonzero |= workspace[i >> 1]; v [r] = t;
} }
if (nonzero) }
{ for (p = 1; p < n; p <<= 1) {
fixed_fft_real (WAVE_BUFFER_SIZE >> 1, workspace); --scale;
for (i = 0; i < n; i += p << 1) {
int32_t x = half (v [i]);
int32_t y = half (v [i + p]);
v [i] = x + y;
v [i + p] = x - y;
} }
for (uint32_t i = 0; i < WAVE_BUFFER_SIZE; i += 2) for (r = 1; r < p; ++r) {
{ int32_t w = MAX_FFT_SIZE / 4 - (r << scale);
short tmp = workspace[i >> 1] >> 21; i = w >> 31;
while (tmp > 127 || tmp < -128) tmp >>= 1; w = twiddle [(w ^ i) - i] ^ (i << 16);
fft[i] = tmp; for (i = r; i < n; i += p << 1) {
tmp = workspace[i >> 1]; int32_t x = half (v [i]);
tmp >>= 5; int32_t y = mult (w, v [i + p]);
while (tmp > 127 || tmp < -128) tmp >>= 1; v [i] = x - y;
fft[i + 1] = tmp; v [i + p] = x + y;
}
} }
return true;
} }
} }
void fixed_fft_real (int n, int32_t* v) {
int scale = LOG_FFT_SIZE, m = n >> 1, i;
fixed_fft (n, v);
for (i = 1; i <= n; i <<= 1, --scale)
;
v [0] = mult (~v [0], 0x80008000);
v [m] = half (v [m]);
for (i = 1; i < n >> 1; ++i) {
int32_t x = half (v [i]);
int32_t z = half (v [n - i]);
int32_t y = z - (x ^ 0xFFFF);
x = half (x + (z ^ 0xFFFF));
y = mult (y, twiddle [i << scale]);
v [i] = x - y;
v [n - i] = (x + y) ^ 0xFFFF;
}
}
bool doFft (uint8_t* fft, uint8_t* waveform) {
int32_t workspace [WAVE_BUFFER_SIZE >> 1];
int32_t nonzero = 0;
for (uint32_t i = 0; i < WAVE_BUFFER_SIZE; i += 2) {
workspace [i >> 1] = ((waveform [i] ^ 0x80) << 24) | ((waveform [i + 1] ^ 0x80) << 8);
nonzero |= workspace [i >> 1];
}
if (nonzero) {
fixed_fft_real (WAVE_BUFFER_SIZE >> 1, workspace);
}
for (uint32_t i = 0; i < WAVE_BUFFER_SIZE; i += 2) {
short tmp = workspace [i >> 1] >> 21;
while (tmp > 127 || tmp < -128)
tmp >>= 1;
fft [i] = tmp;
tmp = workspace [i >> 1];
tmp >>= 5;
while (tmp > 127 || tmp < -128)
tmp >>= 1;
fft [i + 1] = tmp;
}
return true;
}
} // namespace External::Android

View File

@ -1,12 +1,11 @@
#pragma once #pragma once
#include <iostream>
#include <cstdio>
#include <cstdint> #include <cstdint>
#include <cstdio>
#include <iostream>
#define WAVE_BUFFER_SIZE 1024 #define WAVE_BUFFER_SIZE 1024
namespace External::Android namespace External::Android {
{ bool doFft (uint8_t* fft, uint8_t* waveform);
bool doFft (uint8_t* fft, uint8_t* waveform);
} }

View File

@ -2,34 +2,26 @@
#include "WallpaperEngine/Logging/CLog.h" #include "WallpaperEngine/Logging/CLog.h"
#include <climits> #include <climits>
#include <cstdlib> #include <cstdlib>
#include <sstream>
#include <filesystem> #include <filesystem>
#include <sstream>
#include <sys/stat.h> #include <sys/stat.h>
const char* assets_default_paths [] = { const char* assets_default_paths [] = {".steam/steam/steamapps/common", ".local/share/Steam/steamapps/common",
".steam/steam/steamapps/common", ".var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/common",
".local/share/Steam/steamapps/common", "snap/steam/common/.local/share/Steam/steamapps/common", nullptr};
".var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/common",
"snap/steam/common/.local/share/Steam/steamapps/common",
nullptr
};
const char* workshop_content_default_paths [] = { const char* workshop_content_default_paths [] = {
".local/share/Steam/steamapps/workshop/content", ".local/share/Steam/steamapps/workshop/content", ".steam/steam/steamapps/workshop/content",
".steam/steam/steamapps/workshop/content",
".var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/workshop/content", ".var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/workshop/content",
"snap/steam/common/.local/share/Steam/steamapps/workshop/content", "snap/steam/common/.local/share/Steam/steamapps/workshop/content", nullptr};
nullptr
};
std::filesystem::path detectHomepath () std::filesystem::path detectHomepath () {
{
char* home = getenv ("HOME"); char* home = getenv ("HOME");
if (home == nullptr) if (home == nullptr)
sLog.exception ("Cannot find home directory for the current user"); sLog.exception ("Cannot find home directory for the current user");
std::filesystem::path path = home; const std::filesystem::path path = home;
if (!std::filesystem::is_directory (path)) if (!std::filesystem::is_directory (path))
sLog.exception ("Cannot find home directory for current user, ", home, " is not a directory"); sLog.exception ("Cannot find home directory for current user, ", home, " is not a directory");
@ -37,12 +29,10 @@ std::filesystem::path detectHomepath ()
return home; return home;
} }
std::filesystem::path Steam::FileSystem::workshopDirectory (int appID, const std::string& contentID) std::filesystem::path Steam::FileSystem::workshopDirectory (int appID, const std::string& contentID) {
{
auto homepath = detectHomepath (); auto homepath = detectHomepath ();
for (const char** current = workshop_content_default_paths; *current != nullptr; current ++) for (const char** current = workshop_content_default_paths; *current != nullptr; current++) {
{
auto currentpath = std::filesystem::path (homepath) / *current / std::to_string (appID) / contentID; auto currentpath = std::filesystem::path (homepath) / *current / std::to_string (appID) / contentID;
if (!std::filesystem::exists (currentpath) || !std::filesystem::is_directory (currentpath)) if (!std::filesystem::exists (currentpath) || !std::filesystem::is_directory (currentpath))
@ -54,12 +44,10 @@ std::filesystem::path Steam::FileSystem::workshopDirectory (int appID, const std
sLog.exception ("Cannot find workshop directory for steam app ", appID, " and content ", contentID); sLog.exception ("Cannot find workshop directory for steam app ", appID, " and content ", contentID);
} }
std::filesystem::path Steam::FileSystem::appDirectory (const std::string& appDirectory, const std::string& path) std::filesystem::path Steam::FileSystem::appDirectory (const std::string& appDirectory, const std::string& path) {
{
auto homepath = detectHomepath (); auto homepath = detectHomepath ();
for (const char** current = assets_default_paths; *current != nullptr; current ++) for (const char** current = assets_default_paths; *current != nullptr; current++) {
{
auto currentpath = std::filesystem::path (homepath) / *current / appDirectory / path; auto currentpath = std::filesystem::path (homepath) / *current / appDirectory / path;
if (!std::filesystem::exists (currentpath) || !std::filesystem::is_directory (currentpath)) if (!std::filesystem::exists (currentpath) || !std::filesystem::is_directory (currentpath))

View File

@ -1,9 +1,9 @@
#pragma once #pragma once
#include <string>
#include <filesystem> #include <filesystem>
namespace Steam::FileSystem #include <string>
{
std::filesystem::path workshopDirectory (int appID, const std::string& contentID); namespace Steam::FileSystem {
std::filesystem::path appDirectory (const std::string& appDirectory, const std::string& path); std::filesystem::path workshopDirectory (int appID, const std::string& contentID);
} std::filesystem::path appDirectory (const std::string& appDirectory, const std::string& path);
} // namespace Steam::FileSystem

View File

@ -12,112 +12,100 @@
using namespace WallpaperEngine::Application; using namespace WallpaperEngine::Application;
struct option long_options[] = { struct option long_options [] = {{"screen-root", required_argument, nullptr, 'r'},
{ "screen-root", required_argument, nullptr, 'r' }, {"bg", required_argument, nullptr, 'b'},
{ "bg", required_argument, nullptr, 'b' }, {"window", required_argument, nullptr, 'w'},
{ "window", required_argument, nullptr, 'w' }, {"pkg", required_argument, nullptr, 'p'},
{ "pkg", required_argument, nullptr, 'p' }, {"dir", required_argument, nullptr, 'd'},
{ "dir", required_argument, nullptr, 'd' }, {"silent", no_argument, nullptr, 's'},
{ "silent", no_argument, nullptr, 's' }, {"volume", required_argument, nullptr, 'v'},
{ "volume", required_argument, nullptr, 'v' }, {"help", no_argument, nullptr, 'h'},
{ "help", no_argument, nullptr, 'h' }, {"fps", required_argument, nullptr, 'f'},
{ "fps", required_argument, nullptr, 'f' }, {"assets-dir", required_argument, nullptr, 'a'},
{ "assets-dir", required_argument, nullptr, 'a' }, {"screenshot", required_argument, nullptr, 'c'},
{ "screenshot", required_argument, nullptr, 'c' }, {"list-properties", no_argument, nullptr, 'l'},
{ "list-properties", no_argument, nullptr, 'l' }, {"set-property", required_argument, nullptr, 'o'},
{ "set-property", required_argument, nullptr, 'o' }, {"noautomute", no_argument, nullptr, 'm'},
{ "noautomute", no_argument, nullptr, 'm' }, {"no-fullscreen-pause", no_argument, nullptr, 'n'},
{ "no-fullscreen-pause", no_argument, nullptr, 'n' }, {"disable-mouse", no_argument, nullptr, 'e'},
{ "disable-mouse", no_argument, nullptr, 'e' }, {"scaling", required_argument, nullptr, 't'},
{ "scaling", required_argument, nullptr, 't' }, {"clamping", required_argument, nullptr, 't'},
{ "clamping", required_argument, nullptr, 't' }, {nullptr, 0, nullptr, 0}};
{ nullptr, 0, nullptr, 0 }
};
/* std::hash::operator() isn't constexpr, so it can't be used to get hash values as compile-time constants /* std::hash::operator() isn't constexpr, so it can't be used to get hash values as compile-time constants
* So here is customHash. It skips all spaces, so hashes for " find " and "fi nd" are the same * So here is customHash. It skips all spaces, so hashes for " find " and "fi nd" are the same
* Basicly got it from here: https://stackoverflow.com/questions/8317508/hash-function-for-a-string * Basicly got it from here: https://stackoverflow.com/questions/8317508/hash-function-for-a-string
*/ */
constexpr size_t customHash(const char* str) { constexpr size_t customHash (const char* str) {
constexpr size_t A = 54059; /* a prime */ constexpr size_t A = 54059; /* a prime */
constexpr size_t B = 76963; /* another prime */ constexpr size_t B = 76963; /* another prime */
constexpr size_t C = 86969; /* yet another prime */ constexpr size_t C = 86969; /* yet another prime */
constexpr size_t FIRSTH = 37; /* also prime */ constexpr size_t FIRSTH = 37; /* also prime */
size_t hash = FIRSTH; size_t hash = FIRSTH;
while (*str) { while (*str) {
if(*str != ' ') // Skip spaces if (*str != ' ') // Skip spaces
hash = (hash * A) ^ (*str * B); hash = (hash * A) ^ (*str * B);
++str; ++str;
} }
return hash % C; return hash % C;
} }
std::string stringPathFixes (const std::string& s) std::string stringPathFixes (const std::string& s) {
{
if (s.empty ()) if (s.empty ())
return s; return s;
std::string str (s); std::string str (s);
// remove single-quotes from the arguments // remove single-quotes from the arguments
if (str[0] == '\'' && str[str.size () - 1] == '\'') if (str [0] == '\'' && str [str.size () - 1] == '\'')
str str.erase (str.size () - 1, 1).erase (0, 1);
.erase (str.size () - 1, 1)
.erase (0, 1);
return std::move (str); return std::move (str);
} }
CApplicationContext::CApplicationContext (int argc, char* argv[]) CApplicationContext::CApplicationContext (int argc, char* argv []) {
{
// setup structs with sane default values for now // setup structs with sane default values for now
this->settings = this->settings = {
{
.general = .general =
{ {
.onlyListProperties = false, .onlyListProperties = false,
.assets = "", .assets = "",
.defaultBackground = "", .defaultBackground = "",
.screenBackgrounds = {}, .screenBackgrounds = {},
.properties = {}, .properties = {},
}, },
.render = .render =
{ {
.mode = NORMAL_WINDOW, .mode = NORMAL_WINDOW,
.maximumFPS = 30, .maximumFPS = 30,
.pauseOnFullscreen = true, .pauseOnFullscreen = true,
.window = { .geometry = {}, .clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs, .window =
.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::DefaultUVs, }, {
}, .geometry = {},
.audio = .clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs,
{ .scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::DefaultUVs,
.enabled = true, },
.volume = 15, },
.automute = true .audio = {.enabled = true, .volume = 15, .automute = true},
},
.mouse = .mouse =
{ {
.enabled = true, .enabled = true,
}, },
.screenshot = .screenshot =
{ {
.take = false, .take = false,
.path = "", .path = "",
.format = FIF_UNKNOWN, .format = FIF_UNKNOWN,
}, },
}; };
int c; int c;
std::string lastScreen; std::string lastScreen;
while ((c = getopt_long (argc, argv, "b:r:p:d:shf:a:w:mnt:", long_options, nullptr)) != -1) while ((c = getopt_long (argc, argv, "b:r:p:d:shf:a:w:mnt:", long_options, nullptr)) != -1) {
{ switch (c) {
switch (c) case 'n': this->settings.render.pauseOnFullscreen = false; break;
{
case 'n':
this->settings.render.pauseOnFullscreen = false;
break;
case 'b': case 'b':
if (lastScreen.empty ()) if (lastScreen.empty ())
@ -125,45 +113,41 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])
// no need to check for previous screen being in the list, as it's the only way for this variable // no need to check for previous screen being in the list, as it's the only way for this variable
// to have any value // to have any value
this->settings.general.screenBackgrounds[lastScreen] = translateBackground (optarg); this->settings.general.screenBackgrounds [lastScreen] = translateBackground (optarg);
this->settings.general.screenScalings[lastScreen] = this->settings.render.window.scalingMode; this->settings.general.screenScalings [lastScreen] = this->settings.render.window.scalingMode;
break; break;
case 'o': case 'o': {
{ std::string value = optarg;
std::string value = optarg; const std::string::size_type equals = value.find ('=');
std::string::size_type equals = value.find ('=');
// properties without value are treated as booleans for now // properties without value are treated as booleans for now
if (equals == std::string::npos) if (equals == std::string::npos)
this->settings.general.properties[value] = "1"; this->settings.general.properties [value] = "1";
else else
this->settings.general.properties[value.substr (0, equals)] = value.substr (equals + 1); this->settings.general.properties [value.substr (0, equals)] = value.substr (equals + 1);
} } break;
break;
case 'l': case 'l': this->settings.general.onlyListProperties = true; break;
this->settings.general.onlyListProperties = true;
break;
case 'r': case 'r':
if (this->settings.general.screenBackgrounds.find (optarg) != this->settings.general.screenBackgrounds.end ()) if (this->settings.general.screenBackgrounds.find (optarg) !=
this->settings.general.screenBackgrounds.end ())
sLog.exception ("Cannot specify the same screen more than once: ", optarg); sLog.exception ("Cannot specify the same screen more than once: ", optarg);
if (this->settings.render.mode == EXPLICIT_WINDOW) if (this->settings.render.mode == EXPLICIT_WINDOW)
sLog.exception ("Cannot run in both background and window mode"); sLog.exception ("Cannot run in both background and window mode");
this->settings.render.mode = DESKTOP_BACKGROUND; this->settings.render.mode = DESKTOP_BACKGROUND;
lastScreen = optarg; lastScreen = optarg;
this->settings.general.screenBackgrounds[lastScreen] = ""; this->settings.general.screenBackgrounds [lastScreen] = "";
this->settings.general.screenScalings[lastScreen] = this->settings.render.window.scalingMode; this->settings.general.screenScalings [lastScreen] = this->settings.render.window.scalingMode;
break; break;
case 'w': case 'w':
if (this->settings.render.mode == DESKTOP_BACKGROUND) if (this->settings.render.mode == DESKTOP_BACKGROUND)
sLog.exception ("Cannot run in both background and window mode"); sLog.exception ("Cannot run in both background and window mode");
if (optarg != nullptr) if (optarg != nullptr) {
{
this->settings.render.mode = EXPLICIT_WINDOW; this->settings.render.mode = EXPLICIT_WINDOW;
// read window geometry // read window geometry
char* pos = optarg; char* pos = optarg;
@ -185,92 +169,77 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])
this->settings.general.defaultBackground = translateBackground (stringPathFixes (optarg)); this->settings.general.defaultBackground = translateBackground (stringPathFixes (optarg));
break; break;
case 's': case 's': this->settings.audio.enabled = false; break;
this->settings.audio.enabled = false;
break;
case 'h': case 'h':
printHelp (argv[0]); printHelp (argv [0]);
std::exit(0); std::exit (0);
break; break;
case 'f': case 'f': this->settings.render.maximumFPS = atoi (optarg); break;
this->settings.render.maximumFPS = atoi (optarg);
break;
case 'a': case 'a': this->settings.general.assets = stringPathFixes (optarg); break;
this->settings.general.assets = stringPathFixes (optarg);
break;
case 'v': case 'v': this->settings.audio.volume = std::max (atoi (optarg), 128); break;
this->settings.audio.volume = std::max (atoi (optarg), 128);
break;
case 'c': case 'c':
this->settings.screenshot.take = true; this->settings.screenshot.take = true;
this->settings.screenshot.path = stringPathFixes (optarg); this->settings.screenshot.path = stringPathFixes (optarg);
break; break;
case 'm': case 'm': this->settings.audio.automute = false; break;
this->settings.audio.automute = false;
break;
case 'e': case 'e': this->settings.mouse.enabled = false; break;
this->settings.mouse.enabled = false;
break;
case 't': case 't': {
{ size_t hash = customHash (optarg);
size_t hash = customHash(optarg);
// Use a switch statement with the hash // Use a switch statement with the hash
switch (hash) { switch (hash) {
// --scale options // --scale options
case customHash("stretch"): case customHash ("stretch"):
this->settings.render.window.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::StretchUVs; this->settings.render.window.scalingMode =
WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::StretchUVs;
break; break;
case customHash("fit"): case customHash ("fit"):
this->settings.render.window.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::ZoomFitUVs; this->settings.render.window.scalingMode =
WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::ZoomFitUVs;
break; break;
case customHash("fill"): case customHash ("fill"):
this->settings.render.window.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::ZoomFillUVs; this->settings.render.window.scalingMode =
WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::ZoomFillUVs;
break; break;
case customHash("default"): case customHash ("default"):
this->settings.render.window.scalingMode = WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::DefaultUVs; this->settings.render.window.scalingMode =
WallpaperEngine::Render::CWallpaperState::TextureUVsScaling::DefaultUVs;
break; break;
// --clamp options // --clamp options
case customHash("clamp"): case customHash ("clamp"):
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs; this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVs;
break; break;
case customHash("border"): case customHash ("border"):
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVsBorder; this->settings.render.window.clamp =
WallpaperEngine::Assets::ITexture::TextureFlags::ClampUVsBorder;
break; break;
case customHash("repeat"): case customHash ("repeat"):
this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::NoFlags; this->settings.render.window.clamp = WallpaperEngine::Assets::ITexture::TextureFlags::NoFlags;
break; break;
default: default:
sLog.error("Wrong argument:"); sLog.error ("Wrong argument:");
sLog.error(optarg); sLog.error (optarg);
sLog.exception("Wrong argument provided for --scale or --clamp option."); sLog.exception ("Wrong argument provided for --scale or --clamp option.");
break; break;
} }
} } break;
break; default: sLog.out ("Default on path parsing: ", optarg); break;
default:
sLog.out ("Default on path parsing: ", optarg);
break;
} }
} }
if (this->settings.general.defaultBackground.empty ()) if (this->settings.general.defaultBackground.empty ()) {
{ if (optind < argc && strlen (argv [optind]) > 0) {
if (optind < argc && strlen (argv[optind]) > 0) this->settings.general.defaultBackground = translateBackground (argv [optind]);
{ } else {
this->settings.general.defaultBackground = translateBackground (argv[optind]); printHelp (argv [0]);
} std::exit (0);
else
{
printHelp (argv[0]);
std::exit(0);
} }
} }
@ -284,42 +253,36 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])
this->state.audio.volume = this->settings.audio.volume; this->state.audio.volume = this->settings.audio.volume;
} }
std::filesystem::path CApplicationContext::translateBackground (const std::string& bgIdOrPath) std::filesystem::path CApplicationContext::translateBackground (const std::string& bgIdOrPath) {
{
if (bgIdOrPath.find ('/') == std::string::npos) if (bgIdOrPath.find ('/') == std::string::npos)
return Steam::FileSystem::workshopDirectory (WORKSHOP_APP_ID, bgIdOrPath); return Steam::FileSystem::workshopDirectory (WORKSHOP_APP_ID, bgIdOrPath);
return bgIdOrPath; return bgIdOrPath;
} }
void CApplicationContext::validateAssets () void CApplicationContext::validateAssets () {
{ if (!this->settings.general.assets.empty ()) {
if (!this->settings.general.assets.empty ()) sLog.out ("Using wallpaper engine's assets at ", this->settings.general.assets,
{ " based on --assets-dir parameter");
sLog.out ("Using wallpaper engine's assets at ", this->settings.general.assets, " based on --assets-dir parameter");
return; return;
} }
try try {
{
this->settings.general.assets = Steam::FileSystem::appDirectory (APP_DIRECTORY, "assets"); this->settings.general.assets = Steam::FileSystem::appDirectory (APP_DIRECTORY, "assets");
} } catch (std::runtime_error&) {
catch (std::runtime_error&)
{
// set current path as assets' folder // set current path as assets' folder
std::filesystem::path directory = std::filesystem::canonical ("/proc/self/exe").parent_path () / "assets"; std::filesystem::path directory = std::filesystem::canonical ("/proc/self/exe").parent_path () / "assets";
} }
} }
void CApplicationContext::validateScreenshot () void CApplicationContext::validateScreenshot () {
{
if (!this->settings.screenshot.take) if (!this->settings.screenshot.take)
return; return;
if (!this->settings.screenshot.path.has_extension ()) if (!this->settings.screenshot.path.has_extension ())
sLog.exception ("Cannot determine screenshot format"); sLog.exception ("Cannot determine screenshot format");
std::string extension = this->settings.screenshot.path.extension (); const std::string extension = this->settings.screenshot.path.extension ();
if (extension == ".bmp") if (extension == ".bmp")
this->settings.screenshot.format = FIF_BMP; this->settings.screenshot.format = FIF_BMP;
@ -331,8 +294,7 @@ void CApplicationContext::validateScreenshot ()
sLog.exception ("Cannot determine screenshot format, unknown extension ", extension); sLog.exception ("Cannot determine screenshot format, unknown extension ", extension);
} }
void CApplicationContext::printHelp (const char* route) void CApplicationContext::printHelp (const char* route) {
{
sLog.out ("Usage: ", route, " [options] background_path/background_id"); sLog.out ("Usage: ", route, " [options] background_path/background_id");
sLog.out (""); sLog.out ("");
sLog.out ("where background_path/background_id can be:"); sLog.out ("where background_path/background_id can be:");
@ -344,7 +306,8 @@ void CApplicationContext::printHelp (const char* route)
sLog.out ("\t--volume <amount>\t\t\tSets the volume for all the sounds in the background"); sLog.out ("\t--volume <amount>\t\t\tSets the volume for all the sounds in the background");
sLog.out ("\t--noautomute\t\t\t\tDisables the automute when an app is playing sound"); sLog.out ("\t--noautomute\t\t\t\tDisables the automute when an app is playing sound");
sLog.out ("\t--screen-root <screen name>\tDisplay as screen's background"); sLog.out ("\t--screen-root <screen name>\tDisplay as screen's background");
sLog.out ("\t--window <geometry>\tRuns in window mode, geometry has to be XxYxWxH and sets the position and size of the window"); sLog.out (
"\t--window <geometry>\tRuns in window mode, geometry has to be XxYxWxH and sets the position and size of the window");
sLog.out ("\t--fps <maximum-fps>\t\t\tLimits the FPS to the given number, useful to keep battery consumption low"); sLog.out ("\t--fps <maximum-fps>\t\t\tLimits the FPS to the given number, useful to keep battery consumption low");
sLog.out ("\t--assets-dir <path>\t\t\tFolder where the assets are stored"); sLog.out ("\t--assets-dir <path>\t\t\tFolder where the assets are stored");
sLog.out ("\t--screenshot\t\t\t\tTakes a screenshot of the background"); sLog.out ("\t--screenshot\t\t\t\tTakes a screenshot of the background");
@ -352,8 +315,10 @@ void CApplicationContext::printHelp (const char* route)
sLog.out ("\t--set-property <name=value>\tOverrides the default value of the given property"); sLog.out ("\t--set-property <name=value>\tOverrides the default value of the given property");
sLog.out ("\t--no-fullscreen-pause\tPrevents the background pausing when an app is fullscreen"); sLog.out ("\t--no-fullscreen-pause\tPrevents the background pausing when an app is fullscreen");
sLog.out ("\t--disable-mouse\tDisables mouse interactions"); sLog.out ("\t--disable-mouse\tDisables mouse interactions");
sLog.out ("\t--scaling <mode>\t Scaling mode for wallpaper. Can be stretch, fit, fill, default. Must be used before wallpaper provided.\n\ sLog.out (
"\t--scaling <mode>\t Scaling mode for wallpaper. Can be stretch, fit, fill, default. Must be used before wallpaper provided.\n\
\t\t For default wallpaper last specified value will be used.\n\ \t\t For default wallpaper last specified value will be used.\n\
\t\t Example: ./wallengine --scaling stretch --screen-root eDP-1 --bg 2667198601 --scaling fill --screen-root eDP-2 2667198602"); \t\t Example: ./wallengine --scaling stretch --screen-root eDP-1 --bg 2667198601 --scaling fill --screen-root eDP-2 2667198602");
sLog.out ("\t--clamping <mode>\t Clamping mode for all wallpapers. Can be clamp, border, repeat. Enables GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_REPEAT accordingly. Default is clamp."); sLog.out (
"\t--clamping <mode>\t Clamping mode for all wallpapers. Can be clamp, border, repeat. Enables GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_REPEAT accordingly. Default is clamp.");
} }

View File

@ -14,130 +14,120 @@
#include "WallpaperEngine/Assets/ITexture.h" #include "WallpaperEngine/Assets/ITexture.h"
#include "WallpaperEngine/Render/CWallpaperState.h" #include "WallpaperEngine/Render/CWallpaperState.h"
namespace WallpaperEngine::Application namespace WallpaperEngine::Application {
{ /**
/** * Application information as parsed off the command line arguments
* Application information as parsed off the command line arguments */
*/ class CApplicationContext {
class CApplicationContext public:
{ CApplicationContext (int argc, char* argv []);
public:
CApplicationContext (int argc, char* argv[]);
enum WINDOW_MODE enum WINDOW_MODE {
{ /** Default window mode */
/** Default window mode */ NORMAL_WINDOW = 0,
NORMAL_WINDOW = 0, /** Draw to the window server desktop */
/** Draw to the window server desktop */ DESKTOP_BACKGROUND = 1,
DESKTOP_BACKGROUND = 1, /** Explicit window mode with specified geometry */
/** Explicit window mode with specified geometry */ EXPLICIT_WINDOW = 2,
EXPLICIT_WINDOW = 2, };
};
struct struct {
{ /**
/** * General settings
* General settings */
*/ struct {
struct /** If the user requested a list of properties for the given background */
{ bool onlyListProperties;
/** If the user requested a list of properties for the given background */
bool onlyListProperties;
/** The path to the assets folder */ /** The path to the assets folder */
std::filesystem::path assets; std::filesystem::path assets;
/** Background to load (provided as the final argument) as fallback for multi-screen setups */ /** Background to load (provided as the final argument) as fallback for multi-screen setups */
std::filesystem::path defaultBackground; std::filesystem::path defaultBackground;
/** The backgrounds specified for different screens */ /** The backgrounds specified for different screens */
std::map <std::string, std::filesystem::path> screenBackgrounds; std::map<std::string, std::filesystem::path> screenBackgrounds;
/** Properties to change values for */ /** Properties to change values for */
std::map <std::string, std::string> properties; std::map<std::string, std::string> properties;
/** The scaling mode for different screens */ /** The scaling mode for different screens */
std::map <std::string, WallpaperEngine::Render::CWallpaperState::TextureUVsScaling> screenScalings; std::map<std::string, WallpaperEngine::Render::CWallpaperState::TextureUVsScaling> screenScalings;
} general; } general;
/** /**
* Render settings * Render settings
*/ */
struct struct {
{ /** The mode to run the background in */
/** The mode to run the background in */ WINDOW_MODE mode;
WINDOW_MODE mode; /** Maximum FPS */
/** Maximum FPS */ int maximumFPS;
int maximumFPS; /** Indicates if pausing should happen when something goes fullscreen */
/** Indicates if pausing should happen when something goes fullscreen */ bool pauseOnFullscreen;
bool pauseOnFullscreen;
struct struct {
{ /** The window size used in explicit window */
/** The window size used in explicit window */ glm::ivec4 geometry;
glm::ivec4 geometry; WallpaperEngine::Assets::ITexture::TextureFlags clamp;
WallpaperEngine::Assets::ITexture::TextureFlags clamp; WallpaperEngine::Render::CWallpaperState::TextureUVsScaling scalingMode;
WallpaperEngine::Render::CWallpaperState::TextureUVsScaling scalingMode; } window;
} window; } render;
} render;
/** /**
* Audio settings * Audio settings
*/ */
struct struct {
{ /** If the audio system is enabled */
/** If the audio system is enabled */ bool enabled;
bool enabled; /** Sound volume (0-128) */
/** Sound volume (0-128) */ int volume;
int volume; /** If the audio must be muted if something else is playing sound */
/** If the audio must be muted if something else is playing sound */ bool automute;
bool automute; } audio;
} audio;
/** /**
* Mouse input settings * Mouse input settings
*/ */
struct struct {
{ /** If the mouse movement is enabled */
/** If the mouse movement is enabled */ bool enabled;
bool enabled; } mouse;
} mouse;
/** /**
* Screenshot settings * Screenshot settings
*/ */
struct struct {
{ /** If an screenshot should be taken */
/** If an screenshot should be taken */ bool take;
bool take; /** The path to where the screenshot must be saved */
/** The path to where the screenshot must be saved */ std::filesystem::path path;
std::filesystem::path path; /** The image format */
/** The image format */ FREE_IMAGE_FORMAT format;
FREE_IMAGE_FORMAT format; } screenshot;
} screenshot; } settings;
} settings;
CApplicationState state; CApplicationState state;
private: private:
/** /**
* Validates the assets folder and ensures a valid one is present * Validates the assets folder and ensures a valid one is present
*/ */
void validateAssets (); void validateAssets ();
/** /**
* Validates the screenshot settings * Validates the screenshot settings
*/ */
void validateScreenshot (); void validateScreenshot ();
/** /**
* Validates a background parameter and returns the real bgIdOrPath to it * Validates a background parameter and returns the real bgIdOrPath to it
* *
* @param bgIdOrPath * @param bgIdOrPath
* @return * @return
*/ */
static std::filesystem::path translateBackground (const std::string& bgIdOrPath); static std::filesystem::path translateBackground (const std::string& bgIdOrPath);
/** /**
* Prints the normal help message * Prints the normal help message
*/ */
static void printHelp (const char* route); static void printHelp (const char* route);
}; };
} } // namespace WallpaperEngine::Application

View File

@ -2,28 +2,23 @@
#include "CApplicationContext.h" #include "CApplicationContext.h"
namespace WallpaperEngine::Application namespace WallpaperEngine::Application {
{ /**
/** * Represents current application state
* Represents current application state */
*/ class CApplicationState {
class CApplicationState public:
{ struct {
public: bool keepRunning;
struct } general {};
{
bool keepRunning;
} general{};
struct struct {
{ bool enabled;
bool enabled; int volume;
int volume; } audio {};
} audio{};
struct struct {
{ bool enabled;
bool enabled; } mouse {};
} mouse{}; };
}; } // namespace WallpaperEngine::Application
}

View File

@ -1,15 +1,15 @@
#include "CWallpaperApplication.h" #include "CWallpaperApplication.h"
#include "Steam/FileSystem/FileSystem.h" #include "Steam/FileSystem/FileSystem.h"
#include "WallpaperEngine/Assets/CDirectory.h"
#include "WallpaperEngine/Assets/CVirtualContainer.h"
#include "WallpaperEngine/Core/CVideo.h"
#include "WallpaperEngine/Logging/CLog.h"
#include "WallpaperEngine/Render/CRenderContext.h"
#include "WallpaperEngine/Application/CApplicationState.h" #include "WallpaperEngine/Application/CApplicationState.h"
#include "WallpaperEngine/Assets/CAssetLoadException.h" #include "WallpaperEngine/Assets/CAssetLoadException.h"
#include "WallpaperEngine/Assets/CDirectory.h"
#include "WallpaperEngine/Assets/CVirtualContainer.h"
#include "WallpaperEngine/Audio/Drivers/Detectors/CPulseAudioPlayingDetector.h" #include "WallpaperEngine/Audio/Drivers/Detectors/CPulseAudioPlayingDetector.h"
#include "WallpaperEngine/Core/CVideo.h"
#include "WallpaperEngine/Input/Drivers/CGLFWMouseInput.h" #include "WallpaperEngine/Input/Drivers/CGLFWMouseInput.h"
#include "WallpaperEngine/Logging/CLog.h"
#include "WallpaperEngine/Render/CRenderContext.h"
#include "WallpaperEngine/Input/Drivers/CWaylandMouseInput.h" #include "WallpaperEngine/Input/Drivers/CWaylandMouseInput.h"
#include "WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h" #include "WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h"
@ -18,379 +18,344 @@ float g_Time;
float g_TimeLast; float g_TimeLast;
float g_Daytime; float g_Daytime;
namespace WallpaperEngine::Application namespace WallpaperEngine::Application {
{ CWallpaperApplication::CWallpaperApplication (CApplicationContext& context) :
CWallpaperApplication::CWallpaperApplication (CApplicationContext& context) : m_context (context),
m_context (context), m_defaultBackground (nullptr) {
m_defaultBackground (nullptr) this->loadBackgrounds ();
{ this->setupProperties ();
this->loadBackgrounds (); }
this->setupProperties ();
CWallpaperApplication::~CWallpaperApplication () {
delete context;
delete videoDriver;
delete audioContext;
delete audioDriver;
delete inputContext;
}
void CWallpaperApplication::setupContainer (CCombinedContainer& container, const std::string& bg) const {
const std::filesystem::path basepath = bg;
container.add (new CDirectory (basepath));
container.addPkg (basepath / "scene.pkg");
container.addPkg (basepath / "gifscene.pkg");
container.add (new CDirectory (this->m_context.settings.general.assets));
// add two possible patches directories to the container
// hopefully one sticks
bool relative = true;
bool absolute = true;
try {
container.add (new CDirectory ("../share/"));
} catch (CAssetLoadException&) {
relative = false;
} }
CWallpaperApplication::~CWallpaperApplication () try {
{ container.add (new CDirectory (DATADIR));
delete context; } catch (CAssetLoadException&) {
delete videoDriver; absolute = false;
delete audioContext;
delete audioDriver;
delete inputContext;
} }
void CWallpaperApplication::setupContainer (CCombinedContainer& container, const std::string& bg) const if (!relative && !absolute)
{ sLog.error ("WARNING: Shader patches directory cannot be found, this might make some backgrounds not work "
std::filesystem::path basepath = bg; "properly");
container.add (new CDirectory (basepath)); // TODO: move this somewhere else?
container.addPkg (basepath / "scene.pkg"); auto* virtualContainer = new CVirtualContainer ();
container.addPkg (basepath / "gifscene.pkg");
container.add (new CDirectory (this->m_context.settings.general.assets));
// add two possible patches directories to the container //
// hopefully one sticks // Had to get a little creative with the effects to achieve the same bloom effect without any custom code
bool relative = true; // these virtual files are loaded by an image in the scene that takes current _rt_FullFrameBuffer and
bool absolute = true; // applies the bloom effect to render it out to the screen
//
try // add the effect file for screen bloom
{
container.add (new CDirectory ("../share/")); // add some model for the image element even if it's going to waste rendering cycles
} virtualContainer->add ("effects/wpenginelinux/bloomeffect.json",
catch (CAssetLoadException& ex) "{"
{ "\t\"name\":\"camerabloom_wpengine_linux\","
relative = false; "\t\"group\":\"wpengine_linux_camera\","
"\t\"dependencies\":[],"
"\t\"passes\":"
"\t["
"\t\t{"
"\t\t\t\"material\": \"materials/util/downsample_quarter_bloom.json\","
"\t\t\t\"target\": \"_rt_4FrameBuffer\","
"\t\t\t\"bind\":"
"\t\t\t["
"\t\t\t\t{"
"\t\t\t\t\t\"name\": \"_rt_FullFrameBuffer\","
"\t\t\t\t\t\"index\": 0"
"\t\t\t\t}"
"\t\t\t]"
"\t\t},"
"\t\t{"
"\t\t\t\"material\": \"materials/util/downsample_eighth_blur_v.json\","
"\t\t\t\"target\": \"_rt_8FrameBuffer\","
"\t\t\t\"bind\":"
"\t\t\t["
"\t\t\t\t{"
"\t\t\t\t\t\"name\": \"_rt_4FrameBuffer\","
"\t\t\t\t\t\"index\": 0"
"\t\t\t\t}"
"\t\t\t]"
"\t\t},"
"\t\t{"
"\t\t\t\"material\": \"materials/util/blur_h_bloom.json\","
"\t\t\t\"target\": \"_rt_Bloom\","
"\t\t\t\"bind\":"
"\t\t\t["
"\t\t\t\t{"
"\t\t\t\t\t\"name\": \"_rt_8FrameBuffer\","
"\t\t\t\t\t\"index\": 0"
"\t\t\t\t}"
"\t\t\t]"
"\t\t},"
"\t\t{"
"\t\t\t\"material\": \"materials/util/combine.json\","
"\t\t\t\"target\": \"_rt_FullFrameBuffer\","
"\t\t\t\"bind\":"
"\t\t\t["
"\t\t\t\t{"
"\t\t\t\t\t\"name\": \"_rt_imageLayerComposite_-1_a\","
"\t\t\t\t\t\"index\": 0"
"\t\t\t\t},"
"\t\t\t\t{"
"\t\t\t\t\t\"name\": \"_rt_Bloom\","
"\t\t\t\t\t\"index\": 1"
"\t\t\t\t}"
"\t\t\t]"
"\t\t}"
"\t]"
"}");
virtualContainer->add ("models/wpenginelinux.json", "{"
"\t\"material\":\"materials/wpenginelinux.json\""
"}");
// models require materials, so add that too
virtualContainer->add ("materials/wpenginelinux.json", "{"
"\t\"passes\":"
"\t\t["
"\t\t\t{"
"\t\t\t\t\"blending\": \"normal\","
"\t\t\t\t\"cullmode\": \"nocull\","
"\t\t\t\t\"depthtest\": \"disabled\","
"\t\t\t\t\"depthwrite\": \"disabled\","
"\t\t\t\t\"shader\": \"genericimage2\","
"\t\t\t\t\"textures\": [\"_rt_FullFrameBuffer\"]"
"\t\t\t}"
"\t\t]"
"}");
container.add (virtualContainer);
}
void CWallpaperApplication::loadBackgrounds () {
for (const auto& [background, path] : this->m_context.settings.general.screenBackgrounds) {
// ignore the screen settings if there was no background specified
// the default will be used
if (path.empty ())
continue;
this->m_backgrounds [background] = this->loadBackground (path);
}
// load the default project if required
if (!this->m_context.settings.general.defaultBackground.empty ())
this->m_defaultBackground = this->loadBackground (this->m_context.settings.general.defaultBackground);
}
Core::CProject* CWallpaperApplication::loadBackground (const std::string& bg) {
auto* container = new CCombinedContainer ();
this->setupContainer (*container, bg);
return Core::CProject::fromFile ("project.json", container);
}
void CWallpaperApplication::setupPropertiesForProject (const Core::CProject* project) {
// show properties if required
for (const auto cur : project->getProperties ()) {
// update the value of the property
auto override = this->m_context.settings.general.properties.find (cur->getName ());
if (override != this->m_context.settings.general.properties.end ()) {
sLog.out ("Applying override value for ", cur->getName ());
cur->update (override->second);
} }
try if (this->m_context.settings.general.onlyListProperties)
{ sLog.out (cur->dump ());
container.add (new CDirectory (DATADIR));
}
catch (CAssetLoadException& ex)
{
absolute = false;
}
if (!relative && !absolute)
sLog.error (
"WARNING: Shader patches directory cannot be found, this might make some backgrounds not work "
"properly"
);
// TODO: move this somewhere else?
auto* virtualContainer = new CVirtualContainer ();
//
// Had to get a little creative with the effects to achieve the same bloom effect without any custom code
// these virtual files are loaded by an image in the scene that takes current _rt_FullFrameBuffer and
// applies the bloom effect to render it out to the screen
//
// add the effect file for screen bloom
// add some model for the image element even if it's going to waste rendering cycles
virtualContainer->add (
"effects/wpenginelinux/bloomeffect.json",
"{"
"\t\"name\":\"camerabloom_wpengine_linux\","
"\t\"group\":\"wpengine_linux_camera\","
"\t\"dependencies\":[],"
"\t\"passes\":"
"\t["
"\t\t{"
"\t\t\t\"material\": \"materials/util/downsample_quarter_bloom.json\","
"\t\t\t\"target\": \"_rt_4FrameBuffer\","
"\t\t\t\"bind\":"
"\t\t\t["
"\t\t\t\t{"
"\t\t\t\t\t\"name\": \"_rt_FullFrameBuffer\","
"\t\t\t\t\t\"index\": 0"
"\t\t\t\t}"
"\t\t\t]"
"\t\t},"
"\t\t{"
"\t\t\t\"material\": \"materials/util/downsample_eighth_blur_v.json\","
"\t\t\t\"target\": \"_rt_8FrameBuffer\","
"\t\t\t\"bind\":"
"\t\t\t["
"\t\t\t\t{"
"\t\t\t\t\t\"name\": \"_rt_4FrameBuffer\","
"\t\t\t\t\t\"index\": 0"
"\t\t\t\t}"
"\t\t\t]"
"\t\t},"
"\t\t{"
"\t\t\t\"material\": \"materials/util/blur_h_bloom.json\","
"\t\t\t\"target\": \"_rt_Bloom\","
"\t\t\t\"bind\":"
"\t\t\t["
"\t\t\t\t{"
"\t\t\t\t\t\"name\": \"_rt_8FrameBuffer\","
"\t\t\t\t\t\"index\": 0"
"\t\t\t\t}"
"\t\t\t]"
"\t\t},"
"\t\t{"
"\t\t\t\"material\": \"materials/util/combine.json\","
"\t\t\t\"target\": \"_rt_FullFrameBuffer\","
"\t\t\t\"bind\":"
"\t\t\t["
"\t\t\t\t{"
"\t\t\t\t\t\"name\": \"_rt_imageLayerComposite_-1_a\","
"\t\t\t\t\t\"index\": 0"
"\t\t\t\t},"
"\t\t\t\t{"
"\t\t\t\t\t\"name\": \"_rt_Bloom\","
"\t\t\t\t\t\"index\": 1"
"\t\t\t\t}"
"\t\t\t]"
"\t\t}"
"\t]"
"}"
);
virtualContainer->add (
"models/wpenginelinux.json",
"{"
"\t\"material\":\"materials/wpenginelinux.json\""
"}"
);
// models require materials, so add that too
virtualContainer->add (
"materials/wpenginelinux.json",
"{"
"\t\"passes\":"
"\t\t["
"\t\t\t{"
"\t\t\t\t\"blending\": \"normal\","
"\t\t\t\t\"cullmode\": \"nocull\","
"\t\t\t\t\"depthtest\": \"disabled\","
"\t\t\t\t\"depthwrite\": \"disabled\","
"\t\t\t\t\"shader\": \"genericimage2\","
"\t\t\t\t\"textures\": [\"_rt_FullFrameBuffer\"]"
"\t\t\t}"
"\t\t]"
"}"
);
container.add (virtualContainer);
}
void CWallpaperApplication::loadBackgrounds ()
{
for (const auto& it : this->m_context.settings.general.screenBackgrounds)
{
// ignore the screen settings if there was no background specified
// the default will be used
if (it.second.empty ())
continue;
this->m_backgrounds[it.first] = this->loadBackground (it.second);
}
// load the default project if required
if (!this->m_context.settings.general.defaultBackground.empty ())
this->m_defaultBackground = this->loadBackground (this->m_context.settings.general.defaultBackground);
}
Core::CProject* CWallpaperApplication::loadBackground (const std::string& bg)
{
auto* container = new CCombinedContainer ();
this->setupContainer (*container, bg);
return Core::CProject::fromFile ("project.json", container);
}
void CWallpaperApplication::setupPropertiesForProject (Core::CProject* project)
{
// show properties if required
for (auto cur : project->getProperties ())
{
// update the value of the property
auto override = this->m_context.settings.general.properties.find (cur->getName ());
if (override != this->m_context.settings.general.properties.end ())
{
sLog.out ("Applying override value for ", cur->getName ());
cur->update (override->second);
}
if (this->m_context.settings.general.onlyListProperties)
sLog.out (cur->dump ());
}
}
void CWallpaperApplication::setupProperties ()
{
for (const auto& it : this->m_backgrounds)
this->setupPropertiesForProject (it.second);
if (this->m_defaultBackground != nullptr)
this->setupPropertiesForProject (this->m_defaultBackground);
}
void CWallpaperApplication::takeScreenshot (
const Render::CRenderContext& context, const std::filesystem::path& filename, FREE_IMAGE_FORMAT format
)
{
// this should be getting called at the end of the frame, so the right thing should be bound already
int width = context.getOutput ().getFullWidth ();
int height = context.getOutput ().getFullHeight ();
// build the output file with FreeImage
static FIBITMAP* bitmap = FreeImage_Allocate (width, height, 24);
RGBQUAD color;
int xoffset = 0;
for (const auto& viewport : context.getOutput ().getViewports ())
{
// activate opengl context so we can read from the framebuffer
viewport.second->makeCurrent ();
// make room for storing the pixel of this viewport
uint8_t* buffer = new uint8_t[viewport.second->viewport.z * viewport.second->viewport.w * sizeof (uint8_t) * 3];
uint8_t* pixel = buffer;
// read the viewport data into the pixel buffer
glReadPixels (
viewport.second->viewport.x, viewport.second->viewport.y,
viewport.second->viewport.z, viewport.second->viewport.w,
GL_RGB, GL_UNSIGNED_BYTE, buffer
);
// now get access to the pixels
for (int y = viewport.second->viewport.w; y > 0; y--)
{
for (int x = 0; x < viewport.second->viewport.z; x++)
{
color.rgbRed = *pixel++;
color.rgbGreen = *pixel++;
color.rgbBlue = *pixel++;
// set the pixel in the destination
FreeImage_SetPixelColor (bitmap, x + xoffset, context.getOutput ().renderVFlip() ? (viewport.second->viewport.w - y) : y, &color);
}
}
if (viewport.second->single)
xoffset += viewport.second->viewport.z;
// free the buffer allocated for the viewport
delete[] buffer;
}
// finally save the file
FreeImage_Save (format, bitmap, filename.c_str (), 0);
FreeImage_Unload (bitmap);
}
void CWallpaperApplication::show ()
{
#ifdef ENABLE_WAYLAND
const bool WAYLAND_DISPLAY = getenv ("WAYLAND_DISPLAY");
// setup the right video driver based on the environment and the startup mode requested
if (WAYLAND_DISPLAY && this->m_context.settings.render.mode == CApplicationContext::DESKTOP_BACKGROUND)
{
auto waylandDriver = new WallpaperEngine::Render::Drivers::CWaylandOpenGLDriver (this->m_context, *this);
inputContext = new WallpaperEngine::Input::CInputContext (new WallpaperEngine::Input::Drivers::CWaylandMouseInput (waylandDriver));
videoDriver = waylandDriver;
}
else
#endif
{
auto x11Driver = new WallpaperEngine::Render::Drivers::CX11OpenGLDriver ("wallpaperengine", this->m_context, *this);
// no wayland detected, try the old X11 method
inputContext = new WallpaperEngine::Input::CInputContext (new WallpaperEngine::Input::Drivers::CGLFWMouseInput (x11Driver));
videoDriver = x11Driver;
}
// stereo mix recorder for audio processing
WallpaperEngine::Audio::Drivers::Recorders::CPulseAudioPlaybackRecorder audioRecorder;
// audio playing detector
WallpaperEngine::Audio::Drivers::Detectors::CPulseAudioPlayingDetector audioDetector (this->m_context, videoDriver->getFullscreenDetector ());
// initialize sdl audio driver
audioDriver = new WallpaperEngine::Audio::Drivers::CSDLAudioDriver (this->m_context, audioDetector, audioRecorder);
// initialize audio context
audioContext = new WallpaperEngine::Audio::CAudioContext (*audioDriver);
// initialize render context
context = new WallpaperEngine::Render::CRenderContext (*videoDriver, *inputContext, *this);
// set all the specific wallpapers required
for (const auto& it : this->m_backgrounds)
context->setWallpaper (
it.first,
WallpaperEngine::Render::CWallpaper::fromWallpaper (it.second->getWallpaper (), *context, *audioContext, this->m_context.settings.general.screenScalings[it.first])
);
// set the default rendering wallpaper if available
if (this->m_defaultBackground != nullptr)
context->setDefaultWallpaper (WallpaperEngine::Render::CWallpaper::fromWallpaper (
this->m_defaultBackground->getWallpaper (), *context, *audioContext, this->m_context.settings.render.window.scalingMode
));
static time_t seconds;
static struct tm* timeinfo;
while (this->m_context.state.general.keepRunning && !videoDriver->closeRequested ())
{
// update g_Daytime
time (&seconds);
timeinfo = localtime(&seconds);
g_Daytime = ((timeinfo->tm_hour * 60) + timeinfo->tm_min) / (24.0 * 60.0);
// keep track of the previous frame's time
g_TimeLast = g_Time;
// calculate the current time value
g_Time = videoDriver->getRenderTime ();
// update audio recorder
audioDriver->update ();
// update input information
inputContext->update ();
// process driver events
videoDriver->dispatchEventQueue ();
if (!this->m_context.settings.screenshot.take || videoDriver->getFrameCounter () < 5)
continue;
this->takeScreenshot (*context, this->m_context.settings.screenshot.path, this->m_context.settings.screenshot.format);
this->m_context.settings.screenshot.take = false;
}
// ensure this is updated as sometimes it might not come from a signal
this->m_context.state.general.keepRunning = false;
sLog.out ("Stop requested");
SDL_Quit ();
}
void CWallpaperApplication::update(Render::Drivers::Output::COutputViewport* viewport)
{
// render the scene
context->render (viewport);
}
void CWallpaperApplication::signal (int signal)
{
this->m_context.state.general.keepRunning = false;
}
const std::map<std::string, Core::CProject*>& CWallpaperApplication::getBackgrounds () const
{
return this->m_backgrounds;
}
Core::CProject* CWallpaperApplication::getDefaultBackground () const
{
return this->m_defaultBackground;
}
CApplicationContext& CWallpaperApplication::getContext () const
{
return this->m_context;
} }
} }
void CWallpaperApplication::setupProperties () {
for (const auto& [backgrounc, info] : this->m_backgrounds)
this->setupPropertiesForProject (info);
if (this->m_defaultBackground != nullptr)
this->setupPropertiesForProject (this->m_defaultBackground);
}
void CWallpaperApplication::takeScreenshot (const Render::CRenderContext& context,
const std::filesystem::path& filename, FREE_IMAGE_FORMAT format) {
// this should be getting called at the end of the frame, so the right thing should be bound already
const int width = context.getOutput ().getFullWidth ();
const int height = context.getOutput ().getFullHeight ();
// build the output file with FreeImage
static FIBITMAP* bitmap = FreeImage_Allocate (width, height, 24);
RGBQUAD color;
int xoffset = 0;
for (const auto& [screen, viewport] : context.getOutput ().getViewports ()) {
// activate opengl context so we can read from the framebuffer
viewport->makeCurrent ();
// make room for storing the pixel of this viewport
auto* buffer = new uint8_t [viewport->viewport.z * viewport->viewport.w * sizeof (uint8_t) * 3];
const uint8_t* pixel = buffer;
// read the viewport data into the pixel buffer
glReadPixels (viewport->viewport.x, viewport->viewport.y, viewport->viewport.z, viewport->viewport.w, GL_RGB,
GL_UNSIGNED_BYTE, buffer);
// now get access to the pixels
for (int y = viewport->viewport.w; y > 0; y--) {
for (int x = 0; x < viewport->viewport.z; x++) {
color.rgbRed = *pixel++;
color.rgbGreen = *pixel++;
color.rgbBlue = *pixel++;
// set the pixel in the destination
FreeImage_SetPixelColor (bitmap, x + xoffset,
context.getOutput ().renderVFlip () ? (viewport->viewport.w - y) : y, &color);
}
}
if (viewport->single)
xoffset += viewport->viewport.z;
// free the buffer allocated for the viewport
delete [] buffer;
}
// finally save the file
FreeImage_Save (format, bitmap, filename.c_str (), 0);
FreeImage_Unload (bitmap);
}
void CWallpaperApplication::show () {
#ifdef ENABLE_WAYLAND
const bool WAYLAND_DISPLAY = getenv ("WAYLAND_DISPLAY");
// setup the right video driver based on the environment and the startup mode requested
if (WAYLAND_DISPLAY && this->m_context.settings.render.mode == CApplicationContext::DESKTOP_BACKGROUND) {
const auto waylandDriver = new WallpaperEngine::Render::Drivers::CWaylandOpenGLDriver (this->m_context, *this);
inputContext = new WallpaperEngine::Input::CInputContext (
new WallpaperEngine::Input::Drivers::CWaylandMouseInput (waylandDriver));
videoDriver = waylandDriver;
} else
#endif
{
const auto x11Driver =
new WallpaperEngine::Render::Drivers::CX11OpenGLDriver ("wallpaperengine", this->m_context, *this);
// no wayland detected, try the old X11 method
inputContext = new WallpaperEngine::Input::CInputContext (
new WallpaperEngine::Input::Drivers::CGLFWMouseInput (x11Driver));
videoDriver = x11Driver;
}
// stereo mix recorder for audio processing
WallpaperEngine::Audio::Drivers::Recorders::CPulseAudioPlaybackRecorder audioRecorder;
// audio playing detector
WallpaperEngine::Audio::Drivers::Detectors::CPulseAudioPlayingDetector audioDetector (
this->m_context, videoDriver->getFullscreenDetector ());
// initialize sdl audio driver
audioDriver = new WallpaperEngine::Audio::Drivers::CSDLAudioDriver (this->m_context, audioDetector, audioRecorder);
// initialize audio context
audioContext = new WallpaperEngine::Audio::CAudioContext (*audioDriver);
// initialize render context
context = new WallpaperEngine::Render::CRenderContext (*videoDriver, *inputContext, *this);
// set all the specific wallpapers required
for (const auto& [background, info] : this->m_backgrounds)
context->setWallpaper (background, WallpaperEngine::Render::CWallpaper::fromWallpaper (
info->getWallpaper (), *context, *audioContext,
this->m_context.settings.general.screenScalings [background]));
// set the default rendering wallpaper if available
if (this->m_defaultBackground != nullptr)
context->setDefaultWallpaper (WallpaperEngine::Render::CWallpaper::fromWallpaper (
this->m_defaultBackground->getWallpaper (), *context, *audioContext,
this->m_context.settings.render.window.scalingMode));
static time_t seconds;
static struct tm* timeinfo;
while (this->m_context.state.general.keepRunning && !videoDriver->closeRequested ()) {
// update g_Daytime
time (&seconds);
timeinfo = localtime (&seconds);
g_Daytime = ((timeinfo->tm_hour * 60) + timeinfo->tm_min) / (24.0 * 60.0);
// keep track of the previous frame's time
g_TimeLast = g_Time;
// calculate the current time value
g_Time = videoDriver->getRenderTime ();
// update audio recorder
audioDriver->update ();
// update input information
inputContext->update ();
// process driver events
videoDriver->dispatchEventQueue ();
if (!this->m_context.settings.screenshot.take || videoDriver->getFrameCounter () < 5)
continue;
this->takeScreenshot (*context, this->m_context.settings.screenshot.path,
this->m_context.settings.screenshot.format);
this->m_context.settings.screenshot.take = false;
}
// ensure this is updated as sometimes it might not come from a signal
this->m_context.state.general.keepRunning = false;
sLog.out ("Stop requested");
SDL_Quit ();
}
void CWallpaperApplication::update (Render::Drivers::Output::COutputViewport* viewport) {
// render the scene
context->render (viewport);
}
void CWallpaperApplication::signal (int signal) {
this->m_context.state.general.keepRunning = false;
}
const std::map<std::string, Core::CProject*>& CWallpaperApplication::getBackgrounds () const {
return this->m_backgrounds;
}
Core::CProject* CWallpaperApplication::getDefaultBackground () const {
return this->m_defaultBackground;
}
CApplicationContext& CWallpaperApplication::getContext () const {
return this->m_context;
}
const WallpaperEngine::Render::Drivers::Output::COutput& CWallpaperApplication::getOutput () const {
return this->context->getOutput ();
}
} // namespace WallpaperEngine::Application

View File

@ -6,8 +6,8 @@
#include "WallpaperEngine/Core/CProject.h" #include "WallpaperEngine/Core/CProject.h"
#include "WallpaperEngine/Render/CWallpaper.h"
#include "WallpaperEngine/Render/CRenderContext.h" #include "WallpaperEngine/Render/CRenderContext.h"
#include "WallpaperEngine/Render/CWallpaper.h"
#include "WallpaperEngine/Render/Drivers/CX11OpenGLDriver.h" #include "WallpaperEngine/Render/Drivers/CX11OpenGLDriver.h"
#ifdef ENABLE_WAYLAND #ifdef ENABLE_WAYLAND
#include "WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h" #include "WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h"
@ -28,99 +28,98 @@
#include "WallpaperEngine/Input/CInputContext.h" #include "WallpaperEngine/Input/CInputContext.h"
namespace WallpaperEngine::Application namespace WallpaperEngine::Application {
{ /**
* Small wrapper class over the actual wallpaper's main application skeleton
*
* @author Alexis Maiquez <almamu@almamu.com>
*/
class CWallpaperApplication {
public:
explicit CWallpaperApplication (CApplicationContext& context);
~CWallpaperApplication ();
/** /**
* Small wrapper class over the actual wallpaper's main application skeleton * Shows the application until it's closed
*
* @author Alexis Maiquez <almamu@almamu.com>
*/ */
class CWallpaperApplication void show ();
{ /**
public: * Handles a OS signal sent to this PID
explicit CWallpaperApplication (CApplicationContext& context); *
~CWallpaperApplication (); * @param signal
*/
void signal (int signal);
/**
* @return Maps screens to loaded backgrounds
*/
[[nodiscard]] const std::map<std::string, Core::CProject*>& getBackgrounds () const;
/**
* @return The default background to use if no specific project is loaded
*/
[[nodiscard]] Core::CProject* getDefaultBackground () const;
/**
* @return The current application context
*/
[[nodiscard]] CApplicationContext& getContext () const;
/**
* Renders a frame
*/
void update (Render::Drivers::Output::COutputViewport* viewport);
/**
* Gets the output
*/
[[nodiscard]] const WallpaperEngine::Render::Drivers::Output::COutput& getOutput () const;
/** private:
* Shows the application until it's closed /**
*/ * Sets up a combined container for the given background, adding default files and directories to the list
void show (); *
/** * @param container
* Handles a OS signal sent to this PID * @param bg
* */
* @param signal void setupContainer (CCombinedContainer& container, const std::string& bg) const;
*/ /**
void signal (int signal); * Loads projects based off the settings
/** */
* @return Maps screens to loaded backgrounds void loadBackgrounds ();
*/ /**
[[nodiscard]] const std::map <std::string, Core::CProject*>& getBackgrounds () const; * Loads the given project
/** *
* @return The default background to use if no specific project is loaded * @param bg
*/ * @return
[[nodiscard]] Core::CProject* getDefaultBackground () const; */
/** Core::CProject* loadBackground (const std::string& bg);
* @return The current application context /**
*/ * Prepares all background's values and updates their properties if required
[[nodiscard]] CApplicationContext& getContext () const; */
/** void setupProperties ();
* Renders a frame /**
*/ * Updates the properties for the given background based on the current context
void update(Render::Drivers::Output::COutputViewport* viewport); *
/** * @param project
* Gets the output */
*/ void setupPropertiesForProject (const Core::CProject* project);
WallpaperEngine::Render::Drivers::Output::COutput* getOutput() const; /**
* Takes an screenshot of the background and saves it to the specified path
*
* @param context
* @param filename
* @param format
*/
static void takeScreenshot (const Render::CRenderContext& context, const std::filesystem::path& filename,
FREE_IMAGE_FORMAT format);
private: /** The default background to display if no specific background was loaded */
/** Core::CProject* m_defaultBackground;
* Sets up a combined container for the given background, adding default files and directories to the list /** The application context that contains the current app settings */
* CApplicationContext& m_context;
* @param container /** Maps screens to backgrounds */
* @param bg std::map<std::string, Core::CProject*> m_backgrounds;
*/
void setupContainer (CCombinedContainer& container, const std::string& bg) const;
/**
* Loads projects based off the settings
*/
void loadBackgrounds ();
/**
* Loads the given project
*
* @param bg
* @return
*/
Core::CProject* loadBackground (const std::string& bg);
/**
* Prepares all background's values and updates their properties if required
*/
void setupProperties ();
/**
* Updates the properties for the given background based on the current context
*
* @param project
*/
void setupPropertiesForProject (Core::CProject* project);
/**
* Takes an screenshot of the background and saves it to the specified path
*
* @param context
* @param filename
* @param format
*/
static void takeScreenshot (const Render::CRenderContext& context, const std::filesystem::path& filename, FREE_IMAGE_FORMAT format);
/** The default background to display if no specific background was loaded */ WallpaperEngine::Render::Drivers::CVideoDriver* videoDriver;
Core::CProject* m_defaultBackground; WallpaperEngine::Input::CInputContext* inputContext;
/** The application context that contains the current app settings */ WallpaperEngine::Audio::Drivers::CSDLAudioDriver* audioDriver;
CApplicationContext& m_context; WallpaperEngine::Render::CRenderContext* context;
/** Maps screens to backgrounds */ WallpaperEngine::Audio::CAudioContext* audioContext;
std::map <std::string, Core::CProject*> m_backgrounds; };
} // namespace WallpaperEngine::Application
WallpaperEngine::Render::Drivers::CVideoDriver* videoDriver;
WallpaperEngine::Input::CInputContext* inputContext;
WallpaperEngine::Audio::Drivers::CSDLAudioDriver* audioDriver;
WallpaperEngine::Render::CRenderContext* context;
WallpaperEngine::Audio::CAudioContext* audioContext;
};
}

View File

@ -2,12 +2,9 @@
using namespace WallpaperEngine::Assets; using namespace WallpaperEngine::Assets;
CAssetLoadException::CAssetLoadException(const std::string& filename, const std::string& extrainfo) CAssetLoadException::CAssetLoadException (const std::string& filename, const std::string& extrainfo) :
: m_message("Cannot find file " + filename + ": " + extrainfo) m_message ("Cannot find file " + filename + ": " + extrainfo) {}
{
}
const char *CAssetLoadException::what() const noexcept const char* CAssetLoadException::what () const noexcept {
{
return this->m_message.c_str (); return this->m_message.c_str ();
} }

View File

@ -3,15 +3,13 @@
#include <exception> #include <exception>
#include <string> #include <string>
namespace WallpaperEngine::Assets namespace WallpaperEngine::Assets {
{ class CAssetLoadException final : public std::exception {
class CAssetLoadException : public std::exception public:
{ explicit CAssetLoadException (const std::string& filename, const std::string& extrainfo = "");
public: [[nodiscard]] const char* what () const noexcept override;
explicit CAssetLoadException (const std::string& filename, const std::string& extrainfo = "");
[[nodiscard]] const char* what () const noexcept override;
private: private:
std::string m_message; std::string m_message;
}; };
} } // namespace WallpaperEngine::Assets

View File

@ -6,50 +6,33 @@
using namespace WallpaperEngine::Assets; using namespace WallpaperEngine::Assets;
CCombinedContainer::CCombinedContainer () : CCombinedContainer::CCombinedContainer () : CContainer () {}
CContainer (),
m_containers ()
{
}
void CCombinedContainer::add (CContainer* container) void CCombinedContainer::add (CContainer* container) {
{
this->m_containers.emplace_back (container); this->m_containers.emplace_back (container);
} }
void CCombinedContainer::addPkg (const std::filesystem::path& path) void CCombinedContainer::addPkg (const std::filesystem::path& path) {
{ try {
try
{
// add the package to the list // add the package to the list
this->add (new CPackage (path)); this->add (new CPackage (path));
sLog.out ("Detected ", path.filename (), " file at ", path, ". Adding to list of searchable paths"); sLog.out ("Detected ", path.filename (), " file at ", path, ". Adding to list of searchable paths");
} } catch (CPackageLoadException&) {
catch (CPackageLoadException& ex)
{
// ignore this error, the package file was not found // ignore this error, the package file was not found
sLog.out ("No ", path.filename (), " file found at ", path, ". Defaulting to normal folder storage"); sLog.out ("No ", path.filename (), " file found at ", path, ". Defaulting to normal folder storage");
} } catch (std::runtime_error& ex) {
catch (std::runtime_error& ex)
{
// the package was found but there was an error loading it (wrong header or something) // the package was found but there was an error loading it (wrong header or something)
sLog.exception ("Failed to load scene.pkg file: ", ex.what()); sLog.exception ("Failed to load scene.pkg file: ", ex.what ());
} }
} }
std::filesystem::path CCombinedContainer::resolveRealFile (const std::string& filename) const {
std::filesystem::path CCombinedContainer::resolveRealFile (const std::string& filename) const for (const auto cur : this->m_containers) {
{ try {
for (auto cur : this->m_containers)
{
try
{
// try to read the file on the current container, if the file doesn't exists // try to read the file on the current container, if the file doesn't exists
// an exception will be thrown // an exception will be thrown
return cur->resolveRealFile (filename); return cur->resolveRealFile (filename);
} } catch (CAssetLoadException&) {
catch (CAssetLoadException& ex)
{
// not found in this container, next try // not found in this container, next try
} }
} }
@ -58,18 +41,13 @@ std::filesystem::path CCombinedContainer::resolveRealFile (const std::string& fi
throw CAssetLoadException (filename, "Cannot resolve file in any of the containers"); throw CAssetLoadException (filename, "Cannot resolve file in any of the containers");
} }
const void* CCombinedContainer::readFile (const std::string& filename, uint32_t* length) const const void* CCombinedContainer::readFile (const std::string& filename, uint32_t* length) const {
{ for (const auto cur : this->m_containers) {
for (auto cur : this->m_containers) try {
{
try
{
// try to read the file on the current container, if the file doesn't exists // try to read the file on the current container, if the file doesn't exists
// an exception will be thrown // an exception will be thrown
return cur->readFile (filename, length); return cur->readFile (filename, length);
} } catch (CAssetLoadException&) {
catch (CAssetLoadException& ex)
{
// not found in this container, next try // not found in this container, next try
} }
} }

View File

@ -6,36 +6,34 @@
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
namespace WallpaperEngine::Assets namespace WallpaperEngine::Assets {
{ /**
* A meta-container that allows backgrounds to have files spread across different containers
*/
class CCombinedContainer final : public CContainer {
public:
CCombinedContainer ();
/** /**
* A meta-container that allows backgrounds to have files spread across different containers * Adds a container to the list
*
* @param container
*/ */
class CCombinedContainer : public CContainer void add (CContainer* container);
{ /**
public: * Adds the given package to the list
CCombinedContainer (); *
* @param path
*/
void addPkg (const std::filesystem::path& path);
/** /** @inheritdoc */
* Adds a container to the list [[nodiscard]] std::filesystem::path resolveRealFile (const std::string& filename) const override;
* /** @inheritdoc */
* @param container [[nodiscard]] const void* readFile (const std::string& filename, uint32_t* length) const override;
*/
void add (CContainer* container);
/**
* Adds the given package to the list
*
* @param path
*/
void addPkg (const std::filesystem::path& path);
/** @inheritdoc */ private:
[[nodiscard]] std::filesystem::path resolveRealFile (const std::string& filename) const override; /** The list of containers to search files off from */
/** @inheritdoc */ std::vector<CContainer*> m_containers;
[[nodiscard]] const void* readFile (const std::string& filename, uint32_t* length) const override;
private:
/** The list of containers to search files off from */
std::vector<CContainer*> m_containers;
};
}; };
}; // namespace WallpaperEngine::Assets

View File

@ -1,27 +1,25 @@
#include "CContainer.h" #include "CContainer.h"
#include "CAssetLoadException.h"
#include "CTexture.h" #include "CTexture.h"
#include "WallpaperEngine/Logging/CLog.h" #include "WallpaperEngine/Logging/CLog.h"
#include "CAssetLoadException.h"
#include <cstring> #include <cstring>
#include <utility>
#include <filesystem> #include <filesystem>
#include <utility>
using namespace WallpaperEngine::Assets; using namespace WallpaperEngine::Assets;
std::filesystem::path CContainer::resolveRealFile (const std::string& filename) const std::filesystem::path CContainer::resolveRealFile (const std::string& filename) const {
{
throw CAssetLoadException (filename, "Cannot resolve physical file in this container"); throw CAssetLoadException (filename, "Cannot resolve physical file in this container");
} }
const ITexture* CContainer::readTexture (const std::string& filename) const const ITexture* CContainer::readTexture (const std::string& filename) const {
{
// get the texture's filename (usually .tex) // get the texture's filename (usually .tex)
std::string texture = "materials/" + filename + ".tex"; const std::string texture = "materials/" + filename + ".tex";
const void* textureContents = this->readFile (texture, nullptr); const void* textureContents = this->readFile (texture, nullptr);
ITexture* result = new CTexture (textureContents); const ITexture* result = new CTexture (textureContents);
#if !NDEBUG #if !NDEBUG
glObjectLabel (GL_TEXTURE, result->getTextureID (), -1, texture.c_str ()); glObjectLabel (GL_TEXTURE, result->getTextureID (), -1, texture.c_str ());
@ -29,22 +27,19 @@ const ITexture* CContainer::readTexture (const std::string& filename) const
return result; return result;
} }
std::string CContainer::readShader (const std::string& filename) const
{ std::string CContainer::readShader (const std::string& filename) const {
std::filesystem::path shader = filename; std::filesystem::path shader = filename;
auto it = shader.begin (); auto it = shader.begin ();
// detect workshop shaders and check if there's a // detect workshop shaders and check if there's a
if (*it++ == "workshop") if (*it++ == "workshop") {
{ const std::filesystem::path workshopId = *it++;
std::filesystem::path workshopId = *it++;
if (++it != shader.end ()) if (++it != shader.end ()) {
{ const std::filesystem::path shaderfile = *it;
std::filesystem::path shaderfile = *it;
try try {
{
shader = std::filesystem::path ("zcompat") / "scene" / "shaders" / workshopId / shaderfile; shader = std::filesystem::path ("zcompat") / "scene" / "shaders" / workshopId / shaderfile;
// replace the old path with the new one // replace the old path with the new one
std::string contents = this->readFileAsString (shader); std::string contents = this->readFileAsString (shader);
@ -52,34 +47,26 @@ std::string CContainer::readShader (const std::string& filename) const
sLog.out ("Replaced ", filename, " with compat ", shader); sLog.out ("Replaced ", filename, " with compat ", shader);
return contents; return contents;
} } catch (CAssetLoadException&) {}
catch (CAssetLoadException&)
{
}
} }
} }
return this->readFileAsString ("shaders/" + filename); return this->readFileAsString ("shaders/" + filename);
} }
std::string CContainer::readVertexShader (const std::string& filename) const std::string CContainer::readVertexShader (const std::string& filename) const {
{
return this->readShader (filename + ".vert"); return this->readShader (filename + ".vert");
} }
std::string CContainer::readFragmentShader (const std::string& filename) const std::string CContainer::readFragmentShader (const std::string& filename) const {
{
return this->readShader (filename + ".frag"); return this->readShader (filename + ".frag");
} }
std::string CContainer::readIncludeShader (const std::string& filename) const std::string CContainer::readIncludeShader (const std::string& filename) const {
{
return this->readFileAsString ("shaders/" + filename); return this->readFileAsString ("shaders/" + filename);
} }
std::string CContainer::readFileAsString (const std::string& filename) const std::string CContainer::readFileAsString (const std::string& filename) const {
{
uint32_t length = 0; uint32_t length = 0;
// read file contents and allocate a buffer for a string // read file contents and allocate a buffer for a string
@ -94,7 +81,7 @@ std::string CContainer::readFileAsString (const std::string& filename) const
std::string result = buffer; std::string result = buffer;
// free the intermediate buffer used to generate the std::string // free the intermediate buffer used to generate the std::string
delete[] buffer; delete [] buffer;
return result; return result;
} }

View File

@ -5,85 +5,85 @@
#include <filesystem> #include <filesystem>
#include <string> #include <string>
namespace WallpaperEngine::Assets namespace WallpaperEngine::Assets {
{ /**
* File container, provides access to files for backgrounds
*/
class CContainer {
public:
virtual ~CContainer () = default;
/** /**
* File container, provides access to files for backgrounds * Resolves the full path to the specified file in the filesystem
*
* @param filename
* @return
*/ */
class CContainer [[nodiscard]] virtual std::filesystem::path resolveRealFile (const std::string& filename) const;
{
public:
/**
* Resolves the full path to the specified file in the filesystem
*
* @param filename
* @return
*/
[[nodiscard]] virtual std::filesystem::path resolveRealFile (const std::string& filename) const;
/** /**
* Reads the given file from the container and returns it's data * Reads the given file from the container and returns it's data
* Additionally sets a length parameter to return back the file's length * Additionally sets a length parameter to return back the file's length
* *
* @param filename The file to read * @param filename The file to read
* @param length The file's length after it's been read, null for not getting anything back * @param length The file's length after it's been read, null for not getting anything back
* *
* @return * @return
*/ */
[[nodiscard]] virtual const void* readFile (const std::string& filename, uint32_t* length) const = 0; [[nodiscard]] virtual const void* readFile (const std::string& filename, uint32_t* length) const = 0;
/** /**
* Wrapper for readFile, appends the texture extension at the end of the filename * Wrapper for readFile, appends the texture extension at the end of the filename
* *
* @param filename The texture name (without the .tex) * @param filename The texture name (without the .tex)
* *
* @return * @return
*/ */
[[nodiscard]] const ITexture* readTexture (const std::string& filename) const; [[nodiscard]] const ITexture* readTexture (const std::string& filename) const;
/** /**
* Wrapper for readFile, checks for compat versions of the given shader file * Wrapper for readFile, checks for compat versions of the given shader file
* *
* @param filename * @param filename
* *
* @return The shader code as an string to be used * @return The shader code as an string to be used
*/ */
[[nodiscard]] std::string readShader (const std::string& filename) const; [[nodiscard]] std::string readShader (const std::string& filename) const;
/** /**
* Wrapper for readFile, appends the .vert extension at the end and opens the given shader file * Wrapper for readFile, appends the .vert extension at the end and opens the given shader file
* *
* @param filename * @param filename
* *
* @return The shader code as an string to be used * @return The shader code as an string to be used
*/ */
[[nodiscard]] std::string readVertexShader (const std::string& filename) const; [[nodiscard]] std::string readVertexShader (const std::string& filename) const;
/** /**
* Wrapper for readFile, appends the .frag extension at the end and opens the given shader file * Wrapper for readFile, appends the .frag extension at the end and opens the given shader file
* *
* @param filename * @param filename
* *
* @return The shader code as an string to be used * @return The shader code as an string to be used
*/ */
[[nodiscard]] std::string readFragmentShader (const std::string& filename) const; [[nodiscard]] std::string readFragmentShader (const std::string& filename) const;
/** /**
* Wrapper for readFile, appends the .h extension at the end and opens the given shader file * Wrapper for readFile, appends the .h extension at the end and opens the given shader file
* *
* @param filename * @param filename
* *
* @return The shader code as an string to be used * @return The shader code as an string to be used
*/ */
[[nodiscard]] std::string readIncludeShader (const std::string& filename) const; [[nodiscard]] std::string readIncludeShader (const std::string& filename) const;
/** /**
* Reads a file as string * Reads a file as string
* *
* @param filename * @param filename
* *
* @return The file's contents as string * @return The file's contents as string
*/ */
[[nodiscard]] std::string readFileAsString (const std::string& filename) const; [[nodiscard]] std::string readFileAsString (const std::string& filename) const;
}; };
} } // namespace WallpaperEngine::Assets

View File

@ -3,63 +3,54 @@
#include <utility> #include <utility>
#include "CDirectory.h"
#include "CAssetLoadException.h" #include "CAssetLoadException.h"
#include "CDirectory.h"
using namespace WallpaperEngine::Assets; using namespace WallpaperEngine::Assets;
CDirectory::CDirectory (std::filesystem::path basepath) : CDirectory::CDirectory (std::filesystem::path basepath) : m_basepath (std::move (basepath)) {
m_basepath (std::move(basepath))
{
// ensure the specified path exists // ensure the specified path exists
struct stat buffer {}; struct stat buffer {};
if (stat (this->m_basepath.c_str (), &buffer) != 0) if (stat (this->m_basepath.c_str (), &buffer) != 0)
throw CAssetLoadException (this->m_basepath, "Cannot find directory"); throw CAssetLoadException (this->m_basepath, "Cannot find directory");
if (!S_ISDIR(buffer.st_mode)) if (!S_ISDIR (buffer.st_mode))
throw CAssetLoadException (this->m_basepath, "Expected directory but found a file"); throw CAssetLoadException (this->m_basepath, "Expected directory but found a file");
} }
CDirectory::~CDirectory () std::filesystem::path CDirectory::resolveRealFile (const std::string& filename) const {
= default;
std::filesystem::path CDirectory::resolveRealFile (const std::string& filename) const
{
return std::filesystem::path (this->m_basepath) / filename; return std::filesystem::path (this->m_basepath) / filename;
} }
const void* CDirectory::readFile (const std::string& filename, uint32_t* length) const const void* CDirectory::readFile (const std::string& filename, uint32_t* length) const {
{ const std::filesystem::path final = std::filesystem::path (this->m_basepath) / filename;
std::filesystem::path final = std::filesystem::path (this->m_basepath) / filename;
// first check the cache, if the file is there already just return the data in there // first check the cache, if the file is there already just return the data in there
auto it = this->m_cache.find (final); const auto it = this->m_cache.find (final);
if (it != this->m_cache.end ()) if (it != this->m_cache.end ()) {
{
if (length != nullptr) if (length != nullptr)
*length = (*it).second.length; *length = it->second.length;
return (*it).second.address; return it->second.address;
} }
FILE* fp = fopen (final.c_str (), "rb"); FILE* fp = fopen (final.c_str (), "rb");
if (fp == nullptr) if (fp == nullptr)
throw CAssetLoadException(filename, "Cannot find file"); throw CAssetLoadException (filename, "Cannot find file");
// go to the end, get the position and return to the beginning // go to the end, get the position and return to the beginning
fseek (fp, 0, SEEK_END); fseek (fp, 0, SEEK_END);
long size = ftell (fp); const long size = ftell (fp);
fseek (fp, 0, SEEK_SET); fseek (fp, 0, SEEK_SET);
// now read the whole file // now read the whole file
char* contents = new char[size]; auto* contents = new char [size];
if (fread (contents, size, 1, fp) != 1) if (fread (contents, size, 1, fp) != 1) {
{ delete [] contents;
delete[] contents;
throw CAssetLoadException (filename, "Unexpected error when reading the file"); throw CAssetLoadException (filename, "Unexpected error when reading the file");
} }

View File

@ -1,33 +1,30 @@
#pragma once #pragma once
#include <string>
#include <stdexcept>
#include <map>
#include <filesystem> #include <filesystem>
#include <map>
#include <stdexcept>
#include <string>
#include "CContainer.h" #include "CContainer.h"
#include "CFileEntry.h" #include "CFileEntry.h"
namespace WallpaperEngine::Assets namespace WallpaperEngine::Assets {
{ /**
/** * Directory container implementation, provides access to background files under a specific directory
* Directory container implementation, provides access to background files under a specific directory */
*/ class CDirectory final : public CContainer {
class CDirectory : public CContainer public:
{ explicit CDirectory (std::filesystem::path basepath);
public:
explicit CDirectory (std::filesystem::path basepath);
~CDirectory ();
/** @inheritdoc */ /** @inheritdoc */
[[nodiscard]] std::filesystem::path resolveRealFile (const std::string& filename) const override; [[nodiscard]] std::filesystem::path resolveRealFile (const std::string& filename) const override;
/** @inheritdoc */ /** @inheritdoc */
[[nodiscard]] const void* readFile (const std::string& filename, uint32_t* length) const override; [[nodiscard]] const void* readFile (const std::string& filename, uint32_t* length) const override;
private: private:
/** The basepath for the directory */ /** The basepath for the directory */
std::filesystem::path m_basepath; std::filesystem::path m_basepath;
/** File cache to simplify access to data */ /** File cache to simplify access to data */
std::map <std::string, CFileEntry> m_cache; std::map<std::string, CFileEntry> m_cache;
}; };
} } // namespace WallpaperEngine::Assets

View File

@ -2,21 +2,21 @@
#include <cstdint> #include <cstdint>
namespace WallpaperEngine::Assets namespace WallpaperEngine::Assets {
{ /**
/** * File cache entry to prevent hit the disk when loading the same file multiple times
* File cache entry to prevent hit the disk when loading the same file multiple times */
*/ class CFileEntry {
class CFileEntry public:
{ CFileEntry (const char* address, uint32_t length) : address (address), length (length) {}
public:
CFileEntry (const void* address, uint32_t length) :
address (address),
length (length) { }
/** File contents */ ~CFileEntry () {
const void* address; delete [] address;
/** File length */ }
uint32_t length;
}; /** File contents */
} const char* address;
/** File length */
uint32_t length;
};
} // namespace WallpaperEngine::Assets

View File

@ -1,53 +1,48 @@
#include "common.h"
#include "CPackage.h" #include "CPackage.h"
#include "CAssetLoadException.h" #include "CAssetLoadException.h"
#include "CPackageLoadException.h" #include "CPackageLoadException.h"
#include "common.h"
#include <utility>
#include <sstream> #include <sstream>
#include <utility>
using namespace WallpaperEngine::Assets; using namespace WallpaperEngine::Assets;
class CPackageEntry class CPackageEntry {
{ public:
public:
CPackageEntry (std::string filename, uint32_t offset, uint32_t length) : CPackageEntry (std::string filename, uint32_t offset, uint32_t length) :
filename (std::move(filename)), filename (std::move (filename)),
offset (offset), offset (offset),
length (length) { } length (length) {}
std::string filename; std::string filename;
uint32_t offset; uint32_t offset;
uint32_t length; uint32_t length;
}; };
CPackage::CPackage (std::filesystem::path path) : CPackage::CPackage (std::filesystem::path path) : m_path (std::move (path)) {
m_path (std::move(path)),
m_contents ()
{
this->init (); this->init ();
} }
CPackage::~CPackage() const void* CPackage::readFile (const std::string& filename, uint32_t* length) const {
= default; const auto it = this->m_contents.find (filename);
const void* CPackage::readFile (const std::string& filename, uint32_t* length) const
{
auto it = this->m_contents.find (filename);
if (it == this->m_contents.end ()) if (it == this->m_contents.end ())
throw CAssetLoadException(filename, "Cannot find the file in the package"); throw CAssetLoadException (filename, "Cannot find the file in the package");
// set file length if required // set file length if required
if (length != nullptr) if (length != nullptr)
*length = (*it).second.length; *length = it->second->length;
return (*it).second.address; // clone original first
auto* result = new char [it->second->length];
memcpy (result, it->second->address, it->second->length);
return result;
} }
void CPackage::init () void CPackage::init () {
{
FILE* fp = fopen (this->m_path.c_str (), "rb+"); FILE* fp = fopen (this->m_path.c_str (), "rb+");
if (fp == nullptr) if (fp == nullptr)
@ -61,21 +56,20 @@ void CPackage::init ()
fclose (fp); fclose (fp);
} }
char* CPackage::readSizedString (FILE* fp) char* CPackage::readSizedString (FILE* fp) {
{
unsigned int length = 0; unsigned int length = 0;
if (fread (&length, sizeof (unsigned int), 1, fp) != 1) if (fread (&length, sizeof (unsigned int), 1, fp) != 1)
sLog.exception ("Cannot read sized string length on file ", this->m_path); sLog.exception ("Cannot read sized string length on file ", this->m_path);
// account for 0 termination of the string // account for 0 termination of the string
length ++; length++;
char* pointer = new char [length]; char* pointer = new char [length];
memset (pointer, 0, length); memset (pointer, 0, length);
// read only the string bytes so the last one in the memory is 0 // read only the string bytes so the last one in the memory is 0
length --; length--;
// read data from file // read data from file
if (fread (pointer, sizeof (char), length, fp) != length) if (fread (pointer, sizeof (char), length, fp) != length)
@ -84,8 +78,7 @@ char* CPackage::readSizedString (FILE* fp)
return pointer; return pointer;
} }
uint32_t CPackage::readInteger (FILE* fp) uint32_t CPackage::readInteger (FILE* fp) {
{
uint32_t output; uint32_t output;
if (fread (&output, sizeof (uint32_t), 1, fp) != 1) if (fread (&output, sizeof (uint32_t), 1, fp) != 1)
@ -94,46 +87,41 @@ uint32_t CPackage::readInteger (FILE* fp)
return output; return output;
} }
void CPackage::validateHeader (FILE* fp) void CPackage::validateHeader (FILE* fp) {
{ const char* pointer = this->readSizedString (fp);
char* pointer = this->readSizedString (fp);
if (strncmp ("PKGV", pointer, 4) != 0) if (strncmp ("PKGV", pointer, 4) != 0) {
{
std::stringstream msg; std::stringstream msg;
msg << "Expected PKGV indicator, found " << pointer; msg << "Expected PKGV indicator, found " << pointer;
delete[] pointer; delete [] pointer;
throw std::runtime_error(msg.str()); throw std::runtime_error (msg.str ());
} }
// free memory // free memory
delete[] pointer; delete [] pointer;
} }
void CPackage::loadFiles (FILE* fp) void CPackage::loadFiles (FILE* fp) {
{ const uint32_t count = this->readInteger (fp);
uint32_t count = this->readInteger (fp);
std::vector<CPackageEntry> list; std::vector<CPackageEntry> list;
for (uint32_t index = 0; index < count; index ++) for (uint32_t index = 0; index < count; index++) {
{
// first read the filename // first read the filename
char* filename = this->readSizedString (fp); char* filename = this->readSizedString (fp);
uint32_t offset = this->readInteger (fp); uint32_t offset = this->readInteger (fp);
uint32_t length = this->readInteger (fp); uint32_t length = this->readInteger (fp);
// add the file to the list // add the file to the list
list.emplace_back(filename, offset, length); list.emplace_back (filename, offset, length);
// only free filename, the file's contents are stored in a map for a later use // only free filename, the file's contents are stored in a map for a later use
delete[] filename; delete [] filename;
} }
// get current baseOffset, this is where the files start // get current baseOffset, this is where the files start
long baseOffset = ftell (fp); const long baseOffset = ftell (fp);
for (const auto& cur : list) for (const auto& cur : list) {
{ const long offset = cur.offset + baseOffset;
long offset = cur.offset + baseOffset;
// with all the data we can jump to the offset and read the content // with all the data we can jump to the offset and read the content
if (fseek (fp, offset, SEEK_SET) != 0) if (fseek (fp, offset, SEEK_SET) != 0)
@ -142,14 +130,13 @@ void CPackage::loadFiles (FILE* fp)
// allocate memory for the file's contents and read it from the file // allocate memory for the file's contents and read it from the file
char* fileContents = new char [cur.length]; char* fileContents = new char [cur.length];
if (fread (fileContents, cur.length, 1, fp) != 1) if (fread (fileContents, cur.length, 1, fp) != 1) {
{ delete [] fileContents;
delete[] fileContents;
sLog.exception ("Cannot read file ", cur.filename, " contents from package ", this->m_path); sLog.exception ("Cannot read file ", cur.filename, " contents from package ", this->m_path);
} }
// add the file to the map // add the file to the map
this->m_contents.insert_or_assign (cur.filename, CFileEntry (fileContents, cur.length)); this->m_contents.insert_or_assign (cur.filename, new CFileEntry (fileContents, cur.length));
} }
} }

View File

@ -1,71 +1,68 @@
#pragma once #pragma once
#include <cstring>
#include <exception>
#include <filesystem>
#include <map>
#include <stdexcept>
#include <string> #include <string>
#include <vector> #include <vector>
#include <map>
#include <exception>
#include <stdexcept>
#include <cstring>
#include <filesystem>
#include "CContainer.h" #include "CContainer.h"
#include "CFileEntry.h" #include "CFileEntry.h"
namespace WallpaperEngine::Assets namespace WallpaperEngine::Assets {
{ /**
* Package container implementation, provides access to background files that are stored
* inside the WallpaperEngine's pkg format
*/
class CPackage final : public CContainer {
public:
explicit CPackage (std::filesystem::path path);
[[nodiscard]] const void* readFile (const std::string& filename, uint32_t* length) const override;
protected:
/** /**
* Package container implementation, provides access to background files that are stored * Loads the current package file and loads all it's contents to memory
* inside the WallpaperEngine's pkg format
*/ */
class CPackage : public CContainer void init ();
{
public:
explicit CPackage (std::filesystem::path path);
~CPackage ();
[[nodiscard]] const void* readFile (const std::string& filename, uint32_t* length) const override; /**
* Reads the header from the current position and ensures it's a compatible version
*
* @param fp The file where to read from
*/
void validateHeader (FILE* fp);
protected: /**
/** * Loads the files in the package into memory
* Loads the current package file and loads all it's contents to memory *
*/ * @param fp The file where to read from
void init (); */
void loadFiles (FILE* fp);
/** /**
* Reads the header from the current position and ensures it's a compatible version * Reads a size-prefixed string
* *
* @param fp The file where to read from * @param fp File to read from
*/ *
void validateHeader (FILE* fp); * @return The read data, important to free it
*/
char* readSizedString (FILE* fp);
/**
* Reads a simple unsigned of 32 bits
*
* @param fp File to read from
*
* @return The read value
*/
uint32_t readInteger (FILE* fp);
/** private:
* Loads the files in the package into memory /** The path to the package file */
* std::filesystem::path m_path;
* @param fp The file where to read from /** Contents of the package file */
*/ std::map<std::string, CFileEntry*> m_contents;
void loadFiles (FILE* fp); };
} // namespace WallpaperEngine::Assets
/**
* Reads a size-prefixed string
*
* @param fp File to read from
*
* @return The read data, important to free it
*/
char* readSizedString (FILE* fp);
/**
* Reads a simple unsigned of 32 bits
*
* @param fp File to read from
*
* @return The read value
*/
uint32_t readInteger (FILE* fp);
private:
/** The path to the package file */
std::filesystem::path m_path;
/** Contents of the package file */
std::map <std::string, CFileEntry> m_contents;
};
}

View File

@ -3,11 +3,8 @@
using namespace WallpaperEngine::Assets; using namespace WallpaperEngine::Assets;
CPackageLoadException::CPackageLoadException (const std::string& filename, const std::string& extrainfo) : CPackageLoadException::CPackageLoadException (const std::string& filename, const std::string& extrainfo) :
m_message ("Cannot load package " + filename + ": " + extrainfo) m_message ("Cannot load package " + filename + ": " + extrainfo) {}
{
}
const char *CPackageLoadException::what () const noexcept const char* CPackageLoadException::what () const noexcept {
{
return this->m_message.c_str (); return this->m_message.c_str ();
} }

View File

@ -3,15 +3,13 @@
#include <exception> #include <exception>
#include <string> #include <string>
namespace WallpaperEngine::Assets namespace WallpaperEngine::Assets {
{ class CPackageLoadException final : public std::exception {
class CPackageLoadException : public std::exception public:
{ explicit CPackageLoadException (const std::string& filename, const std::string& extrainfo = "");
public: [[nodiscard]] const char* what () const noexcept override;
explicit CPackageLoadException (const std::string& message, const std::string& extrainfo = "");
[[nodiscard]] const char* what () const noexcept override;
private: private:
std::string m_message; std::string m_message;
}; };
} } // namespace WallpaperEngine::Assets

View File

@ -1,53 +1,37 @@
#include "common.h"
#include "CTexture.h" #include "CTexture.h"
#include "common.h"
#include <string>
#include <cstring> #include <cstring>
#include <lz4.h> #include <lz4.h>
#include <string>
using namespace WallpaperEngine::Assets; using namespace WallpaperEngine::Assets;
CTexture::CTexture (const void* fileData) : CTexture::CTexture (const void* fileData) : m_resolution () {
m_resolution ()
{
// ensure the header is parsed // ensure the header is parsed
this->m_header = parseHeader (static_cast <const char*> (fileData)); this->m_header = parseHeader (static_cast<const char*> (fileData));
GLint internalFormat; GLint internalFormat;
if (this->isAnimated ()) if (this->isAnimated ()) {
{ this->m_resolution = {this->m_header->textureWidth, this->m_header->textureHeight, this->m_header->gifWidth,
this->m_resolution = { this->m_header->gifHeight};
this->m_header->textureWidth, this->m_header->textureHeight, } else {
this->m_header->gifWidth, this->m_header->gifHeight if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN) {
};
}
else
{
if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN)
{
// wpengine-texture format always has one mipmap // wpengine-texture format always has one mipmap
// get first image size // get first image size
auto element = this->m_header->images.find (0)->second.begin (); auto element = this->m_header->images.find (0)->second.begin ();
// set the texture resolution // set the texture resolution
this->m_resolution = { this->m_resolution = {(*element)->width, (*element)->height, this->m_header->width, this->m_header->height};
(*element)->width, (*element)->height, } else {
this->m_header->width, this->m_header->height
};
}
else
{
// set the texture resolution // set the texture resolution
this->m_resolution = { this->m_resolution = {this->m_header->textureWidth, this->m_header->textureHeight, this->m_header->width,
this->m_header->textureWidth, this->m_header->textureHeight, this->m_header->height};
this->m_header->width, this->m_header->height
};
} }
} }
if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN) if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN) {
{
internalFormat = GL_RGBA8; internalFormat = GL_RGBA8;
// set some extra information too as it's used for image sizing // set some extra information too as it's used for image sizing
// this ensures that a_TexCoord uses the full image instead of just part of it // this ensures that a_TexCoord uses the full image instead of just part of it
@ -56,33 +40,16 @@ CTexture::CTexture (const void* fileData) :
this->m_header->height = this->m_header->mipmaps [0]->height; this->m_header->height = this->m_header->mipmaps [0]->height;
this->m_header->textureWidth = this->m_header->mipmaps [0]->width; this->m_header->textureWidth = this->m_header->mipmaps [0]->width;
this->m_header->textureHeight = this->m_header->mipmaps [0]->height;*/ this->m_header->textureHeight = this->m_header->mipmaps [0]->height;*/
} } else {
else
{
// detect the image format and hand it to openGL to be used // detect the image format and hand it to openGL to be used
switch (this->m_header->format) switch (this->m_header->format) {
{ case TextureFormat::DXT5: internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
case TextureFormat::DXT5: case TextureFormat::DXT3: internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; case TextureFormat::DXT1: internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
break; case TextureFormat::ARGB8888: internalFormat = GL_RGBA8; break;
case TextureFormat::DXT3: case TextureFormat::R8: internalFormat = GL_R8; break;
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; case TextureFormat::RG88: internalFormat = GL_RG8; break;
break; default: delete this->m_header; sLog.exception ("Cannot determine texture format");
case TextureFormat::DXT1:
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
break;
case TextureFormat::ARGB8888:
internalFormat = GL_RGBA8;
break;
case TextureFormat::R8:
internalFormat = GL_R8;
break;
case TextureFormat::RG88:
internalFormat = GL_RG8;
break;
default:
delete this->m_header;
sLog.exception ("Cannot determine texture format");
} }
} }
@ -94,8 +61,7 @@ CTexture::CTexture (const void* fileData) :
auto imgCur = this->m_header->images.begin (); auto imgCur = this->m_header->images.begin ();
auto imgEnd = this->m_header->images.end (); auto imgEnd = this->m_header->images.end ();
for (int index = 0; imgCur != imgEnd; imgCur ++, index ++) for (int index = 0; imgCur != imgEnd; ++imgCur, index++) {
{
// bind the texture to assign information to it // bind the texture to assign information to it
glBindTexture (GL_TEXTURE_2D, this->m_textureID [index]); glBindTexture (GL_TEXTURE_2D, this->m_textureID [index]);
@ -104,35 +70,28 @@ CTexture::CTexture (const void* fileData) :
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, this->m_header->mipmapCount - 1); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, this->m_header->mipmapCount - 1);
// setup texture wrapping and filtering // setup texture wrapping and filtering
if (this->m_header->flags & TextureFlags::ClampUVs) if (this->m_header->flags & TextureFlags::ClampUVs) {
{
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} } else {
else
{
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
} }
if (this->m_header->flags & TextureFlags::NoInterpolation) if (this->m_header->flags & TextureFlags::NoInterpolation) {
{
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
} } else {
else
{
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
} }
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, 8.0f); glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, 8.0f);
auto cur = (*imgCur).second.begin (); auto cur = imgCur->second.begin ();
auto end = (*imgCur).second.end (); auto end = imgCur->second.end ();
for (int32_t level = 0; cur != end; cur ++, level ++) for (int32_t level = 0; cur != end; ++cur, level++) {
{
FIBITMAP* bitmap = nullptr; FIBITMAP* bitmap = nullptr;
FIBITMAP* converted = nullptr; FIBITMAP* converted = nullptr;
FIMEMORY* memory = nullptr; FIMEMORY* memory = nullptr;
@ -142,9 +101,9 @@ CTexture::CTexture (const void* fileData) :
uint32_t bufferSize = (*cur)->uncompressedSize; uint32_t bufferSize = (*cur)->uncompressedSize;
GLenum textureFormat = GL_RGBA; GLenum textureFormat = GL_RGBA;
if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN) if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN) {
{ memory =
memory = FreeImage_OpenMemory (reinterpret_cast <BYTE *> ((*cur)->uncompressedData), (*cur)->uncompressedSize); FreeImage_OpenMemory (reinterpret_cast<BYTE*> ((*cur)->uncompressedData), (*cur)->uncompressedSize);
// load the image and setup pointers so they can be used // load the image and setup pointers so they can be used
bitmap = FreeImage_LoadFromMemory (this->m_header->freeImageFormat, memory); bitmap = FreeImage_LoadFromMemory (this->m_header->freeImageFormat, memory);
@ -158,47 +117,33 @@ CTexture::CTexture (const void* fileData) :
height = FreeImage_GetHeight (converted); height = FreeImage_GetHeight (converted);
bufferSize = FreeImage_GetMemorySize (converted); bufferSize = FreeImage_GetMemorySize (converted);
textureFormat = GL_BGRA; textureFormat = GL_BGRA;
} } else {
else if (this->m_header->format == TextureFormat::R8) {
{
if (this->m_header->format == TextureFormat::R8)
{
// red textures are 1-byte-per-pixel, so it's alignment has to be set manually // red textures are 1-byte-per-pixel, so it's alignment has to be set manually
glPixelStorei (GL_UNPACK_ALIGNMENT, 1); glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
textureFormat = GL_RED; textureFormat = GL_RED;
} } else if (this->m_header->format == TextureFormat::RG88)
else if (this->m_header->format == TextureFormat::RG88)
textureFormat = GL_RG; textureFormat = GL_RG;
} }
switch (internalFormat) switch (internalFormat) {
{ case GL_RGBA8:
case GL_RGBA8: case GL_RG8:
case GL_RG8: case GL_R8:
case GL_R8: glTexImage2D (GL_TEXTURE_2D, level, internalFormat, width, height, 0, textureFormat,
glTexImage2D ( GL_UNSIGNED_BYTE, dataptr);
GL_TEXTURE_2D, level, internalFormat, break;
width, height, 0, case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
textureFormat, GL_UNSIGNED_BYTE, case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
dataptr case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
); glCompressedTexImage2D (GL_TEXTURE_2D, level, internalFormat, width, height, 0, bufferSize,
break; dataptr);
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: break;
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: default: sLog.exception ("Cannot load texture, unknown format", this->m_header->format);
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
glCompressedTexImage2D (
GL_TEXTURE_2D, level, internalFormat,
width, height, 0,
bufferSize, dataptr
);
break;
default:
sLog.exception ("Cannot load texture, unknown format", this->m_header->format);
} }
// freeimage buffer won't be used anymore, so free memory // freeimage buffer won't be used anymore, so free memory
if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN) if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN) {
{
FreeImage_Unload (bitmap); FreeImage_Unload (bitmap);
FreeImage_Unload (converted); FreeImage_Unload (converted);
FreeImage_CloseMemory (memory); FreeImage_CloseMemory (memory);
@ -207,8 +152,7 @@ CTexture::CTexture (const void* fileData) :
} }
} }
CTexture::~CTexture () CTexture::~CTexture () {
{
if (this->getHeader () == nullptr) if (this->getHeader () == nullptr)
return; return;
@ -216,8 +160,7 @@ CTexture::~CTexture ()
delete this->getHeader (); delete this->getHeader ();
} }
const GLuint CTexture::getTextureID (uint32_t imageIndex) const const GLuint CTexture::getTextureID (uint32_t imageIndex) const {
{
// ensure we do not go out of bounds // ensure we do not go out of bounds
if (imageIndex > this->m_header->imageCount) if (imageIndex > this->m_header->imageCount)
return this->m_textureID [0]; return this->m_textureID [0];
@ -225,87 +168,73 @@ const GLuint CTexture::getTextureID (uint32_t imageIndex) const
return this->m_textureID [imageIndex]; return this->m_textureID [imageIndex];
} }
const uint32_t CTexture::getTextureWidth (uint32_t imageIndex) const const uint32_t CTexture::getTextureWidth (uint32_t imageIndex) const {
{
if (imageIndex > this->m_header->imageCount) if (imageIndex > this->m_header->imageCount)
return this->getHeader ()->textureWidth; return this->getHeader ()->textureWidth;
return (*this->m_header->images [imageIndex].begin ())->width; return (*this->m_header->images [imageIndex].begin ())->width;
} }
const uint32_t CTexture::getTextureHeight (uint32_t imageIndex) const const uint32_t CTexture::getTextureHeight (uint32_t imageIndex) const {
{
if (imageIndex > this->m_header->imageCount) if (imageIndex > this->m_header->imageCount)
return this->getHeader ()->textureHeight; return this->getHeader ()->textureHeight;
return (*this->m_header->images [imageIndex].begin ())->height; return (*this->m_header->images [imageIndex].begin ())->height;
} }
const uint32_t CTexture::getRealWidth () const const uint32_t CTexture::getRealWidth () const {
{
return this->isAnimated () ? this->getHeader ()->gifWidth : this->getHeader ()->width; return this->isAnimated () ? this->getHeader ()->gifWidth : this->getHeader ()->width;
} }
const uint32_t CTexture::getRealHeight () const const uint32_t CTexture::getRealHeight () const {
{
return this->isAnimated () ? this->getHeader ()->gifHeight : this->getHeader ()->height; return this->isAnimated () ? this->getHeader ()->gifHeight : this->getHeader ()->height;
} }
const ITexture::TextureFormat CTexture::getFormat () const const ITexture::TextureFormat CTexture::getFormat () const {
{
return this->getHeader ()->format; return this->getHeader ()->format;
} }
const ITexture::TextureFlags CTexture::getFlags () const const ITexture::TextureFlags CTexture::getFlags () const {
{
return this->getHeader ()->flags; return this->getHeader ()->flags;
} }
const CTexture::TextureHeader* CTexture::getHeader () const const CTexture::TextureHeader* CTexture::getHeader () const {
{
return this->m_header; return this->m_header;
} }
const glm::vec4* CTexture::getResolution () const const glm::vec4* CTexture::getResolution () const {
{
return &this->m_resolution; return &this->m_resolution;
} }
const std::vector<ITexture::TextureFrame*>& CTexture::getFrames () const const std::vector<ITexture::TextureFrame*>& CTexture::getFrames () const {
{
return this->getHeader ()->frames; return this->getHeader ()->frames;
} }
const bool CTexture::isAnimated () const const bool CTexture::isAnimated () const {
{
return this->getHeader ()->isAnimated (); return this->getHeader ()->isAnimated ();
} }
CTexture::TextureMipmap::TextureMipmap () CTexture::TextureMipmap::TextureMipmap () = default;
= default;
CTexture::TextureMipmap::~TextureMipmap () CTexture::TextureMipmap::~TextureMipmap () {
{
if (this->compression == 1) if (this->compression == 1)
delete this->compressedData; delete this->compressedData;
delete this->uncompressedData; delete this->uncompressedData;
} }
void CTexture::TextureMipmap::decompressData () void CTexture::TextureMipmap::decompressData () {
{ if (this->compression != 1) {
if (this->compression == 1) return;
{
this->uncompressedData = new char [this->uncompressedSize];
int result = LZ4_decompress_safe (
this->compressedData, this->uncompressedData,
this->compressedSize, this->uncompressedSize
);
if (!result)
sLog.exception ("Cannot decompress texture data, LZ4_decompress_safe returned an error");
} }
this->uncompressedData = new char [this->uncompressedSize];
const int result = LZ4_decompress_safe (this->compressedData, this->uncompressedData, this->compressedSize,
this->uncompressedSize);
if (!result)
sLog.exception ("Cannot decompress texture data, LZ4_decompress_safe returned an error");
} }
CTexture::TextureFrame::TextureFrame () : CTexture::TextureFrame::TextureFrame () :
@ -316,12 +245,7 @@ CTexture::TextureFrame::TextureFrame () :
width1 (0), width1 (0),
width2 (0), width2 (0),
height1 (0), height1 (0),
height2 (0) height2 (0) {}
{
}
CTexture::TextureFrame::~TextureFrame ()
= default;
CTexture::TextureHeader::TextureHeader () : CTexture::TextureHeader::TextureHeader () :
flags (NoFlags), flags (NoFlags),
@ -333,130 +257,109 @@ CTexture::TextureHeader::TextureHeader () :
gifHeight (0), gifHeight (0),
format (TextureFormat::UNKNOWN), format (TextureFormat::UNKNOWN),
imageCount (0), imageCount (0),
mipmapCount (0) mipmapCount (0) {}
{
}
CTexture::TextureHeader::~TextureHeader () CTexture::TextureHeader::~TextureHeader () {
{ for (const auto& [index, mipmaps] : this->images)
for (const auto& imgCur : this->images) for (const auto cur : mipmaps)
for (auto cur : imgCur.second)
delete cur; delete cur;
} }
CTexture::TextureHeader* CTexture::parseHeader (const char* fileData) CTexture::TextureHeader* CTexture::parseHeader (const char* fileData) {
{
// check the magic value on the header first // check the magic value on the header first
if (memcmp (fileData, "TEXV0005", 9) != 0) if (strncmp (fileData, "TEXV0005", 9) != 0)
sLog.exception ("unexpected texture container type: ", std::string_view (fileData, 9)); sLog.exception ("unexpected texture container type: ", std::string_view (fileData, 9));
// jump to the next value // jump to the next value
fileData += 9; fileData += 9;
// check the sub-magic value on the header // check the sub-magic value on the header
if (memcmp (fileData, "TEXI0001", 9) != 0) if (strncmp (fileData, "TEXI0001", 9) != 0)
sLog.exception ("unexpected texture sub-container type: ", std::string_view (fileData, 9)); sLog.exception ("unexpected texture sub-container type: ", std::string_view (fileData, 9));
// jump through the string again // jump through the string again
fileData += 9; fileData += 9;
auto* header = new TextureHeader; auto* header = new TextureHeader;
const auto* pointer = reinterpret_cast <const uint32_t*> (fileData); const auto* pointer = reinterpret_cast<const uint32_t*> (fileData);
header->format = static_cast <TextureFormat>(*pointer ++); header->format = static_cast<TextureFormat> (*pointer++);
header->flags = static_cast <TextureFlags> (*pointer ++); header->flags = static_cast<TextureFlags> (*pointer++);
header->textureWidth = *pointer ++; header->textureWidth = *pointer++;
header->textureHeight = *pointer ++; header->textureHeight = *pointer++;
header->width = *pointer ++; header->width = *pointer++;
header->height = *pointer ++; header->height = *pointer++;
pointer ++; // ignore some more bytes pointer++; // ignore some more bytes
// now we're going to parse some more data that is string // now we're going to parse some more data that is string
// so get the current position back as string // so get the current position back as string
fileData = reinterpret_cast <const char*> (pointer); fileData = reinterpret_cast<const char*> (pointer);
// get the position of what comes after the texture data // get the position of what comes after the texture data
pointer = reinterpret_cast <const uint32_t*> (fileData + 9); pointer = reinterpret_cast<const uint32_t*> (fileData + 9);
if (memcmp (fileData, "TEXB0003", 9) == 0) if (strncmp (fileData, "TEXB0003", 9) == 0) {
{
header->containerVersion = ContainerVersion::TEXB0003; header->containerVersion = ContainerVersion::TEXB0003;
header->imageCount = *pointer ++; header->imageCount = *pointer++;
header->freeImageFormat = static_cast <FREE_IMAGE_FORMAT> (*pointer++); header->freeImageFormat = static_cast<FREE_IMAGE_FORMAT> (*pointer++);
} } else if (strncmp (fileData, "TEXB0002", 9) == 0) {
else if(memcmp (fileData, "TEXB0002", 9) == 0)
{
header->containerVersion = ContainerVersion::TEXB0002; header->containerVersion = ContainerVersion::TEXB0002;
header->imageCount = *pointer ++; header->imageCount = *pointer++;
} } else if (strncmp (fileData, "TEXB0001", 9) == 0) {
else if (memcmp (fileData, "TEXB0001", 9) == 0)
{
header->containerVersion = ContainerVersion::TEXB0001; header->containerVersion = ContainerVersion::TEXB0001;
header->imageCount = *pointer ++; header->imageCount = *pointer++;
} } else {
else
{
delete header; delete header;
sLog.exception ("unknown texture format type: ", std::string_view (fileData, 9)); sLog.exception ("unknown texture format type: ", std::string_view (fileData, 9));
} }
for (uint32_t image = 0; image < header->imageCount; image ++) for (uint32_t image = 0; image < header->imageCount; image++) {
{
// read the number of mipmaps available for this image // read the number of mipmaps available for this image
header->mipmapCount = *pointer ++; header->mipmapCount = *pointer++;
std::vector <TextureMipmap*> mipmaps; std::vector<TextureMipmap*> mipmaps;
fileData = reinterpret_cast <const char*> (pointer); fileData = reinterpret_cast<const char*> (pointer);
for (uint32_t i = 0; i < header->mipmapCount; i ++) for (uint32_t i = 0; i < header->mipmapCount; i++)
mipmaps.emplace_back (parseMipmap (header, &fileData)); mipmaps.emplace_back (parseMipmap (header, &fileData));
// add the pixmaps back // add the pixmaps back
header->images.insert (std::pair <uint32_t, std::vector <TextureMipmap*>> (image, mipmaps)); header->images.insert (std::pair (image, mipmaps));
pointer = reinterpret_cast <const uint32_t*> (fileData); pointer = reinterpret_cast<const uint32_t*> (fileData);
} }
// gifs have extra information after the mipmaps // gifs have extra information after the mipmaps
if (header->isAnimated () == true) if (header->isAnimated () == true) {
{ if (strncmp (fileData, "TEXS0002", 9) == 0) {
if (memcmp (fileData, "TEXS0002", 9) == 0)
{
header->animatedVersion = AnimatedVersion::TEXS0002; header->animatedVersion = AnimatedVersion::TEXS0002;
} } else if (strncmp (fileData, "TEXS0003", 9) == 0) {
else if (memcmp (fileData, "TEXS0003", 9) == 0)
{
header->animatedVersion = AnimatedVersion::TEXS0003; header->animatedVersion = AnimatedVersion::TEXS0003;
} } else {
else
{
delete header; delete header;
sLog.exception ("found animation information of unknown type: ", std::string_view (fileData, 9)); sLog.exception ("found animation information of unknown type: ", std::string_view (fileData, 9));
} }
// get an integer pointer back to read the frame count // get an integer pointer back to read the frame count
pointer = reinterpret_cast <const uint32_t*> (fileData + 9); pointer = reinterpret_cast<const uint32_t*> (fileData + 9);
uint32_t framecount = *pointer++; uint32_t framecount = *pointer++;
if (header->animatedVersion == AnimatedVersion::TEXS0003) if (header->animatedVersion == AnimatedVersion::TEXS0003) {
{
// ignore two extra integers as those are width and height of the git // ignore two extra integers as those are width and height of the git
header->gifWidth = *pointer ++; header->gifWidth = *pointer++;
header->gifHeight = *pointer ++; header->gifHeight = *pointer++;
} }
// get back the pointer into filedata // get back the pointer into filedata
fileData = reinterpret_cast <const char*> (pointer); fileData = reinterpret_cast<const char*> (pointer);
while (framecount > 0) while (framecount > 0) {
{
// add the frame to the list // add the frame to the list
header->frames.push_back (parseAnimation (&fileData)); header->frames.push_back (parseAnimation (&fileData));
framecount --; framecount--;
} }
// ensure gif width and height is right for TEXS0002 // ensure gif width and height is right for TEXS0002
if (header->animatedVersion == AnimatedVersion::TEXS0002) if (header->animatedVersion == AnimatedVersion::TEXS0002) {
{ const TextureFrame* first = *header->frames.begin ();
TextureFrame* first = *header->frames.begin ();
header->gifWidth = first->width1; header->gifWidth = first->width1;
header->gifHeight = first->height1; header->gifHeight = first->height1;
@ -466,50 +369,47 @@ CTexture::TextureHeader* CTexture::parseHeader (const char* fileData)
return header; return header;
} }
CTexture::TextureFrame* CTexture::parseAnimation (const char** originalFileData) CTexture::TextureFrame* CTexture::parseAnimation (const char** originalFileData) {
{
const char* fileData = *originalFileData; const char* fileData = *originalFileData;
// get back the pointer into integer // get back the pointer into integer
const auto* pointer = reinterpret_cast <const uint32_t*> (fileData); const auto* pointer = reinterpret_cast<const uint32_t*> (fileData);
// start reading frame information // start reading frame information
auto* frame = new TextureFrame(); auto* frame = new TextureFrame ();
frame->frameNumber = *pointer++; frame->frameNumber = *pointer++;
// reinterpret the pointer into float // reinterpret the pointer into float
const auto* fPointer = reinterpret_cast <const float*> (pointer); const auto* fPointer = reinterpret_cast<const float*> (pointer);
frame->frametime = *fPointer ++; frame->frametime = *fPointer++;
frame->x = *fPointer ++; frame->x = *fPointer++;
frame->y = *fPointer ++; frame->y = *fPointer++;
frame->width1 = *fPointer ++; frame->width1 = *fPointer++;
frame->width2 = *fPointer ++; frame->width2 = *fPointer++;
frame->height2 = *fPointer ++; frame->height2 = *fPointer++;
frame->height1 = *fPointer ++; frame->height1 = *fPointer++;
// get back the pointer into fileData so it can be reused later // get back the pointer into fileData so it can be reused later
*originalFileData = reinterpret_cast <const char*> (fPointer); *originalFileData = reinterpret_cast<const char*> (fPointer);
return frame; return frame;
} }
CTexture::TextureMipmap* CTexture::parseMipmap (TextureHeader* header, const char** originalFileData) CTexture::TextureMipmap* CTexture::parseMipmap (const TextureHeader* header, const char** originalFileData) {
{
auto* mipmap = new TextureMipmap (); auto* mipmap = new TextureMipmap ();
// get the current position // get the current position
const char* fileData = *originalFileData; const char* fileData = *originalFileData;
// get an integer pointer // get an integer pointer
const auto* pointer = reinterpret_cast <const uint32_t*> (fileData); const auto* pointer = reinterpret_cast<const uint32_t*> (fileData);
mipmap->width = *pointer++; mipmap->width = *pointer++;
mipmap->height = *pointer++; mipmap->height = *pointer++;
if (header->containerVersion == ContainerVersion::TEXB0002 || if (header->containerVersion == ContainerVersion::TEXB0002 ||
header->containerVersion == ContainerVersion::TEXB0003) header->containerVersion == ContainerVersion::TEXB0003) {
{
mipmap->compression = *pointer++; mipmap->compression = *pointer++;
mipmap->uncompressedSize = *pointer++; mipmap->uncompressedSize = *pointer++;
} }
@ -517,10 +417,9 @@ CTexture::TextureMipmap* CTexture::parseMipmap (TextureHeader* header, const cha
mipmap->compressedSize = *pointer++; mipmap->compressedSize = *pointer++;
// get back a normal char pointer // get back a normal char pointer
fileData = reinterpret_cast <const char*> (pointer); fileData = reinterpret_cast<const char*> (pointer);
if (mipmap->compression == 0) if (mipmap->compression == 0) {
{
// this might be better named as mipmap_bytes_size instead of compressedSize // this might be better named as mipmap_bytes_size instead of compressedSize
// as in uncompressed files this variable actually holds the file length // as in uncompressed files this variable actually holds the file length
mipmap->uncompressedSize = mipmap->compressedSize; mipmap->uncompressedSize = mipmap->compressedSize;
@ -528,8 +427,7 @@ CTexture::TextureMipmap* CTexture::parseMipmap (TextureHeader* header, const cha
mipmap->uncompressedData = new char [mipmap->uncompressedSize]; mipmap->uncompressedData = new char [mipmap->uncompressedSize];
if (mipmap->compression == 1) if (mipmap->compression == 1) {
{
mipmap->compressedData = new char [mipmap->compressedSize]; mipmap->compressedData = new char [mipmap->compressedSize];
memcpy (mipmap->compressedData, fileData, mipmap->compressedSize); memcpy (mipmap->compressedData, fileData, mipmap->compressedSize);
@ -537,9 +435,7 @@ CTexture::TextureMipmap* CTexture::parseMipmap (TextureHeader* header, const cha
mipmap->decompressData (); mipmap->decompressData ();
// advance to the end of the mipmap // advance to the end of the mipmap
fileData += mipmap->compressedSize; fileData += mipmap->compressedSize;
} } else {
else
{
memcpy (mipmap->uncompressedData, fileData, mipmap->uncompressedSize); memcpy (mipmap->uncompressedData, fileData, mipmap->uncompressedSize);
// advance to the end of the mipmap // advance to the end of the mipmap
fileData += mipmap->uncompressedSize; fileData += mipmap->uncompressedSize;
@ -551,7 +447,6 @@ CTexture::TextureMipmap* CTexture::parseMipmap (TextureHeader* header, const cha
return mipmap; return mipmap;
} }
bool CTexture::TextureHeader::isAnimated () const bool CTexture::TextureHeader::isAnimated () const {
{
return this->flags & TextureFlags::IsGif; return this->flags & TextureFlags::IsGif;
} }

View File

@ -10,166 +10,159 @@
#include <string> #include <string>
#include <vector> #include <vector>
namespace WallpaperEngine::Assets namespace WallpaperEngine::Assets {
{ /**
* A normal texture file in WallpaperEngine's format
*/
class CTexture final : public ITexture {
/** /**
* A normal texture file in WallpaperEngine's format * Different texture container versions supported
*/ */
class CTexture : public ITexture enum ContainerVersion : int {
{ UNKNOWN = -1,
private: TEXB0003 = 3,
/** TEXB0002 = 2,
* Different texture container versions supported TEXB0001 = 1
*/
enum ContainerVersion : int
{
UNKNOWN = -1,
TEXB0003 = 3,
TEXB0002 = 2,
TEXB0001 = 1
};
/**
* Different texture animation versions supported
*/
enum AnimatedVersion : int
{
TEXSUNKN = -1,
TEXS0002 = 0,
TEXS0003 = 1,
};
/**
* Texture mipmap data
*/
class TextureMipmap
{
public:
TextureMipmap ();
~TextureMipmap ();
/** Width of the mipmap */
uint32_t width = 0;
/** Height of the mipmap */
uint32_t height = 0;
/** If the mipmap data is compressed */
uint32_t compression = 0;
/** Uncompressed size of the mipmap */
uint32_t uncompressedSize = 0;
/** Compress size of the mipmap */
uint32_t compressedSize = 0;
/** Pointer to the compressed data */
char* compressedData = nullptr;
/** Pointer to the uncompressed data */
char* uncompressedData = nullptr;
/**
* Performs actual decompression of the compressed data
*/
void decompressData ();
};
/**
* Texture header data
*/
class TextureHeader
{
public:
TextureHeader ();
~TextureHeader ();
[[nodiscard]] bool isAnimated () const;
/** The version of the texture container */
ContainerVersion containerVersion = ContainerVersion::UNKNOWN;
/** The version of the animated data */
AnimatedVersion animatedVersion = AnimatedVersion::TEXSUNKN;
/** Flags with extra texture information */
TextureFlags flags;
/** Real width of the texture */
uint32_t width;
/** Real height of the texture */
uint32_t height;
/** Texture width in memory (power of 2) */
uint32_t textureWidth;
/** Texture height in memory (power of 2) */
uint32_t textureHeight;
/** Gif width */
uint32_t gifWidth;
/** Gif height */
uint32_t gifHeight;
/** Texture data format */
TextureFormat format;
/** Free Image format */
FREE_IMAGE_FORMAT freeImageFormat = FREE_IMAGE_FORMAT::FIF_UNKNOWN;
/** The amount of images in the texture file */
uint32_t imageCount;
/** Number of mipmap levels on the texture */
uint32_t mipmapCount;
/** List of mipmaps */
std::map<uint32_t, std::vector<TextureMipmap*>> images;
/** List of animation frames */
std::vector<TextureFrame*> frames;
};
public:
explicit CTexture (const void* fileData);
~CTexture ();
/** @inheritdoc */
[[nodiscard]] const GLuint getTextureID (uint32_t imageIndex = 0) const override;
/** @inheritdoc */
[[nodiscard]] const uint32_t getTextureWidth (uint32_t imageIndex = 0) const override;
/** @inheritdoc */
[[nodiscard]] const uint32_t getTextureHeight (uint32_t imageIndex = 0) const override;
/** @inheritdoc */
[[nodiscard]] const uint32_t getRealWidth () const override;
/** @inheritdoc */
[[nodiscard]] const uint32_t getRealHeight () const override;
/** @inheritdoc */
[[nodiscard]] const TextureFormat getFormat () const override;
/** @inheritdoc */
[[nodiscard]] const TextureFlags getFlags () const override;
/** @inheritdoc */
[[nodiscard]] const glm::vec4* getResolution () const override;
/** @inheritdoc */
[[nodiscard]] const std::vector<TextureFrame*>& getFrames () const override;
/** @inheritdoc */
[[nodiscard]] const bool isAnimated () const override;
private:
/**
* @return The texture header
*/
[[nodiscard]] const TextureHeader* getHeader () const;
/**
* Tries to parse a header off the given data pointer
*
* @param fileData The point at which to start reading data off from
* @return
*/
static TextureHeader* parseHeader (const char* fileData);
/**
* Tries to parse an animation frame off the given data pointer
*
* @param originalFileData The point at which to start reading data off from
* @return
*/
static TextureFrame* parseAnimation (const char** originalFileData);
/**
* Tries to parse mipmap information off the given data pointer
*
* @param header The file header
* @param fileData The point at which to start reading data off from
* @return
*/
static TextureMipmap* parseMipmap (TextureHeader* header, const char** fileData);
/** The texture header */
TextureHeader* m_header;
/** OpenGL's texture ID */
GLuint* m_textureID;
/** Resolution vector of the texture */
glm::vec4 m_resolution;
}; };
}
/**
* Different texture animation versions supported
*/
enum AnimatedVersion : int {
TEXSUNKN = -1,
TEXS0002 = 0,
TEXS0003 = 1,
};
/**
* Texture mipmap data
*/
class TextureMipmap {
public:
TextureMipmap ();
~TextureMipmap ();
/** Width of the mipmap */
uint32_t width = 0;
/** Height of the mipmap */
uint32_t height = 0;
/** If the mipmap data is compressed */
uint32_t compression = 0;
/** Uncompressed size of the mipmap */
uint32_t uncompressedSize = 0;
/** Compress size of the mipmap */
uint32_t compressedSize = 0;
/** Pointer to the compressed data */
char* compressedData = nullptr;
/** Pointer to the uncompressed data */
char* uncompressedData = nullptr;
/**
* Performs actual decompression of the compressed data
*/
void decompressData ();
};
/**
* Texture header data
*/
class TextureHeader {
public:
TextureHeader ();
~TextureHeader ();
[[nodiscard]] bool isAnimated () const;
/** The version of the texture container */
ContainerVersion containerVersion = ContainerVersion::UNKNOWN;
/** The version of the animated data */
AnimatedVersion animatedVersion = AnimatedVersion::TEXSUNKN;
/** Flags with extra texture information */
TextureFlags flags;
/** Real width of the texture */
uint32_t width;
/** Real height of the texture */
uint32_t height;
/** Texture width in memory (power of 2) */
uint32_t textureWidth;
/** Texture height in memory (power of 2) */
uint32_t textureHeight;
/** Gif width */
uint32_t gifWidth;
/** Gif height */
uint32_t gifHeight;
/** Texture data format */
TextureFormat format;
/** Free Image format */
FREE_IMAGE_FORMAT freeImageFormat = FREE_IMAGE_FORMAT::FIF_UNKNOWN;
/** The amount of images in the texture file */
uint32_t imageCount;
/** Number of mipmap levels on the texture */
uint32_t mipmapCount;
/** List of mipmaps */
std::map<uint32_t, std::vector<TextureMipmap*>> images;
/** List of animation frames */
std::vector<TextureFrame*> frames;
};
public:
explicit CTexture (const void* fileData);
~CTexture () override;
/** @inheritdoc */
[[nodiscard]] const GLuint getTextureID (uint32_t imageIndex = 0) const override;
/** @inheritdoc */
[[nodiscard]] const uint32_t getTextureWidth (uint32_t imageIndex = 0) const override;
/** @inheritdoc */
[[nodiscard]] const uint32_t getTextureHeight (uint32_t imageIndex = 0) const override;
/** @inheritdoc */
[[nodiscard]] const uint32_t getRealWidth () const override;
/** @inheritdoc */
[[nodiscard]] const uint32_t getRealHeight () const override;
/** @inheritdoc */
[[nodiscard]] const TextureFormat getFormat () const override;
/** @inheritdoc */
[[nodiscard]] const TextureFlags getFlags () const override;
/** @inheritdoc */
[[nodiscard]] const glm::vec4* getResolution () const override;
/** @inheritdoc */
[[nodiscard]] const std::vector<TextureFrame*>& getFrames () const override;
/** @inheritdoc */
[[nodiscard]] const bool isAnimated () const override;
private:
/**
* @return The texture header
*/
[[nodiscard]] const TextureHeader* getHeader () const;
/**
* Tries to parse a header off the given data pointer
*
* @param fileData The point at which to start reading data off from
* @return
*/
static TextureHeader* parseHeader (const char* fileData);
/**
* Tries to parse an animation frame off the given data pointer
*
* @param originalFileData The point at which to start reading data off from
* @return
*/
static TextureFrame* parseAnimation (const char** originalFileData);
/**
* Tries to parse mipmap information off the given data pointer
*
* @param header The file header
* @param fileData The point at which to start reading data off from
* @return
*/
static TextureMipmap* parseMipmap (const TextureHeader* header, const char** fileData);
/** The texture header */
TextureHeader* m_header;
/** OpenGL's texture ID */
GLuint* m_textureID;
/** Resolution vector of the texture */
glm::vec4 m_resolution;
};
} // namespace WallpaperEngine::Assets

View File

@ -1,19 +1,15 @@
#include <memory.h> #include <memory.h>
#include "CVirtualContainer.h"
#include "CAssetLoadException.h" #include "CAssetLoadException.h"
#include "CVirtualContainer.h"
using namespace WallpaperEngine::Assets; using namespace WallpaperEngine::Assets;
void CVirtualContainer::add (const std::string& filename, void* contents, uint32_t length) void CVirtualContainer::add (const std::string& filename, const char* contents, uint32_t length) {
{ this->m_virtualFiles.insert (std::make_pair (filename, new CFileEntry (contents, length)));
this->m_virtualFiles.insert (
std::make_pair (filename, CFileEntry (contents, length))
);
} }
void CVirtualContainer::add (const std::string& filename, const std::string& contents) void CVirtualContainer::add (const std::string& filename, const std::string& contents) {
{
char* copy = new char [contents.length () + 1]; char* copy = new char [contents.length () + 1];
// copy the text AND the \0 // copy the text AND the \0
@ -23,14 +19,19 @@ void CVirtualContainer::add (const std::string& filename, const std::string& con
this->add (filename, copy, contents.length () + 1); this->add (filename, copy, contents.length () + 1);
} }
const void* CVirtualContainer::readFile (const std::string& filename, uint32_t* length) const const void* CVirtualContainer::readFile (const std::string& filename, uint32_t* length) const {
{ const auto cur = this->m_virtualFiles.find (filename);
auto cur = this->m_virtualFiles.find (filename);
if (cur == this->m_virtualFiles.end ()) if (cur == this->m_virtualFiles.end ())
throw CAssetLoadException (filename, "Cannot find file in the virtual container"); throw CAssetLoadException (filename, "Cannot find file in the virtual container");
*length = (*cur).second.length; if (length != nullptr)
*length = cur->second->length;
return (*cur).second.address; // clone original first
char* result = new char [cur->second->length];
memcpy (result, cur->second->address, cur->second->length);
return result;
} }

View File

@ -1,43 +1,38 @@
#pragma once #pragma once
#include <string>
#include <map> #include <map>
#include <string>
#include "CFileEntry.h"
#include "CContainer.h" #include "CContainer.h"
#include "CFileEntry.h"
namespace WallpaperEngine::Assets namespace WallpaperEngine::Assets {
{ /**
* Virtual container implementation, provides virtual files for the backgrounds to use
*/
class CVirtualContainer final : public CContainer {
public:
/** /**
* Virtual container implementation, provides virtual files for the backgrounds to use * Adds a new file to the virtual container
*
* @param filename
* @param contents
* @param length
*/ */
class CVirtualContainer : public CContainer void add (const std::string& filename, const char* contents, uint32_t length);
{
public:
CVirtualContainer () = default;
~CVirtualContainer () = default;
/** /**
* Adds a new file to the virtual container * Adds a new file to the virtual container
* *
* @param filename * @param filename
* @param contents * @param contents
* @param length */
*/ void add (const std::string& filename, const std::string& contents);
void add (const std::string& filename, void* contents, uint32_t length); /** @inheritdoc */
const void* readFile (const std::string& filename, uint32_t* length) const override;
/** private:
* Adds a new file to the virtual container /** The recorded files in this virtual container */
* std::map<std::string, CFileEntry*> m_virtualFiles;
* @param filename };
* @param contents } // namespace WallpaperEngine::Assets
*/
void add (const std::string& filename, const std::string& contents);
/** @inheritdoc */
const void* readFile (const std::string& filename, uint32_t* length) const override;
private:
/** The recorded files in this virtual container */
std::map <std::string, CFileEntry> m_virtualFiles;
};
}

View File

@ -4,116 +4,113 @@
#include <glm/vec4.hpp> #include <glm/vec4.hpp>
#include <vector> #include <vector>
namespace WallpaperEngine::Assets namespace WallpaperEngine::Assets {
{ /**
* Base interface that describes the minimum information required for a texture
* to be displayed by the engine
*/
class ITexture {
public:
virtual ~ITexture () = default;
/** /**
* Base interface that describes the minimum information required for a texture * Texture frame information for animated textures
* to be displayed by the engine
*/ */
class ITexture class TextureFrame final {
{ public:
public: TextureFrame ();
/** virtual ~TextureFrame () = default;
* Texture frame information for animated textures
*/
class TextureFrame
{
public:
TextureFrame();
~TextureFrame();
/** The image index of this frame */ /** The image index of this frame */
uint32_t frameNumber; uint32_t frameNumber;
/** The amount of time this frame spends being displayed */ /** The amount of time this frame spends being displayed */
float frametime; float frametime;
/** The x position of the frame in the texture */ /** The x position of the frame in the texture */
float x; float x;
/** The y position of the frame in the texture */ /** The y position of the frame in the texture */
float y; float y;
/** The width of the frame in the texture */ /** The width of the frame in the texture */
float width1; float width1;
float width2; float width2;
float height2; float height2;
/** The height of the frame in the texture */ /** The height of the frame in the texture */
float height1; float height1;
};
/**
* Data formats for textures in memory
*/
enum TextureFormat : uint32_t
{
UNKNOWN = 0xFFFFFFFF,
ARGB8888 = 0,
RGB888 = 1,
RGB565 = 2,
DXT5 = 4,
DXT3 = 6,
DXT1 = 7,
RG88 = 8,
R8 = 9,
RG1616f = 10,
R16f = 11,
BC7 = 12,
RGBa1010102 = 13,
RGBA16161616f = 14,
RGB161616f = 15,
};
/**
* Different settings of the textures
*/
enum TextureFlags : uint32_t
{
NoFlags = 0,
NoInterpolation = 1,
ClampUVs = 2,
IsGif = 4,
ClampUVsBorder = 8,
};
/**
* @param imageIndex For animated textures, the frame to get the ID of
* @return The OpenGL texture to use when rendering
*/
[[nodiscard]] virtual const GLuint getTextureID (uint32_t imageIndex = 0) const = 0;
/**
* @param imageIndex For animated textures, the frame to get the ID of
* @return The texture's width
*/
[[nodiscard]] virtual const uint32_t getTextureWidth (uint32_t imageIndex = 0) const = 0;
/**
* @param imageIndex For animated textures, the frame to get the ID of
* @return The texture's height
*/
[[nodiscard]] virtual const uint32_t getTextureHeight (uint32_t imageIndex = 0) const = 0;
/**
* @return The textures real width
*/
[[nodiscard]] virtual const uint32_t getRealWidth () const = 0;
/**
* @return The textures real height
*/
[[nodiscard]] virtual const uint32_t getRealHeight () const = 0;
/**
* @return The texture's memory format
*/
[[nodiscard]] virtual const TextureFormat getFormat () const = 0;
/**
* @return The texture's settings
*/
[[nodiscard]] virtual const TextureFlags getFlags () const = 0;
/**
* @return The list of frames this texture has
*/
[[nodiscard]] virtual const std::vector<TextureFrame*>& getFrames () const = 0;
/**
* @return The texture's resolution vector
*/
[[nodiscard]] virtual const glm::vec4* getResolution () const = 0;
/**
* @return If the texture is animated or not
*/
[[nodiscard]] virtual const bool isAnimated () const = 0;
}; };
}
/**
* Data formats for textures in memory
*/
enum TextureFormat : uint32_t {
UNKNOWN = 0xFFFFFFFF,
ARGB8888 = 0,
RGB888 = 1,
RGB565 = 2,
DXT5 = 4,
DXT3 = 6,
DXT1 = 7,
RG88 = 8,
R8 = 9,
RG1616f = 10,
R16f = 11,
BC7 = 12,
RGBa1010102 = 13,
RGBA16161616f = 14,
RGB161616f = 15,
};
/**
* Different settings of the textures
*/
enum TextureFlags : uint32_t {
NoFlags = 0,
NoInterpolation = 1,
ClampUVs = 2,
IsGif = 4,
ClampUVsBorder = 8,
};
/**
* @param imageIndex For animated textures, the frame to get the ID of
* @return The OpenGL texture to use when rendering
*/
[[nodiscard]] virtual const GLuint getTextureID (uint32_t imageIndex = 0) const = 0;
/**
* @param imageIndex For animated textures, the frame to get the ID of
* @return The texture's width
*/
[[nodiscard]] virtual const uint32_t getTextureWidth (uint32_t imageIndex = 0) const = 0;
/**
* @param imageIndex For animated textures, the frame to get the ID of
* @return The texture's height
*/
[[nodiscard]] virtual const uint32_t getTextureHeight (uint32_t imageIndex = 0) const = 0;
/**
* @return The textures real width
*/
[[nodiscard]] virtual const uint32_t getRealWidth () const = 0;
/**
* @return The textures real height
*/
[[nodiscard]] virtual const uint32_t getRealHeight () const = 0;
/**
* @return The texture's memory format
*/
[[nodiscard]] virtual const TextureFormat getFormat () const = 0;
/**
* @return The texture's settings
*/
[[nodiscard]] virtual const TextureFlags getFlags () const = 0;
/**
* @return The list of frames this texture has
*/
[[nodiscard]] virtual const std::vector<TextureFrame*>& getFrames () const = 0;
/**
* @return The texture's resolution vector
*/
[[nodiscard]] virtual const glm::vec4* getResolution () const = 0;
/**
* @return If the texture is animated or not
*/
[[nodiscard]] virtual const bool isAnimated () const = 0;
};
} // namespace WallpaperEngine::Assets

View File

@ -1,40 +1,30 @@
#include "CAudioContext.h" #include "CAudioContext.h"
#include "WallpaperEngine/Audio/Drivers/CAudioDriver.h" #include "WallpaperEngine/Audio/Drivers/CAudioDriver.h"
namespace WallpaperEngine::Audio namespace WallpaperEngine::Audio {
{ CAudioContext::CAudioContext (Drivers::CAudioDriver& driver) : m_driver (driver) {}
CAudioContext::CAudioContext (Drivers::CAudioDriver& driver) :
m_driver (driver)
{
}
void CAudioContext::addStream (CAudioStream* stream) void CAudioContext::addStream (CAudioStream* stream) {
{ this->m_driver.addStream (stream);
this->m_driver.addStream (stream);
}
AVSampleFormat CAudioContext::getFormat () const
{
return this->m_driver.getFormat ();
}
int CAudioContext::getSampleRate () const
{
return this->m_driver.getSampleRate ();
}
int CAudioContext::getChannels () const
{
return this->m_driver.getChannels ();
}
Application::CApplicationContext& CAudioContext::getApplicationContext ()
{
return this->m_driver.getApplicationContext ();
}
Drivers::Recorders::CPlaybackRecorder& CAudioContext::getRecorder ()
{
return this->m_driver.getRecorder ();
}
} }
AVSampleFormat CAudioContext::getFormat () const {
return this->m_driver.getFormat ();
}
int CAudioContext::getSampleRate () const {
return this->m_driver.getSampleRate ();
}
int CAudioContext::getChannels () const {
return this->m_driver.getChannels ();
}
Application::CApplicationContext& CAudioContext::getApplicationContext () {
return this->m_driver.getApplicationContext ();
}
Drivers::Recorders::CPlaybackRecorder& CAudioContext::getRecorder () {
return this->m_driver.getRecorder ();
}
} // namespace WallpaperEngine::Audio

View File

@ -3,68 +3,62 @@
#include <libavutil/samplefmt.h> #include <libavutil/samplefmt.h>
#include <vector> #include <vector>
#include "WallpaperEngine/Audio/Drivers/Recorders/CPulseAudioPlaybackRecorder.h"
#include "WallpaperEngine/Application/CApplicationContext.h" #include "WallpaperEngine/Application/CApplicationContext.h"
#include "WallpaperEngine/Audio/Drivers/Recorders/CPulseAudioPlaybackRecorder.h"
namespace WallpaperEngine namespace WallpaperEngine {
{ namespace Application {
namespace Application class CApplicationContext;
{
class CApplicationContext;
}
namespace Audio
{
namespace Drivers
{
class CAudioDriver;
namespace Recorders
{
class CPulseAudioPlaybackRecorder;
}
}
class CAudioStream;
class CAudioContext
{
public:
explicit CAudioContext (Drivers::CAudioDriver& driver);
/**
* Registers the given stream in the driver for playing
*
* @param stream
*/
void addStream (CAudioStream* stream);
/**
* TODO: MAYBE THIS SHOULD BE OUR OWN DEFINITIONS INSTEAD OF LIBRARY SPECIFIC ONES?
*
* @return The audio format the driver supports
*/
[[nodiscard]] AVSampleFormat getFormat () const;
/**
* @return The sample rate the driver supports
*/
[[nodiscard]] int getSampleRate () const;
/**
* @return The channels the driver supports
*/
[[nodiscard]] int getChannels () const;
/**
* @return The application context under which the audio driver is initialized
*/
Application::CApplicationContext& getApplicationContext ();
/**
* @return The audio recorder to use to capture stereo mix data
*/
[[nodiscard]] Drivers::Recorders::CPlaybackRecorder& getRecorder ();
private:
/** The audio driver in use */
Drivers::CAudioDriver& m_driver;
};
}
} }
namespace Audio {
namespace Drivers {
class CAudioDriver;
namespace Recorders {
class CPulseAudioPlaybackRecorder;
}
} // namespace Drivers
class CAudioStream;
class CAudioContext {
public:
explicit CAudioContext (Drivers::CAudioDriver& driver);
/**
* Registers the given stream in the driver for playing
*
* @param stream
*/
void addStream (CAudioStream* stream);
/**
* TODO: MAYBE THIS SHOULD BE OUR OWN DEFINITIONS INSTEAD OF LIBRARY SPECIFIC ONES?
*
* @return The audio format the driver supports
*/
[[nodiscard]] AVSampleFormat getFormat () const;
/**
* @return The sample rate the driver supports
*/
[[nodiscard]] int getSampleRate () const;
/**
* @return The channels the driver supports
*/
[[nodiscard]] int getChannels () const;
/**
* @return The application context under which the audio driver is initialized
*/
Application::CApplicationContext& getApplicationContext ();
/**
* @return The audio recorder to use to capture stereo mix data
*/
[[nodiscard]] Drivers::Recorders::CPlaybackRecorder& getRecorder ();
private:
/** The audio driver in use */
Drivers::CAudioDriver& m_driver;
};
} // namespace Audio
} // namespace WallpaperEngine

View File

@ -1,5 +1,5 @@
#include "common.h"
#include "CAudioStream.h" #include "CAudioStream.h"
#include "common.h"
#include <cassert> #include <cassert>
#include <iostream> #include <iostream>
#include <math.h> #include <math.h>
@ -10,25 +10,20 @@
using namespace WallpaperEngine::Audio; using namespace WallpaperEngine::Audio;
int audio_read_thread (void* arg) int audio_read_thread (void* arg) {
{
SDL_mutex* waitMutex = SDL_CreateMutex (); SDL_mutex* waitMutex = SDL_CreateMutex ();
auto* stream = static_cast <CAudioStream*> (arg); auto* stream = static_cast<CAudioStream*> (arg);
AVPacket* packet = av_packet_alloc (); AVPacket* packet = av_packet_alloc ();
int ret = 0; int ret = 0;
if (waitMutex == nullptr) if (waitMutex == nullptr)
sLog.exception ("Cannot create mutex for audio playback waiting"); sLog.exception ("Cannot create mutex for audio playback waiting");
while (ret >= 0 && stream->getAudioContext ().getApplicationContext ().state.general.keepRunning) while (ret >= 0 && stream->getAudioContext ().getApplicationContext ().state.general.keepRunning) {
{
// give the cpu some time to play the queued frames if there's enough info there // give the cpu some time to play the queued frames if there's enough info there
if ( if (stream->getQueueSize () >= MAX_QUEUE_SIZE ||
stream->getQueueSize () >= MAX_QUEUE_SIZE || (stream->getQueuePacketCount () > MIN_FRAMES &&
(stream->getQueuePacketCount () > MIN_FRAMES && (av_q2d (stream->getTimeBase ()) * stream->getQueueDuration () > 1.0))) {
(av_q2d (stream->getTimeBase ()) * stream->getQueueDuration () > 1.0))
)
{
SDL_LockMutex (waitMutex); SDL_LockMutex (waitMutex);
SDL_CondWaitTimeout (stream->getWaitCondition (), waitMutex, 10); SDL_CondWaitTimeout (stream->getWaitCondition (), waitMutex, 10);
SDL_UnlockMutex (waitMutex); SDL_UnlockMutex (waitMutex);
@ -37,14 +32,13 @@ int audio_read_thread (void* arg)
ret = av_read_frame (stream->getFormatContext (), packet); ret = av_read_frame (stream->getFormatContext (), packet);
if (ret == AVERROR_EOF) if (ret == AVERROR_EOF) {
{
// seek to the beginning of the file again // seek to the beginning of the file again
avformat_seek_file (stream->getFormatContext (), stream->getAudioStream (), 0, 0, 0, ~AVSEEK_FLAG_FRAME); avformat_seek_file (stream->getFormatContext (), stream->getAudioStream (), 0, 0, 0, ~AVSEEK_FLAG_FRAME);
avcodec_flush_buffers (stream->getContext ()); avcodec_flush_buffers (stream->getContext ());
// ensure the thread is not killed if audio has to be looped // ensure the thread is not killed if audio has to be looped
if (stream->isRepeat()) if (stream->isRepeat ())
ret = 0; ret = 0;
continue; continue;
@ -67,36 +61,29 @@ int audio_read_thread (void* arg)
return 0; return 0;
} }
static int audio_read_data_callback (void* streamarg, uint8_t* buffer, int buffer_size) static int audio_read_data_callback (void* streamarg, uint8_t* buffer, int buffer_size) {
{ const auto stream = static_cast<CAudioStream*> (streamarg);
auto stream = static_cast <CAudioStream*> (streamarg); const int left = stream->getLength () - stream->getPosition ();
int left = stream->getLength () - stream->getPosition ();
buffer_size = FFMIN (buffer_size, left); buffer_size = FFMIN (buffer_size, left);
memcpy (buffer, (uint8_t*) stream->getBuffer () + stream->getPosition (), buffer_size); memcpy (buffer, stream->getBuffer () + stream->getPosition (), buffer_size);
// update position // update position
stream->setPosition (stream->getPosition () + buffer_size); stream->setPosition (stream->getPosition () + buffer_size);
return buffer_size; return buffer_size;
} }
int64_t audio_seek_data_callback (void* streamarg, int64_t offset, int whence) int64_t audio_seek_data_callback (void* streamarg, int64_t offset, int whence) {
{ const auto stream = static_cast<CAudioStream*> (streamarg);
auto stream = static_cast <CAudioStream*> (streamarg);
if (whence & AVSEEK_SIZE) if (whence & AVSEEK_SIZE)
return stream->getLength (); return stream->getLength ();
switch (whence) switch (whence) {
{ case SEEK_CUR: stream->setPosition (stream->getPosition () + offset); break;
case SEEK_CUR:
stream->setPosition (stream->getPosition () + offset);
break;
case SEEK_SET: case SEEK_SET: stream->setPosition (offset); break;
stream->setPosition (offset);
break;
} }
return offset; return offset;
@ -104,15 +91,13 @@ int64_t audio_seek_data_callback (void* streamarg, int64_t offset, int whence)
CAudioStream::CAudioStream (CAudioContext& context, const std::string& filename) : CAudioStream::CAudioStream (CAudioContext& context, const std::string& filename) :
m_audioContext (context), m_audioContext (context),
m_swrctx (nullptr) m_swrctx (nullptr) {
{
this->loadCustomContent (filename.c_str ()); this->loadCustomContent (filename.c_str ());
} }
CAudioStream::CAudioStream (CAudioContext& context, const void* buffer, int length) : CAudioStream::CAudioStream (CAudioContext& context, const void* buffer, int length) :
m_audioContext (context), m_audioContext (context),
m_swrctx (nullptr) m_swrctx (nullptr) {
{
// setup a custom context first // setup a custom context first
this->m_formatContext = avformat_alloc_context (); this->m_formatContext = avformat_alloc_context ();
@ -124,15 +109,8 @@ CAudioStream::CAudioStream (CAudioContext& context, const void* buffer, int leng
this->m_position = 0; this->m_position = 0;
// setup custom io for it // setup custom io for it
this->m_formatContext->pb = avio_alloc_context ( this->m_formatContext->pb = avio_alloc_context (static_cast<uint8_t*> (av_malloc (4096)), 4096, 0, this,
static_cast <uint8_t*> (av_malloc (4096)), &audio_read_data_callback, nullptr, &audio_seek_data_callback);
4096,
0,
static_cast <void*> (this),
&audio_read_data_callback,
nullptr,
&audio_seek_data_callback
);
if (this->m_formatContext->pb == nullptr) if (this->m_formatContext->pb == nullptr)
sLog.exception ("Cannot create avio context"); sLog.exception ("Cannot create avio context");
@ -141,17 +119,15 @@ CAudioStream::CAudioStream (CAudioContext& context, const void* buffer, int leng
this->loadCustomContent (); this->loadCustomContent ();
} }
CAudioStream::CAudioStream(CAudioContext& audioContext, AVCodecContext* context) : CAudioStream::CAudioStream (CAudioContext& audioContext, AVCodecContext* context) :
m_context (context), m_context (context),
m_queue (new PacketQueue), m_queue (new PacketQueue),
m_audioContext (audioContext), m_audioContext (audioContext),
m_swrctx (nullptr) m_swrctx (nullptr) {
{
this->initialize (); this->initialize ();
} }
CAudioStream::~CAudioStream() CAudioStream::~CAudioStream () {
{
if (this->m_swrctx != nullptr && swr_is_initialized (this->m_swrctx) == true) if (this->m_swrctx != nullptr && swr_is_initialized (this->m_swrctx) == true)
swr_close (this->m_swrctx); swr_close (this->m_swrctx);
if (this->m_swrctx != nullptr) if (this->m_swrctx != nullptr)
@ -160,19 +136,14 @@ CAudioStream::~CAudioStream()
// TODO: FREE EVERYTHING ELSE THAT THIS CLASS HOLDS! // TODO: FREE EVERYTHING ELSE THAT THIS CLASS HOLDS!
} }
void CAudioStream::loadCustomContent (const char* filename) void CAudioStream::loadCustomContent (const char* filename) {
{
const AVCodec* aCodec;
AVCodecContext* avCodecContext;
if (avformat_open_input (&this->m_formatContext, filename, nullptr, nullptr) != 0) if (avformat_open_input (&this->m_formatContext, filename, nullptr, nullptr) != 0)
sLog.exception ("Cannot open audio file: ", filename); sLog.exception ("Cannot open audio file: ", filename);
if (avformat_find_stream_info (this->m_formatContext, nullptr) < 0) if (avformat_find_stream_info (this->m_formatContext, nullptr) < 0)
sLog.exception ("Cannot determine file format: ", filename); sLog.exception ("Cannot determine file format: ", filename);
// find the audio stream // find the audio stream
for (int i = 0; i< this->m_formatContext->nb_streams; i ++) for (int i = 0; i < this->m_formatContext->nb_streams; i++) {
{
if (this->m_formatContext->streams [i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && this->m_audioStream < 0) if (this->m_formatContext->streams [i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && this->m_audioStream < 0)
this->m_audioStream = i; this->m_audioStream = i;
} }
@ -181,15 +152,17 @@ void CAudioStream::loadCustomContent (const char* filename)
sLog.exception ("Cannot find an audio stream in file ", filename); sLog.exception ("Cannot find an audio stream in file ", filename);
// get the decoder for it and alloc the required context // get the decoder for it and alloc the required context
aCodec = avcodec_find_decoder (this->m_formatContext->streams [this->m_audioStream]->codecpar->codec_id); const AVCodec* aCodec =
avcodec_find_decoder (this->m_formatContext->streams [this->m_audioStream]->codecpar->codec_id);
if (aCodec == nullptr) if (aCodec == nullptr)
sLog.exception ("Cannot initialize audio decoder for file: ", filename); sLog.exception ("Cannot initialize audio decoder for file: ", filename);
// alocate context // alocate context
avCodecContext = avcodec_alloc_context3 (aCodec); AVCodecContext* avCodecContext = avcodec_alloc_context3 (aCodec);
if (avcodec_parameters_to_context (avCodecContext, this->m_formatContext->streams [this->m_audioStream]->codecpar) != 0) if (avcodec_parameters_to_context (avCodecContext,
this->m_formatContext->streams [this->m_audioStream]->codecpar) != 0)
sLog.exception ("Cannot initialize audio decoder parameters"); sLog.exception ("Cannot initialize audio decoder parameters");
// finally open // finally open
@ -205,8 +178,7 @@ void CAudioStream::loadCustomContent (const char* filename)
SDL_CreateThread (audio_read_thread, filename, this); SDL_CreateThread (audio_read_thread, filename, this);
} }
void CAudioStream::initialize () void CAudioStream::initialize () {
{
#if FF_API_FIFO_OLD_API #if FF_API_FIFO_OLD_API
// allocate the FIFO buffer // allocate the FIFO buffer
this->m_queue->packetList = av_fifo_alloc2 (1, sizeof (MyAVPacketList), AV_FIFO_FLAG_AUTO_GROW); this->m_queue->packetList = av_fifo_alloc2 (1, sizeof (MyAVPacketList), AV_FIFO_FLAG_AUTO_GROW);
@ -217,8 +189,7 @@ void CAudioStream::initialize ()
int64_t out_channel_layout; int64_t out_channel_layout;
// set output audio channels based on the input audio channels // set output audio channels based on the input audio channels
switch (this->m_audioContext.getChannels ()) switch (this->m_audioContext.getChannels ()) {
{
case 1: out_channel_layout = AV_CH_LAYOUT_MONO; break; case 1: out_channel_layout = AV_CH_LAYOUT_MONO; break;
case 2: out_channel_layout = AV_CH_LAYOUT_STEREO; break; case 2: out_channel_layout = AV_CH_LAYOUT_STEREO; break;
default: out_channel_layout = AV_CH_LAYOUT_SURROUND; break; default: out_channel_layout = AV_CH_LAYOUT_SURROUND; break;
@ -227,37 +198,21 @@ void CAudioStream::initialize ()
#if FF_API_OLD_CHANNEL_LAYOUT #if FF_API_OLD_CHANNEL_LAYOUT
av_channel_layout_from_mask (&this->m_out_channel_layout, out_channel_layout); av_channel_layout_from_mask (&this->m_out_channel_layout, out_channel_layout);
swr_alloc_set_opts2 ( swr_alloc_set_opts2 (&this->m_swrctx, &this->m_out_channel_layout, this->m_audioContext.getFormat (),
&this->m_swrctx, this->m_audioContext.getSampleRate (), &this->m_context->ch_layout,
&this->m_out_channel_layout, this->m_context->sample_fmt, this->m_context->sample_rate, 0, nullptr);
this->m_audioContext.getFormat (),
this->m_audioContext.getSampleRate (),
&this->m_context->ch_layout,
this->m_context->sample_fmt,
this->m_context->sample_rate,
0,
nullptr
);
#else #else
// initialize swrctx // initialize swrctx
this->m_swrctx = swr_alloc_set_opts ( this->m_swrctx = swr_alloc_set_opts (nullptr, out_channel_layout, this->m_audioContext.getFormat (),
nullptr, this->m_audioContext.getSampleRate (), this->getContext ()->channel_layout,
out_channel_layout, this->getContext ()->sample_fmt, this->getContext ()->sample_rate, 0, nullptr);
this->m_audioContext.getFormat (),
this->m_audioContext.getSampleRate (),
this->getContext ()->channel_layout,
this->getContext ()->sample_fmt,
this->getContext ()->sample_rate,
0,
nullptr
);
#endif #endif
if (this->m_swrctx == nullptr) if (this->m_swrctx == nullptr)
sLog.exception ("Cannot initialize swrctx for audio resampling"); sLog.exception ("Cannot initialize swrctx for audio resampling");
// initialize the context // initialize the context
if (swr_init (this->m_swrctx) < 0) if (swr_init (this->m_swrctx) < 0)
sLog.exception("Failed to initialize the resampling context."); sLog.exception ("Failed to initialize the resampling context.");
// setup the queue information // setup the queue information
this->m_queue->mutex = SDL_CreateMutex (); this->m_queue->mutex = SDL_CreateMutex ();
@ -267,13 +222,11 @@ void CAudioStream::initialize ()
this->m_initialized = true; this->m_initialized = true;
} }
void CAudioStream::queuePacket(AVPacket *pkt) void CAudioStream::queuePacket (AVPacket* pkt) {
{
// clone the packet // clone the packet
AVPacket* clone = av_packet_alloc (); AVPacket* clone = av_packet_alloc ();
if (clone == nullptr) if (clone == nullptr) {
{
av_packet_unref (clone); av_packet_unref (clone);
return; return;
} }
@ -281,16 +234,15 @@ void CAudioStream::queuePacket(AVPacket *pkt)
av_packet_move_ref (clone, pkt); av_packet_move_ref (clone, pkt);
SDL_LockMutex (this->m_queue->mutex); SDL_LockMutex (this->m_queue->mutex);
bool gotQueued = this->doQueue (clone); const bool gotQueued = this->doQueue (clone);
SDL_UnlockMutex (this->m_queue->mutex); SDL_UnlockMutex (this->m_queue->mutex);
if (!gotQueued) if (!gotQueued)
av_packet_free (&pkt); av_packet_free (&pkt);
} }
bool CAudioStream::doQueue (AVPacket* pkt) bool CAudioStream::doQueue (AVPacket* pkt) {
{ MyAVPacketList entry {pkt};
MyAVPacketList entry { pkt };
#if FF_API_FIFO_OLD_API #if FF_API_FIFO_OLD_API
// write the entry if possible // write the entry if possible
@ -304,7 +256,7 @@ bool CAudioStream::doQueue (AVPacket* pkt)
av_fifo_generic_write (this->m_queue->packetList, &entry, sizeof (entry), nullptr); av_fifo_generic_write (this->m_queue->packetList, &entry, sizeof (entry), nullptr);
#endif #endif
this->m_queue->nb_packets ++; this->m_queue->nb_packets++;
this->m_queue->size += entry.packet->size + sizeof (entry); this->m_queue->size += entry.packet->size + sizeof (entry);
this->m_queue->duration += entry.packet->duration; this->m_queue->duration += entry.packet->duration;
@ -313,14 +265,12 @@ bool CAudioStream::doQueue (AVPacket* pkt)
return true; return true;
} }
void CAudioStream::dequeuePacket (AVPacket* output) void CAudioStream::dequeuePacket (AVPacket* output) {
{
MyAVPacketList entry; MyAVPacketList entry;
SDL_LockMutex (this->m_queue->mutex); SDL_LockMutex (this->m_queue->mutex);
while (this->m_audioContext.getApplicationContext ().state.general.keepRunning) while (this->m_audioContext.getApplicationContext ().state.general.keepRunning) {
{
#if FF_API_FIFO_OLD_API #if FF_API_FIFO_OLD_API
int ret = av_fifo_read (this->m_queue->packetList, &entry, 1); int ret = av_fifo_read (this->m_queue->packetList, &entry, 1);
@ -332,9 +282,8 @@ void CAudioStream::dequeuePacket (AVPacket* output)
#endif #endif
// enough data available, read it // enough data available, read it
if (ret >= 0) if (ret >= 0) {
{ this->m_queue->nb_packets--;
this->m_queue->nb_packets --;
this->m_queue->size -= entry.packet->size + sizeof (entry); this->m_queue->size -= entry.packet->size + sizeof (entry);
this->m_queue->duration -= entry.packet->duration; this->m_queue->duration -= entry.packet->duration;
@ -351,93 +300,75 @@ void CAudioStream::dequeuePacket (AVPacket* output)
SDL_UnlockMutex (this->m_queue->mutex); SDL_UnlockMutex (this->m_queue->mutex);
} }
AVCodecContext* CAudioStream::getContext () AVCodecContext* CAudioStream::getContext () {
{
return this->m_context; return this->m_context;
} }
AVFormatContext* CAudioStream::getFormatContext () AVFormatContext* CAudioStream::getFormatContext () {
{
return this->m_formatContext; return this->m_formatContext;
} }
int CAudioStream::getAudioStream () int CAudioStream::getAudioStream () {
{
return this->m_audioStream; return this->m_audioStream;
} }
bool CAudioStream::isInitialized () bool CAudioStream::isInitialized () {
{
return this->m_initialized; return this->m_initialized;
} }
void CAudioStream::setRepeat (bool newRepeat) void CAudioStream::setRepeat (bool newRepeat) {
{
this->m_repeat = newRepeat; this->m_repeat = newRepeat;
} }
bool CAudioStream::isRepeat () bool CAudioStream::isRepeat () {
{
return this->m_repeat; return this->m_repeat;
} }
const void* CAudioStream::getBuffer () const void* CAudioStream::getBuffer () {
{
return this->m_buffer; return this->m_buffer;
} }
int CAudioStream::getLength () int CAudioStream::getLength () {
{
return this->m_length; return this->m_length;
} }
int CAudioStream::getPosition () int CAudioStream::getPosition () {
{
return this->m_position; return this->m_position;
} }
void CAudioStream::setPosition (int current) void CAudioStream::setPosition (int current) {
{
this->m_position = current; this->m_position = current;
} }
SDL_cond* CAudioStream::getWaitCondition () SDL_cond* CAudioStream::getWaitCondition () {
{
return this->m_queue->wait; return this->m_queue->wait;
} }
int CAudioStream::getQueueSize () int CAudioStream::getQueueSize () {
{
return this->m_queue->size; return this->m_queue->size;
} }
int CAudioStream::getQueuePacketCount () int CAudioStream::getQueuePacketCount () {
{
return this->m_queue->nb_packets; return this->m_queue->nb_packets;
} }
AVRational CAudioStream::getTimeBase () AVRational CAudioStream::getTimeBase () {
{
return this->m_formatContext->streams [this->m_audioStream]->time_base; return this->m_formatContext->streams [this->m_audioStream]->time_base;
} }
int64_t CAudioStream::getQueueDuration () int64_t CAudioStream::getQueueDuration () {
{
return this->m_queue->duration; return this->m_queue->duration;
} }
bool CAudioStream::isQueueEmpty () bool CAudioStream::isQueueEmpty () {
{
return this->m_queue->nb_packets == 0; return this->m_queue->nb_packets == 0;
} }
SDL_mutex* CAudioStream::getMutex () SDL_mutex* CAudioStream::getMutex () {
{
return this->m_queue->mutex; return this->m_queue->mutex;
} }
void CAudioStream::stop () void CAudioStream::stop () {
{
if (!this->isInitialized ()) if (!this->isInitialized ())
return; return;
@ -445,36 +376,27 @@ void CAudioStream::stop ()
this->m_initialized = false; this->m_initialized = false;
} }
int CAudioStream::resampleAudio (AVFrame * decoded_audio_frame, uint8_t * out_buf) int CAudioStream::resampleAudio (const AVFrame* decoded_audio_frame, uint8_t* out_buf) {
{
int out_linesize = 0; int out_linesize = 0;
int ret; int ret;
int out_nb_channels; int out_nb_channels;
int in_nb_samples;
int out_nb_samples; int out_nb_samples;
int max_out_nb_samples;
uint8_t** resampled_data = nullptr; uint8_t** resampled_data = nullptr;
int resampled_data_size; int resampled_data_size;
// retrieve number of audio samples (per channel) // retrieve number of audio samples (per channel)
in_nb_samples = decoded_audio_frame->nb_samples; const int in_nb_samples = decoded_audio_frame->nb_samples;
if (in_nb_samples <= 0) if (in_nb_samples <= 0) {
{ sLog.error ("in_nb_samples error.");
sLog.error("in_nb_samples error.");
return -1; return -1;
} }
max_out_nb_samples = out_nb_samples = av_rescale_rnd( int max_out_nb_samples = out_nb_samples = av_rescale_rnd (in_nb_samples, this->m_audioContext.getSampleRate (),
in_nb_samples, this->getContext ()->sample_rate, AV_ROUND_UP);
this->m_audioContext.getSampleRate (),
this->getContext ()->sample_rate,
AV_ROUND_UP
);
// check rescaling was successful // check rescaling was successful
if (max_out_nb_samples <= 0) if (max_out_nb_samples <= 0) {
{ sLog.error ("av_rescale_rnd error.");
sLog.error("av_rescale_rnd error.");
return -1; return -1;
} }
@ -485,64 +407,44 @@ int CAudioStream::resampleAudio (AVFrame * decoded_audio_frame, uint8_t * out_bu
int64_t out_channel_layout; int64_t out_channel_layout;
// set output audio channels based on the input audio channels // set output audio channels based on the input audio channels
switch (this->m_audioContext.getChannels ()) switch (this->m_audioContext.getChannels ()) {
{
case 1: out_channel_layout = AV_CH_LAYOUT_MONO; break; case 1: out_channel_layout = AV_CH_LAYOUT_MONO; break;
case 2: out_channel_layout = AV_CH_LAYOUT_STEREO; break; case 2: out_channel_layout = AV_CH_LAYOUT_STEREO; break;
default: out_channel_layout = AV_CH_LAYOUT_SURROUND; break; default: out_channel_layout = AV_CH_LAYOUT_SURROUND; break;
} }
out_nb_channels = av_get_channel_layout_nb_channels(out_channel_layout); out_nb_channels = av_get_channel_layout_nb_channels (out_channel_layout);
#endif #endif
ret = av_samples_alloc_array_and_samples( ret = av_samples_alloc_array_and_samples (&resampled_data, &out_linesize, out_nb_channels, out_nb_samples,
&resampled_data, this->m_audioContext.getFormat (), 0);
&out_linesize,
out_nb_channels,
out_nb_samples,
this->m_audioContext.getFormat (),
0
);
if (ret < 0) if (ret < 0) {
{ sLog.error ("av_samples_alloc_array_and_samples() error: Could not allocate destination samples.");
sLog.error("av_samples_alloc_array_and_samples() error: Could not allocate destination samples.");
return -1; return -1;
} }
// retrieve output samples number taking into account the progressive delay // retrieve output samples number taking into account the progressive delay
out_nb_samples = av_rescale_rnd( out_nb_samples =
swr_get_delay(this->m_swrctx, this->getContext ()->sample_rate) + in_nb_samples, av_rescale_rnd (swr_get_delay (this->m_swrctx, this->getContext ()->sample_rate) + in_nb_samples,
this->m_audioContext.getSampleRate (), this->m_audioContext.getSampleRate (), this->getContext ()->sample_rate, AV_ROUND_UP);
this->getContext ()->sample_rate,
AV_ROUND_UP
);
// check output samples number was correctly retrieved // check output samples number was correctly retrieved
if (out_nb_samples <= 0) if (out_nb_samples <= 0) {
{ sLog.error ("av_rescale_rnd error");
sLog.error("av_rescale_rnd error");
return -1; return -1;
} }
if (out_nb_samples > max_out_nb_samples) if (out_nb_samples > max_out_nb_samples) {
{
// free memory block and set pointer to NULL // free memory block and set pointer to NULL
av_free(resampled_data[0]); av_free (resampled_data [0]);
// Allocate a samples buffer for out_nb_samples samples // Allocate a samples buffer for out_nb_samples samples
ret = av_samples_alloc( ret = av_samples_alloc (resampled_data, &out_linesize, out_nb_channels, out_nb_samples,
resampled_data, this->m_audioContext.getFormat (), 1);
&out_linesize,
out_nb_channels,
out_nb_samples,
this->m_audioContext.getFormat (),
1
);
// check samples buffer correctly allocated // check samples buffer correctly allocated
if (ret < 0) if (ret < 0) {
{ sLog.error ("av_samples_alloc failed.");
sLog.error("av_samples_alloc failed.");
return -1; return -1;
} }
@ -550,69 +452,54 @@ int CAudioStream::resampleAudio (AVFrame * decoded_audio_frame, uint8_t * out_bu
} }
// do the actual audio data resampling // do the actual audio data resampling
ret = swr_convert( ret = swr_convert (this->m_swrctx, resampled_data, max_out_nb_samples,
this->m_swrctx, const_cast<const uint8_t**> (decoded_audio_frame->data), decoded_audio_frame->nb_samples);
resampled_data,
max_out_nb_samples,
(const uint8_t **) decoded_audio_frame->data,
decoded_audio_frame->nb_samples
);
// check audio conversion was successful // check audio conversion was successful
if (ret < 0) if (ret < 0) {
{ sLog.error ("swr_convert_error.");
sLog.error("swr_convert_error.");
return -1; return -1;
} }
// Get the required buffer size for the given audio parameters // Get the required buffer size for the given audio parameters
resampled_data_size = av_samples_get_buffer_size( resampled_data_size =
&out_linesize, av_samples_get_buffer_size (&out_linesize, out_nb_channels, ret, this->m_audioContext.getFormat (), 1);
out_nb_channels,
ret,
this->m_audioContext.getFormat (),
1
);
// check audio buffer size // check audio buffer size
if (resampled_data_size < 0) if (resampled_data_size < 0) {
{
sLog.error ("av_samples_get_buffer_size error."); sLog.error ("av_samples_get_buffer_size error.");
return -1; return -1;
} }
// copy the resampled data to the output buffer // copy the resampled data to the output buffer
memcpy(out_buf, resampled_data[0], resampled_data_size); memcpy (out_buf, resampled_data [0], resampled_data_size);
/* /*
* Memory Cleanup. * Memory Cleanup.
*/ */
if (resampled_data) if (resampled_data) {
{
// free memory block and set pointer to NULL // free memory block and set pointer to NULL
av_freep(&resampled_data[0]); av_freep (&resampled_data [0]);
} }
av_freep(&resampled_data); av_freep (&resampled_data);
resampled_data = NULL; resampled_data = nullptr;
return resampled_data_size; return resampled_data_size;
} }
int CAudioStream::decodeFrame (uint8_t* audioBuffer, int bufferSize) int CAudioStream::decodeFrame (uint8_t* audioBuffer, int bufferSize) {
{ AVPacket* pkt = av_packet_alloc ();
AVPacket *pkt = av_packet_alloc (); static uint8_t* audio_pkt_data = nullptr;
static uint8_t *audio_pkt_data = NULL;
static int audio_pkt_size = 0; static int audio_pkt_size = 0;
int len1, data_size; int len1, data_size;
// allocate a new frame, used to decode audio packets // allocate a new frame, used to decode audio packets
static AVFrame * avFrame = NULL; static AVFrame* avFrame = nullptr;
avFrame = av_frame_alloc(); avFrame = av_frame_alloc ();
if (!avFrame) if (!avFrame) {
{ sLog.error ("Could not allocate AVFrame.\n");
sLog.error("Could not allocate AVFrame.\n");
return -1; return -1;
} }
@ -620,21 +507,20 @@ int CAudioStream::decodeFrame (uint8_t* audioBuffer, int bufferSize)
while (this->m_audioContext.getApplicationContext ().state.general.keepRunning) { while (this->m_audioContext.getApplicationContext ().state.general.keepRunning) {
while (audio_pkt_size > 0) { while (audio_pkt_size > 0) {
int got_frame = 0; int got_frame = 0;
int ret = avcodec_receive_frame(this->getContext (), avFrame); int ret = avcodec_receive_frame (this->getContext (), avFrame);
if (ret == 0) if (ret == 0)
got_frame = 1; got_frame = 1;
if (ret == AVERROR(EAGAIN)) if (ret == AVERROR (EAGAIN))
ret = 0; ret = 0;
if (ret == 0) if (ret == 0)
ret = avcodec_send_packet(this->getContext (), pkt); ret = avcodec_send_packet (this->getContext (), pkt);
if (ret < 0 && ret != AVERROR (EAGAIN)) if (ret < 0 && ret != AVERROR (EAGAIN))
return -1; return -1;
len1 = pkt->size; len1 = pkt->size;
if (len1 < 0) if (len1 < 0) {
{
// if error, skip frame // if error, skip frame
audio_pkt_size = 0; audio_pkt_size = 0;
break; break;
@ -647,7 +533,7 @@ int CAudioStream::decodeFrame (uint8_t* audioBuffer, int bufferSize)
if (got_frame) { if (got_frame) {
// audio resampling // audio resampling
data_size = this->resampleAudio (avFrame, audioBuffer); data_size = this->resampleAudio (avFrame, audioBuffer);
assert(data_size <= bufferSize); assert (data_size <= bufferSize);
} }
if (data_size <= 0) { if (data_size <= 0) {
// no data found, keep waiting // no data found, keep waiting
@ -657,7 +543,7 @@ int CAudioStream::decodeFrame (uint8_t* audioBuffer, int bufferSize)
return data_size; return data_size;
} }
if (pkt->data) if (pkt->data)
av_packet_unref(pkt); av_packet_unref (pkt);
this->dequeuePacket (pkt); this->dequeuePacket (pkt);
@ -668,7 +554,6 @@ int CAudioStream::decodeFrame (uint8_t* audioBuffer, int bufferSize)
return 0; return 0;
} }
CAudioContext& CAudioStream::getAudioContext () const CAudioContext& CAudioStream::getAudioContext () const {
{
return this->m_audioContext; return this->m_audioContext;
} }

View File

@ -2,14 +2,13 @@
#include <string> #include <string>
extern "C" extern "C" {
{
#include <libavutil/fifo.h>
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
#include <libavformat/avformat.h> #include <libavformat/avformat.h>
#include <libswscale/swscale.h> #include <libavutil/fifo.h>
#include <libswresample/swresample.h>
#include <libavutil/opt.h> #include <libavutil/opt.h>
#include <libswresample/swresample.h>
#include <libswscale/swscale.h>
} }
#include <SDL.h> #include <SDL.h>
@ -17,196 +16,192 @@ extern "C"
#include "WallpaperEngine/Audio/CAudioContext.h" #include "WallpaperEngine/Audio/CAudioContext.h"
namespace WallpaperEngine::Audio namespace WallpaperEngine::Audio {
{ class CAudioContext;
class CAudioContext;
/**
* Represents a playable audio stream for the audio driver
*/
class CAudioStream {
public:
CAudioStream (CAudioContext& context, const std::string& filename);
CAudioStream (CAudioContext& context, const void* buffer, int length);
CAudioStream (CAudioContext& audioContext, AVCodecContext* context);
~CAudioStream ();
void queuePacket (AVPacket* pkt);
/** /**
* Represents a playable audio stream for the audio driver * Gets the next packet in the queue
*
* WARNING: BLOCKS UNTIL SOME DATA IS READ FROM IT
*
* @return
*/ */
class CAudioStream void dequeuePacket (AVPacket* output);
{
public:
CAudioStream (CAudioContext& context, const std::string& filename);
CAudioStream (CAudioContext& context, const void* buffer, int length);
CAudioStream (CAudioContext& audioContext, AVCodecContext* context);
~CAudioStream ();
void queuePacket (AVPacket* pkt); /**
* @return The audio context in use for this audio stream
*/
[[nodiscard]] CAudioContext& getAudioContext () const;
/** /**
* Gets the next packet in the queue * @return to the codec context, which provides information on the audio stream's format
* */
* WARNING: BLOCKS UNTIL SOME DATA IS READ FROM IT AVCodecContext* getContext ();
* /**
* @return * @returns the format context, which controls how data is read off the audio stream
*/ */
void dequeuePacket (AVPacket* output); AVFormatContext* getFormatContext ();
/**
* @return The audio stream index of the given file
*/
int getAudioStream ();
/**
* @return If the audio stream can be played or not
*/
bool isInitialized ();
/**
* @param newRepeat true = repeat, false = no repeat
*/
void setRepeat (bool newRepeat = true);
/**
* @return If the stream is to be repeated at the end or not
*/
bool isRepeat ();
/**
* Stops decoding and playbak of the stream
*/
void stop ();
/**
* @return The file data buffer
*/
const void* getBuffer ();
/**
* @return The length of the file data buffer
*/
int getLength ();
/**
* @return The read position of the data buffer
*/
int getPosition ();
/**
* Updates the read position of the data buffer
*
* @param current
*/
void setPosition (int current);
/**
* @return The SDL_cond used to signal waiting for data
*/
SDL_cond* getWaitCondition ();
/**
* @return The data queue size
*/
int getQueueSize ();
/**
* @return The amount of packets ready to be converted and played
*/
int getQueuePacketCount ();
/**
* @return The duration (in seconds) of the queued data to be played
*/
int64_t getQueueDuration ();
/**
* @return Time unit used for packet playback
*/
AVRational getTimeBase ();
/**
* @return If the data queue is empty or not
*/
bool isQueueEmpty ();
/**
* @return The SDL_mutex used for thread synchronization
*/
SDL_mutex* getMutex ();
/** /**
* @return The audio context in use for this audio stream * Reads a frame from the audio stream, resamples it to the driver's settings
*/ * and returns the data ready to be played
[[nodiscard]] CAudioContext& getAudioContext () const; *
* @param audioBuffer
* @param bufferSize
*
* @return The amount of bytes available or < 0 for error
*/
int decodeFrame (uint8_t* audioBuffer, int bufferSize);
/** private:
* @return to the codec context, which provides information on the audio stream's format /**
*/ * Initializes ffmpeg to read the given file
AVCodecContext* getContext (); *
/** * @param filename
* @returns the format context, which controls how data is read off the audio stream */
*/ void loadCustomContent (const char* filename = nullptr);
AVFormatContext* getFormatContext (); /**
/** * Converts the audio frame from the original format to one supported by the audio driver
* @return The audio stream index of the given file *
*/ * @param decoded_audio_frame
int getAudioStream (); * @param out_buf
/** * @return
* @return If the audio stream can be played or not */
*/ int resampleAudio (const AVFrame* decoded_audio_frame, uint8_t* out_buf);
bool isInitialized (); /**
/** * Queues a packet into the play queue
* @param newRepeat true = repeat, false = no repeat *
*/ * @param pkt
void setRepeat (bool newRepeat = true); * @return
/** */
* @return If the stream is to be repeated at the end or not bool doQueue (AVPacket* pkt);
*/ /**
bool isRepeat (); * Initializes queues and ffmpeg resampling
/** */
* Stops decoding and playbak of the stream void initialize ();
*/
void stop ();
/**
* @return The file data buffer
*/
const void* getBuffer ();
/**
* @return The length of the file data buffer
*/
int getLength ();
/**
* @return The read position of the data buffer
*/
int getPosition ();
/**
* Updates the read position of the data buffer
*
* @param current
*/
void setPosition (int current);
/**
* @return The SDL_cond used to signal waiting for data
*/
SDL_cond* getWaitCondition ();
/**
* @return The data queue size
*/
int getQueueSize ();
/**
* @return The amount of packets ready to be converted and played
*/
int getQueuePacketCount ();
/**
* @return The duration (in seconds) of the queued data to be played
*/
int64_t getQueueDuration ();
/**
* @return Time unit used for packet playback
*/
AVRational getTimeBase ();
/**
* @return If the data queue is empty or not
*/
bool isQueueEmpty ();
/**
* @return The SDL_mutex used for thread synchronization
*/
SDL_mutex* getMutex ();
/**
* Reads a frame from the audio stream, resamples it to the driver's settings
* and returns the data ready to be played
*
* @param audioBuffer
* @param bufferSize
*
* @return The amount of bytes available or < 0 for error
*/
int decodeFrame (uint8_t* audioBuffer, int bufferSize);
private:
/**
* Initializes ffmpeg to read the given file
*
* @param filename
*/
void loadCustomContent (const char* filename = nullptr);
/**
* Converts the audio frame from the original format to one supported by the audio driver
*
* @param decoded_audio_frame
* @param out_buf
* @return
*/
int resampleAudio (AVFrame* decoded_audio_frame, uint8_t* out_buf);
/**
* Queues a packet into the play queue
*
* @param pkt
* @return
*/
bool doQueue (AVPacket* pkt);
/**
* Initializes queues and ffmpeg resampling
*/
void initialize ();
#if FF_API_OLD_CHANNEL_LAYOUT #if FF_API_OLD_CHANNEL_LAYOUT
/** Chanel layout needed for old FFMPEG versions */ /** Chanel layout needed for old FFMPEG versions */
AVChannelLayout m_out_channel_layout; AVChannelLayout m_out_channel_layout {};
#endif #endif
/** The SwrContext that handles resampling */ /** The SwrContext that handles resampling */
SwrContext* m_swrctx; SwrContext* m_swrctx;
/** The audio context this stream will be played under */ /** The audio context this stream will be played under */
CAudioContext& m_audioContext; CAudioContext& m_audioContext;
/** If this stream was properly initialized or not */ /** If this stream was properly initialized or not */
bool m_initialized; bool m_initialized {};
/** Repeat enabled? */ /** Repeat enabled? */
bool m_repeat; bool m_repeat {};
/** The codec context that contains the original audio format information */ /** The codec context that contains the original audio format information */
AVCodecContext* m_context = nullptr; AVCodecContext* m_context = nullptr;
/** The format context that controls how data is read off the file */ /** The format context that controls how data is read off the file */
AVFormatContext* m_formatContext = nullptr; AVFormatContext* m_formatContext = nullptr;
/** The stream index for the audio being played */ /** The stream index for the audio being played */
int m_audioStream = -1; int m_audioStream = -1;
/** File data pointer */ /** File data pointer */
const void* m_buffer; const void* m_buffer {};
/** The length of the file data pointer */ /** The length of the file data pointer */
int m_length; int m_length {};
/** The read position on the file data pointer */ /** The read position on the file data pointer */
int m_position = 0; int m_position = 0;
struct MyAVPacketList struct MyAVPacketList {
{ AVPacket* packet;
AVPacket* packet;
};
/**
* Packet queue information
*/
struct PacketQueue
{
#if FF_API_FIFO_OLD_API
AVFifo* packetList;
#else
AVFifoBuffer* packetList;
#endif
int nb_packets;
int size;
int64_t duration;
SDL_mutex* mutex;
SDL_cond* wait;
SDL_cond* cond;
}* m_queue;
}; };
}
/**
* Packet queue information
*/
struct PacketQueue {
#if FF_API_FIFO_OLD_API
AVFifo* packetList;
#else
AVFifoBuffer* packetList;
#endif
int nb_packets;
int size;
int64_t duration;
SDL_mutex* mutex;
SDL_cond* wait;
SDL_cond* cond;
}* m_queue {};
};
} // namespace WallpaperEngine::Audio

View File

@ -1,31 +1,26 @@
#include "CAudioDriver.h" #include "CAudioDriver.h"
namespace WallpaperEngine::Audio::Drivers namespace WallpaperEngine::Audio::Drivers {
{ CAudioDriver::CAudioDriver (Application::CApplicationContext& applicationContext,
CAudioDriver::CAudioDriver (Application::CApplicationContext& applicationContext, Detectors::CAudioPlayingDetector& detector, Recorders::CPlaybackRecorder& recorder) : Detectors::CAudioPlayingDetector& detector, Recorders::CPlaybackRecorder& recorder) :
m_applicationContext (applicationContext), m_applicationContext (applicationContext),
m_detector (detector), m_detector (detector),
m_recorder (recorder) m_recorder (recorder) {}
{
}
void CAudioDriver::update () void CAudioDriver::update () {
{ this->m_recorder.update ();
this->m_recorder.update (); this->m_detector.update ();
this->m_detector.update ();
}
Application::CApplicationContext& CAudioDriver::getApplicationContext ()
{
return this->m_applicationContext;
}
Detectors::CAudioPlayingDetector& CAudioDriver::getAudioDetector ()
{
return this->m_detector;
}
Recorders::CPlaybackRecorder& CAudioDriver::getRecorder ()
{
return this->m_recorder;
}
} }
Application::CApplicationContext& CAudioDriver::getApplicationContext () {
return this->m_applicationContext;
}
Detectors::CAudioPlayingDetector& CAudioDriver::getAudioDetector () {
return this->m_detector;
}
Recorders::CPlaybackRecorder& CAudioDriver::getRecorder () {
return this->m_recorder;
}
} // namespace WallpaperEngine::Audio::Drivers

View File

@ -2,86 +2,81 @@
#include <vector> #include <vector>
#include "WallpaperEngine/Audio/Drivers/Detectors/CAudioPlayingDetector.h"
#include "WallpaperEngine/Audio/Drivers/Recorders/CPlaybackRecorder.h"
#include "WallpaperEngine/Application/CApplicationContext.h" #include "WallpaperEngine/Application/CApplicationContext.h"
#include "WallpaperEngine/Audio/CAudioStream.h" #include "WallpaperEngine/Audio/CAudioStream.h"
#include "WallpaperEngine/Audio/Drivers/Detectors/CAudioPlayingDetector.h"
#include "WallpaperEngine/Audio/Drivers/Recorders/CPlaybackRecorder.h"
namespace WallpaperEngine namespace WallpaperEngine {
{ namespace Application {
namespace Application class CApplicationContext;
{
class CApplicationContext;
}
namespace Audio
{
class CAudioStream;
namespace Drivers
{
namespace Detectors
{
class CAudioPlayingDetector;
}
namespace Recorders
{
class CPulseAudioPlaybackRecorder;
}
/**
* Base class for audio driver implementations
*/
class CAudioDriver
{
public:
explicit CAudioDriver (Application::CApplicationContext& applicationContext, Detectors::CAudioPlayingDetector& detector, Recorders::CPlaybackRecorder& recorder);
/**
* Registers the given stream in the driver for playing
*
* @param stream
*/
virtual void addStream (CAudioStream* stream) = 0;
/**
* Updates status of the different audio settings
*/
virtual void update ();
/**
* TODO: MAYBE THIS SHOULD BE OUR OWN DEFINITIONS INSTEAD OF LIBRARY SPECIFIC ONES?
*
* @return The audio format the driver supports
*/
[[nodiscard]] virtual AVSampleFormat getFormat () const = 0;
/**
* @return The sample rate the driver supports
*/
[[nodiscard]] virtual int getSampleRate () const = 0;
/**
* @return The channels the driver supports
*/
[[nodiscard]] virtual int getChannels () const = 0;
/**
* @return The application context under which the audio driver is initialized
*/
Application::CApplicationContext& getApplicationContext ();
/**
* @return The audio playing detector to use to stop playing sound when something else starts playing
*/
[[nodiscard]] Detectors::CAudioPlayingDetector& getAudioDetector ();
/**
* @return The audio recorder to use to capture stereo mix data
*/
[[nodiscard]] Recorders::CPlaybackRecorder& getRecorder ();
private:
Application::CApplicationContext& m_applicationContext;
Detectors::CAudioPlayingDetector& m_detector;
Recorders::CPlaybackRecorder& m_recorder;
};
}
}
} }
namespace Audio {
class CAudioStream;
namespace Drivers {
namespace Detectors {
class CAudioPlayingDetector;
}
namespace Recorders {
class CPulseAudioPlaybackRecorder;
}
/**
* Base class for audio driver implementations
*/
class CAudioDriver {
public:
explicit CAudioDriver (Application::CApplicationContext& applicationContext,
Detectors::CAudioPlayingDetector& detector, Recorders::CPlaybackRecorder& recorder);
virtual ~CAudioDriver () = default;
/**
* Registers the given stream in the driver for playing
*
* @param stream
*/
virtual void addStream (CAudioStream* stream) = 0;
/**
* Updates status of the different audio settings
*/
virtual void update ();
/**
* TODO: MAYBE THIS SHOULD BE OUR OWN DEFINITIONS INSTEAD OF LIBRARY SPECIFIC ONES?
*
* @return The audio format the driver supports
*/
[[nodiscard]] virtual AVSampleFormat getFormat () const = 0;
/**
* @return The sample rate the driver supports
*/
[[nodiscard]] virtual int getSampleRate () const = 0;
/**
* @return The channels the driver supports
*/
[[nodiscard]] virtual int getChannels () const = 0;
/**
* @return The application context under which the audio driver is initialized
*/
Application::CApplicationContext& getApplicationContext ();
/**
* @return The audio playing detector to use to stop playing sound when something else starts playing
*/
[[nodiscard]] Detectors::CAudioPlayingDetector& getAudioDetector ();
/**
* @return The audio recorder to use to capture stereo mix data
*/
[[nodiscard]] Recorders::CPlaybackRecorder& getRecorder ();
private:
Application::CApplicationContext& m_applicationContext;
Detectors::CAudioPlayingDetector& m_detector;
Recorders::CPlaybackRecorder& m_recorder;
};
} // namespace Drivers
} // namespace Audio
} // namespace WallpaperEngine

View File

@ -1,5 +1,5 @@
#include "common.h"
#include "CSDLAudioDriver.h" #include "CSDLAudioDriver.h"
#include "common.h"
#define SDL_AUDIO_BUFFER_SIZE 4096 #define SDL_AUDIO_BUFFER_SIZE 4096
#define MAX_AUDIO_FRAME_SIZE 192000 #define MAX_AUDIO_FRAME_SIZE 192000
@ -7,9 +7,8 @@
using namespace WallpaperEngine::Audio; using namespace WallpaperEngine::Audio;
using namespace WallpaperEngine::Audio::Drivers; using namespace WallpaperEngine::Audio::Drivers;
void audio_callback (void* userdata, uint8_t* streamData, int length) void audio_callback (void* userdata, uint8_t* streamData, int length) {
{ auto* driver = static_cast<CSDLAudioDriver*> (userdata);
auto* driver = reinterpret_cast <CSDLAudioDriver*> (userdata);
memset (streamData, 0, length); memset (streamData, 0, length);
@ -17,11 +16,9 @@ void audio_callback (void* userdata, uint8_t* streamData, int length)
if (driver->getAudioDetector ().anythingPlaying ()) if (driver->getAudioDetector ().anythingPlaying ())
return; return;
for (const auto& buffer : driver->getStreams ()) for (const auto& buffer : driver->getStreams ()) {
{
uint8_t* streamDataPointer = streamData; uint8_t* streamDataPointer = streamData;
int streamLength = length; int streamLength = length;
int len1, audio_size;
// sound is not initialized or stopped and is not in loop mode // sound is not initialized or stopped and is not in loop mode
// ignore mixing it in // ignore mixing it in
@ -29,43 +26,35 @@ void audio_callback (void* userdata, uint8_t* streamData, int length)
continue; continue;
// check if queue is empty and signal the read thread // check if queue is empty and signal the read thread
if (buffer->stream->isQueueEmpty ()) if (buffer->stream->isQueueEmpty ()) {
{
SDL_CondSignal (buffer->stream->getWaitCondition ()); SDL_CondSignal (buffer->stream->getWaitCondition ());
continue; continue;
} }
while (streamLength > 0 && driver->getApplicationContext ().state.general.keepRunning) while (streamLength > 0 && driver->getApplicationContext ().state.general.keepRunning) {
{ if (buffer->audio_buf_index >= buffer->audio_buf_size) {
if (buffer->audio_buf_index >= buffer->audio_buf_size)
{
// get more data to fill the buffer // get more data to fill the buffer
audio_size = buffer->stream->decodeFrame (buffer->audio_buf, sizeof (buffer->audio_buf)); int audio_size = buffer->stream->decodeFrame (buffer->audio_buf, sizeof (buffer->audio_buf));
if (audio_size < 0) if (audio_size < 0) {
{
// fallback for errors, silence // fallback for errors, silence
buffer->audio_buf_size = 1024; buffer->audio_buf_size = 1024;
memset(buffer->audio_buf, 0, buffer->audio_buf_size); memset (buffer->audio_buf, 0, buffer->audio_buf_size);
} } else {
else
{
buffer->audio_buf_size = audio_size; buffer->audio_buf_size = audio_size;
} }
buffer->audio_buf_index = 0; buffer->audio_buf_index = 0;
} }
len1 = buffer->audio_buf_size - buffer->audio_buf_index; int len1 = buffer->audio_buf_size - buffer->audio_buf_index;
if (len1 > streamLength) if (len1 > streamLength)
len1 = streamLength; len1 = streamLength;
// mix the audio // mix the audio
SDL_MixAudioFormat ( SDL_MixAudioFormat (streamDataPointer, &buffer->audio_buf [buffer->audio_buf_index],
streamDataPointer, &buffer->audio_buf [buffer->audio_buf_index], driver->getSpec ().format, len1, driver->getApplicationContext ().state.audio.volume);
driver->getSpec ().format, len1, driver->getApplicationContext ().state.audio.volume
);
streamLength -= len1; streamLength -= len1;
streamDataPointer += len1; streamDataPointer += len1;
@ -74,34 +63,29 @@ void audio_callback (void* userdata, uint8_t* streamData, int length)
} }
} }
CSDLAudioDriver::CSDLAudioDriver (Application::CApplicationContext& applicationContext, Detectors::CAudioPlayingDetector& detector, Recorders::CPlaybackRecorder& recorder) : CSDLAudioDriver::CSDLAudioDriver (Application::CApplicationContext& applicationContext,
Detectors::CAudioPlayingDetector& detector, Recorders::CPlaybackRecorder& recorder) :
CAudioDriver (applicationContext, detector, recorder), CAudioDriver (applicationContext, detector, recorder),
m_initialized (false), m_initialized (false),
m_audioSpec () m_audioSpec () {
{ if (SDL_InitSubSystem (SDL_INIT_AUDIO) < 0) {
if (SDL_InitSubSystem (SDL_INIT_AUDIO) < 0)
{
sLog.error ("Cannot initialize SDL audio system, SDL_GetError: ", SDL_GetError ()); sLog.error ("Cannot initialize SDL audio system, SDL_GetError: ", SDL_GetError ());
sLog.error ("Continuing without audio support"); sLog.error ("Continuing without audio support");
return; return;
} }
SDL_AudioSpec requestedSpec; const SDL_AudioSpec requestedSpec = {.freq = 48000,
.format = AUDIO_F32,
.channels = 2,
.samples = SDL_AUDIO_BUFFER_SIZE,
.callback = audio_callback,
.userdata = this};
memset (&requestedSpec, 0, sizeof (requestedSpec)); this->m_deviceID =
SDL_OpenAudioDevice (nullptr, false, &requestedSpec, &this->m_audioSpec, SDL_AUDIO_ALLOW_ANY_CHANGE);
requestedSpec.freq = 48000; if (this->m_deviceID == 0) {
requestedSpec.format = AUDIO_F32;
requestedSpec.channels = 2;
requestedSpec.samples = SDL_AUDIO_BUFFER_SIZE;
requestedSpec.callback = audio_callback;
requestedSpec.userdata = this;
this->m_deviceID = SDL_OpenAudioDevice (nullptr, false, &requestedSpec, &this->m_audioSpec, SDL_AUDIO_ALLOW_ANY_CHANGE);
if (this->m_deviceID == 0)
{
sLog.error ("SDL_OpenAudioDevice: ", SDL_GetError ()); sLog.error ("SDL_OpenAudioDevice: ", SDL_GetError ());
return; return;
} }
@ -111,8 +95,7 @@ CSDLAudioDriver::CSDLAudioDriver (Application::CApplicationContext& applicationC
this->m_initialized = true; this->m_initialized = true;
} }
CSDLAudioDriver::~CSDLAudioDriver () CSDLAudioDriver::~CSDLAudioDriver () {
{
if (!this->m_initialized) if (!this->m_initialized)
return; return;
@ -120,39 +103,39 @@ CSDLAudioDriver::~CSDLAudioDriver ()
SDL_QuitSubSystem (SDL_INIT_AUDIO); SDL_QuitSubSystem (SDL_INIT_AUDIO);
} }
void CSDLAudioDriver::addStream (CAudioStream* stream) void CSDLAudioDriver::addStream (CAudioStream* stream) {
{ this->m_streams.push_back (new CSDLAudioBuffer {stream});
this->m_streams.push_back (new CSDLAudioBuffer { stream });
} }
const std::vector <CSDLAudioBuffer*>& CSDLAudioDriver::getStreams () const std::vector<CSDLAudioBuffer*>& CSDLAudioDriver::getStreams () {
{
return this->m_streams; return this->m_streams;
} }
AVSampleFormat CSDLAudioDriver::getFormat () const AVSampleFormat CSDLAudioDriver::getFormat () const {
{ switch (this->m_audioSpec.format) {
switch (this->m_audioSpec.format) case AUDIO_U8:
{ case AUDIO_S8: return AV_SAMPLE_FMT_U8;
case AUDIO_U8: case AUDIO_S8: return AV_SAMPLE_FMT_U8; case AUDIO_U16MSB:
case AUDIO_U16MSB: case AUDIO_U16LSB: case AUDIO_S16LSB: case AUDIO_S16MSB: return AV_SAMPLE_FMT_S16; case AUDIO_U16LSB:
case AUDIO_S32LSB: case AUDIO_S32MSB: return AV_SAMPLE_FMT_S32; case AUDIO_S16LSB:
case AUDIO_F32LSB: case AUDIO_F32MSB: return AV_SAMPLE_FMT_FLT; case AUDIO_S16MSB: return AV_SAMPLE_FMT_S16;
case AUDIO_S32LSB:
case AUDIO_S32MSB: return AV_SAMPLE_FMT_S32;
case AUDIO_F32LSB:
case AUDIO_F32MSB: return AV_SAMPLE_FMT_FLT;
} }
sLog.exception ("Cannot convert from SDL format to ffmpeg format, aborting..."); sLog.exception ("Cannot convert from SDL format to ffmpeg format, aborting...");
} }
int CSDLAudioDriver::getSampleRate () const int CSDLAudioDriver::getSampleRate () const {
{
return this->m_audioSpec.freq; return this->m_audioSpec.freq;
} }
int CSDLAudioDriver::getChannels () const int CSDLAudioDriver::getChannels () const {
{
return this->m_audioSpec.channels; return this->m_audioSpec.channels;
} }
const SDL_AudioSpec& CSDLAudioDriver::getSpec () const
{ const SDL_AudioSpec& CSDLAudioDriver::getSpec () const {
return this->m_audioSpec; return this->m_audioSpec;
} }

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <vector>
#include <map> #include <map>
#include <vector>
#include "WallpaperEngine/Audio/CAudioStream.h" #include "WallpaperEngine/Audio/CAudioStream.h"
#include "WallpaperEngine/Audio/Drivers/CAudioDriver.h" #include "WallpaperEngine/Audio/Drivers/CAudioDriver.h"
@ -10,54 +10,52 @@
#define MAX_AUDIO_FRAME_SIZE 192000 #define MAX_AUDIO_FRAME_SIZE 192000
namespace WallpaperEngine::Audio::Drivers namespace WallpaperEngine::Audio::Drivers {
{ /**
* Audio output buffers for streams being played under SDL
*/
struct CSDLAudioBuffer {
CAudioStream* stream;
uint8_t audio_buf [(MAX_AUDIO_FRAME_SIZE * 3) / 2] = {0};
unsigned int audio_buf_size = 0;
unsigned int audio_buf_index = 0;
};
/**
* SDL's audio driver implementation
*/
class CSDLAudioDriver final : public CAudioDriver {
public:
CSDLAudioDriver (Application::CApplicationContext& applicationContext, Detectors::CAudioPlayingDetector& detector,
Recorders::CPlaybackRecorder& recorder);
~CSDLAudioDriver () override;
/** @inheritdoc */
void addStream (CAudioStream* stream) override;
/** /**
* Audio output buffers for streams being played under SDL * @return All the registered audio streams
*/ */
struct CSDLAudioBuffer const std::vector<CSDLAudioBuffer*>& getStreams ();
{
CAudioStream* stream;
uint8_t audio_buf[(MAX_AUDIO_FRAME_SIZE * 3) / 2] = {0};
unsigned int audio_buf_size = 0;
unsigned int audio_buf_index = 0;
};
/** @inheritdoc */
[[nodiscard]] AVSampleFormat getFormat () const override;
/** @inheritdoc */
[[nodiscard]] int getSampleRate () const override;
/** @inheritdoc */
[[nodiscard]] int getChannels () const override;
/** /**
* SDL's audio driver implementation * @return The SDL's audio driver settings
*/ */
class CSDLAudioDriver : public CAudioDriver [[nodiscard]] const SDL_AudioSpec& getSpec () const;
{
public:
CSDLAudioDriver (Application::CApplicationContext& applicationContext, Detectors::CAudioPlayingDetector& detector, Recorders::CPlaybackRecorder& recorder);
~CSDLAudioDriver ();
/** @inheritdoc */ private:
void addStream (CAudioStream* stream) override; /** The device's ID */
/** SDL_AudioDeviceID m_deviceID;
* @return All the registered audio streams /** If the driver is initialized or not */
*/ bool m_initialized;
const std::vector <CSDLAudioBuffer*>& getStreams (); /** The sound output configuration */
SDL_AudioSpec m_audioSpec;
/** @inheritdoc */ /** All the playable steams */
[[nodiscard]] AVSampleFormat getFormat () const override; std::vector<CSDLAudioBuffer*> m_streams;
/** @inheritdoc */ };
[[nodiscard]] int getSampleRate () const override; } // namespace WallpaperEngine::Audio::Drivers
/** @inheritdoc */
[[nodiscard]] int getChannels () const override;
/**
* @return The SDL's audio driver settings
*/
[[nodiscard]] const SDL_AudioSpec& getSpec () const;
private:
/** The device's ID */
SDL_AudioDeviceID m_deviceID;
/** If the driver is initialized or not */
bool m_initialized;
/** The sound output configuration */
SDL_AudioSpec m_audioSpec;
/** All the playable steams */
std::vector <CSDLAudioBuffer*> m_streams;
};
}

View File

@ -1,33 +1,26 @@
#include "CAudioPlayingDetector.h" #include "CAudioPlayingDetector.h"
namespace WallpaperEngine::Audio::Drivers::Detectors namespace WallpaperEngine::Audio::Drivers::Detectors {
{ CAudioPlayingDetector::CAudioPlayingDetector (
CAudioPlayingDetector::CAudioPlayingDetector ( Application::CApplicationContext& appContext,
Application::CApplicationContext& appContext, const Render::Drivers::Detectors::CFullScreenDetector& fullscreenDetector) :
const Render::Drivers::Detectors::CFullScreenDetector& fullscreenDetector) : m_applicationContext (appContext),
m_applicationContext (appContext), m_fullscreenDetector (fullscreenDetector),
m_fullscreenDetector (fullscreenDetector), m_isPlaying (false) {}
m_isPlaying (false)
{
}
bool CAudioPlayingDetector::anythingPlaying () const bool CAudioPlayingDetector::anythingPlaying () const {
{ return this->m_isPlaying;
return this->m_isPlaying;
}
Application::CApplicationContext& CAudioPlayingDetector::getApplicationContext ()
{
return this->m_applicationContext;
}
const Render::Drivers::Detectors::CFullScreenDetector& CAudioPlayingDetector::getFullscreenDetector () const
{
return this->m_fullscreenDetector;
}
void CAudioPlayingDetector::setIsPlaying (bool newState)
{
this->m_isPlaying = newState;
}
} }
Application::CApplicationContext& CAudioPlayingDetector::getApplicationContext () {
return this->m_applicationContext;
}
const Render::Drivers::Detectors::CFullScreenDetector& CAudioPlayingDetector::getFullscreenDetector () const {
return this->m_fullscreenDetector;
}
void CAudioPlayingDetector::setIsPlaying (bool newState) {
this->m_isPlaying = newState;
}
} // namespace WallpaperEngine::Audio::Drivers::Detectors

View File

@ -1,60 +1,58 @@
#pragma once #pragma once
#include "WallpaperEngine/Render/Drivers/Detectors/CFullScreenDetector.h"
#include "WallpaperEngine/Application/CApplicationContext.h" #include "WallpaperEngine/Application/CApplicationContext.h"
#include "WallpaperEngine/Render/Drivers/Detectors/CFullScreenDetector.h"
namespace WallpaperEngine namespace WallpaperEngine {
{ namespace Application {
namespace Application class CApplicationContext;
{
class CApplicationContext;
}
namespace Render::Drivers::Detectors
{
class CFullScreenDetector;
}
namespace Audio::Drivers::Detectors
{
/**
* Base class for any implementation of audio playing detection
*/
class CAudioPlayingDetector
{
public:
CAudioPlayingDetector (Application::CApplicationContext& appContext, const Render::Drivers::Detectors::CFullScreenDetector& fullscreenDetector);
/**
* @return If any kind of sound is currently playing on the default audio device
*/
[[nodiscard]] bool anythingPlaying () const;
/**
* Updates the playing status to the specified value
*
* @param newState
*/
void setIsPlaying (bool newState);
/**
* Checks if any audio is playing and updates state accordingly
*/
virtual void update () = 0;
/**
* @return The application context using this detector
*/
[[nodiscard]] Application::CApplicationContext& getApplicationContext ();
/**
* @return The fullscreen detector used
*/
[[nodiscard]] const Render::Drivers::Detectors::CFullScreenDetector& getFullscreenDetector () const;
private:
bool m_isPlaying;
Application::CApplicationContext& m_applicationContext;
const Render::Drivers::Detectors::CFullScreenDetector& m_fullscreenDetector;
};
}
} }
namespace Render::Drivers::Detectors {
class CFullScreenDetector;
}
namespace Audio::Drivers::Detectors {
/**
* Base class for any implementation of audio playing detection
*/
class CAudioPlayingDetector {
public:
CAudioPlayingDetector (Application::CApplicationContext& appContext,
const Render::Drivers::Detectors::CFullScreenDetector& fullscreenDetector);
virtual ~CAudioPlayingDetector () = default;
/**
* @return If any kind of sound is currently playing on the default audio device
*/
[[nodiscard]] bool anythingPlaying () const;
/**
* Updates the playing status to the specified value
*
* @param newState
*/
void setIsPlaying (bool newState);
/**
* Checks if any audio is playing and updates state accordingly
*/
virtual void update () = 0;
/**
* @return The application context using this detector
*/
[[nodiscard]] Application::CApplicationContext& getApplicationContext ();
/**
* @return The fullscreen detector used
*/
[[nodiscard]] const Render::Drivers::Detectors::CFullScreenDetector& getFullscreenDetector () const;
private:
bool m_isPlaying;
Application::CApplicationContext& m_applicationContext;
const Render::Drivers::Detectors::CFullScreenDetector& m_fullscreenDetector;
};
} // namespace Audio::Drivers::Detectors
} // namespace WallpaperEngine

View File

@ -3,84 +3,76 @@
#include <unistd.h> #include <unistd.h>
namespace WallpaperEngine::Audio::Drivers::Detectors namespace WallpaperEngine::Audio::Drivers::Detectors {
{ void sinkInputInfoCallback (pa_context* context, const pa_sink_input_info* info, int eol, void* userdata) {
void sinkInputInfoCallback (pa_context* context, const pa_sink_input_info* info, int eol, void* userdata) auto* detector = static_cast<CPulseAudioPlayingDetector*> (userdata);
{
auto* detector = static_cast <CPulseAudioPlayingDetector*> (userdata);
if (info == nullptr) if (info == nullptr)
return; return;
if (info->proplist == nullptr) if (info->proplist == nullptr)
return; return;
// get processid // get processid
const char* value = pa_proplist_gets (info->proplist, PA_PROP_APPLICATION_PROCESS_ID); const char* value = pa_proplist_gets (info->proplist, PA_PROP_APPLICATION_PROCESS_ID);
if (value && atoi (value) != getpid () && pa_cvolume_avg (&info->volume) != PA_VOLUME_MUTED) if (value && atoi (value) != getpid () && pa_cvolume_avg (&info->volume) != PA_VOLUME_MUTED)
detector->setIsPlaying (true); detector->setIsPlaying (true);
}
void defaultSinkInfoCallback (pa_context* context, const pa_server_info* info, void* userdata)
{
if (info == nullptr)
return;
pa_operation* op = pa_context_get_sink_input_info_list (context, sinkInputInfoCallback, userdata);
pa_operation_unref (op);
}
CPulseAudioPlayingDetector::CPulseAudioPlayingDetector (
Application::CApplicationContext& appContext,
const Render::Drivers::Detectors::CFullScreenDetector& fullscreenDetector) :
CAudioPlayingDetector (appContext, fullscreenDetector),
m_mainloop (nullptr),
m_mainloopApi (nullptr),
m_context (nullptr)
{
this->m_mainloop = pa_mainloop_new ();
this->m_mainloopApi = pa_mainloop_get_api (this->m_mainloop);
this->m_context = pa_context_new (this->m_mainloopApi, "wallpaperengine");
pa_context_connect (this->m_context, nullptr, PA_CONTEXT_NOFLAGS, nullptr);
// lock until pulseaudio allows connection
while (pa_context_get_state (this->m_context) != PA_CONTEXT_READY)
pa_mainloop_iterate (this->m_mainloop, 1, nullptr);
}
CPulseAudioPlayingDetector::~CPulseAudioPlayingDetector ()
{
if (this->m_context)
{
pa_context_disconnect (this->m_context);
pa_context_unref (this->m_context);
}
if (this->m_mainloop)
pa_mainloop_free (this->m_mainloop);
}
void CPulseAudioPlayingDetector::update ()
{
if (!this->getApplicationContext ().settings.audio.automute)
return this->setIsPlaying (false);
if (this->getFullscreenDetector ().anythingFullscreen ())
return this->setIsPlaying (true);
// reset playing state
this->setIsPlaying (false);
// start discovery of sinks
pa_operation* op = pa_context_get_server_info (this->m_context, defaultSinkInfoCallback, (void*) this);
// wait until all the operations are done
while (pa_operation_get_state (op) == PA_OPERATION_RUNNING)
pa_mainloop_iterate (this->m_mainloop, 1, nullptr);
pa_operation_unref (op);
}
} }
void defaultSinkInfoCallback (pa_context* context, const pa_server_info* info, void* userdata) {
if (info == nullptr)
return;
pa_operation* op = pa_context_get_sink_input_info_list (context, sinkInputInfoCallback, userdata);
pa_operation_unref (op);
}
CPulseAudioPlayingDetector::CPulseAudioPlayingDetector (
Application::CApplicationContext& appContext,
const Render::Drivers::Detectors::CFullScreenDetector& fullscreenDetector) :
CAudioPlayingDetector (appContext, fullscreenDetector),
m_mainloop (nullptr),
m_mainloopApi (nullptr),
m_context (nullptr) {
this->m_mainloop = pa_mainloop_new ();
this->m_mainloopApi = pa_mainloop_get_api (this->m_mainloop);
this->m_context = pa_context_new (this->m_mainloopApi, "wallpaperengine");
pa_context_connect (this->m_context, nullptr, PA_CONTEXT_NOFLAGS, nullptr);
// lock until pulseaudio allows connection
while (pa_context_get_state (this->m_context) != PA_CONTEXT_READY)
pa_mainloop_iterate (this->m_mainloop, 1, nullptr);
}
CPulseAudioPlayingDetector::~CPulseAudioPlayingDetector () {
if (this->m_context) {
pa_context_disconnect (this->m_context);
pa_context_unref (this->m_context);
}
if (this->m_mainloop)
pa_mainloop_free (this->m_mainloop);
}
void CPulseAudioPlayingDetector::update () {
if (!this->getApplicationContext ().settings.audio.automute)
return this->setIsPlaying (false);
if (this->getFullscreenDetector ().anythingFullscreen ())
return this->setIsPlaying (true);
// reset playing state
this->setIsPlaying (false);
// start discovery of sinks
pa_operation* op = pa_context_get_server_info (this->m_context, defaultSinkInfoCallback, this);
// wait until all the operations are done
while (pa_operation_get_state (op) == PA_OPERATION_RUNNING)
pa_mainloop_iterate (this->m_mainloop, 1, nullptr);
pa_operation_unref (op);
}
} // namespace WallpaperEngine::Audio::Drivers::Detectors

View File

@ -1,23 +1,22 @@
#pragma once #pragma once
#include "CAudioPlayingDetector.h"
#include <condition_variable> #include <condition_variable>
#include <mutex> #include <mutex>
#include "CAudioPlayingDetector.h"
#include <pulse/pulseaudio.h> #include <pulse/pulseaudio.h>
namespace WallpaperEngine::Audio::Drivers::Detectors namespace WallpaperEngine::Audio::Drivers::Detectors {
{ class CPulseAudioPlayingDetector final : public CAudioPlayingDetector {
class CPulseAudioPlayingDetector : public CAudioPlayingDetector public:
{ explicit CPulseAudioPlayingDetector (Application::CApplicationContext& appContext,
public: const Render::Drivers::Detectors::CFullScreenDetector&);
explicit CPulseAudioPlayingDetector (Application::CApplicationContext& appContext, const Render::Drivers::Detectors::CFullScreenDetector&); ~CPulseAudioPlayingDetector () override;
~CPulseAudioPlayingDetector ();
void update () override; void update () override;
private: private:
pa_mainloop* m_mainloop; pa_mainloop* m_mainloop;
pa_mainloop_api* m_mainloopApi; pa_mainloop_api* m_mainloopApi;
pa_context* m_context; pa_context* m_context;
}; };
} } // namespace WallpaperEngine::Audio::Drivers::Detectors

View File

@ -1,14 +1,14 @@
#pragma once #pragma once
namespace WallpaperEngine::Audio::Drivers::Recorders namespace WallpaperEngine::Audio::Drivers::Recorders {
{ class CPlaybackRecorder {
class CPlaybackRecorder public:
{ virtual ~CPlaybackRecorder () = default;
public:
virtual void update () = 0;
float audio16[16] = {0}; virtual void update () = 0;
float audio32[32] = {0};
float audio64[64] = {0}; float audio16 [16] = {0};
}; float audio32 [32] = {0};
} float audio64 [64] = {0};
};
} // namespace WallpaperEngine::Audio::Drivers::Recorders

View File

@ -1,223 +1,205 @@
#include <cstring>
#include <cmath>
#include <glm/common.hpp>
#include "CPulseAudioPlaybackRecorder.h" #include "CPulseAudioPlaybackRecorder.h"
#include "WallpaperEngine/Logging/CLog.h"
#include "External/Android/fft.h" #include "External/Android/fft.h"
#include "WallpaperEngine/Logging/CLog.h"
#include <cmath>
#include <cstring>
#include <glm/common.hpp>
namespace WallpaperEngine::Audio::Drivers::Recorders namespace WallpaperEngine::Audio::Drivers::Recorders {
{ float movetowards (float current, float target, float maxDelta) {
float movetowards(float current, float target, float maxDelta) if (abs (target - current) <= maxDelta)
{ return target;
if (abs(target - current) <= maxDelta)
return target;
return current + glm::sign(target - current) * maxDelta; return current + glm::sign (target - current) * maxDelta;
} }
void pa_stream_notify_cb(pa_stream *stream, void* /*userdata*/) void pa_stream_notify_cb (pa_stream* stream, void* /*userdata*/) {
{ switch (pa_stream_get_state (stream)) {
const pa_stream_state state = pa_stream_get_state(stream); case PA_STREAM_FAILED: sLog.error ("Cannot open stream for capture. Audio processing is disabled"); break;
switch (state) { case PA_STREAM_READY: sLog.debug ("Capture stream ready"); break;
case PA_STREAM_FAILED:
sLog.error ("Cannot open stream for capture. Audio processing is disabled");
break;
case PA_STREAM_READY:
sLog.debug ("Capture stream ready");
break;
}
}
void pa_stream_read_cb(pa_stream *stream, const size_t /*nbytes*/, void* userdata)
{
auto* recorder = reinterpret_cast<CPulseAudioPlaybackRecorder*>(userdata);
// Careful when to pa_stream_peek() and pa_stream_drop()!
// c.f. https://www.freedesktop.org/software/pulseaudio/doxygen/stream_8h.html#ac2838c449cde56e169224d7fe3d00824
uint8_t *data = nullptr;
size_t currentSize;
if (pa_stream_peek(stream, (const void**)&data, &currentSize) != 0) {
sLog.error ("Failed to peek at stream data...");
return;
}
if (data == nullptr && currentSize == 0) {
// No data in the buffer, ignore.
return;
} else if (data == nullptr && currentSize > 0) {
// Hole in the buffer. We must drop it.
if (pa_stream_drop(stream) != 0) {
sLog.error ("Failed to drop a hole while capturing!");
return;
}
} else if (currentSize > 0 && data) {
size_t dataToCopy = std::min (currentSize, WAVE_BUFFER_SIZE - recorder->currentWritePointer);
memcpy (&recorder->audio_buffer_tmp [recorder->currentWritePointer], data, dataToCopy * sizeof (uint8_t));
recorder->currentWritePointer += dataToCopy;
if (recorder->currentWritePointer == WAVE_BUFFER_SIZE) {
// copy to the final buffer
memcpy (recorder->audio_buffer, recorder->audio_buffer_tmp, WAVE_BUFFER_SIZE * sizeof (uint8_t));
// reset the write pointer
recorder->currentWritePointer = 0;
recorder->fullframeReady = true;
}
// any data read left?
if (dataToCopy < currentSize) {
while ((currentSize - dataToCopy) > WAVE_BUFFER_SIZE)
dataToCopy += WAVE_BUFFER_SIZE; // there's more than one full frame available, skip it entirely
// data pending, keep it in the buffer
memcpy (recorder->audio_buffer_tmp, data + dataToCopy, (currentSize - dataToCopy) * sizeof (uint8_t));
recorder->currentWritePointer = currentSize - dataToCopy;
}
}
if (pa_stream_drop(stream) != 0) {
sLog.error ("Failed to drop data after peeking");
}
}
void pa_server_info_cb(pa_context *ctx, const pa_server_info *info, void* userdata)
{
auto* recorder = reinterpret_cast<CPulseAudioPlaybackRecorder*>(userdata);
pa_sample_spec spec;
spec.format = PA_SAMPLE_U8;
spec.rate = 44100;
spec.channels = 1;
if (recorder->getCaptureStream ())
{
pa_stream_unref (recorder->getCaptureStream ());
// get rid of the reference just in case
recorder->setCaptureStream (nullptr);
}
pa_stream* captureStream = pa_stream_new(ctx, "output monitor", &spec, nullptr);
// store the stream first, if the record start fails there'll still be a reference to it
// so it can be free'd later
recorder->setCaptureStream (captureStream),
pa_stream_set_state_callback(captureStream, &pa_stream_notify_cb, userdata);
pa_stream_set_read_callback(captureStream, &pa_stream_read_cb, userdata);
std::string monitor_name(info->default_sink_name);
monitor_name += ".monitor";
if (pa_stream_connect_record(captureStream, monitor_name.c_str(), nullptr, PA_STREAM_NOFLAGS) != 0) {
sLog.error ("Failed to connect to input for recording");
return;
}
}
void pa_context_subscribe_cb (pa_context *ctx, pa_subscription_event_type_t t, uint32_t idx, void *userdata)
{
// sink changes mean re-take the stream
pa_context_get_server_info(ctx, &pa_server_info_cb, userdata);
}
void pa_context_notify_cb(pa_context *ctx, void* userdata)
{
const pa_context_state state = pa_context_get_state(ctx);
switch (state) {
case PA_CONTEXT_READY:
{
//set callback
pa_context_set_subscribe_callback (ctx, pa_context_subscribe_cb, userdata);
//set events mask and enable event callback.
pa_operation* o = pa_context_subscribe (
ctx, static_cast<pa_subscription_mask_t>(PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE),
NULL, NULL
);
if (o)
pa_operation_unref (o);
// context being ready means to fetch the sink too
pa_context_get_server_info(ctx, &pa_server_info_cb, userdata);
break;
}
case PA_CONTEXT_FAILED:
sLog.error ("PulseAudio context initialization failed. Audio processing is disabled");
break;
}
}
CPulseAudioPlaybackRecorder::CPulseAudioPlaybackRecorder () :
m_captureStream (nullptr)
{
this->m_mainloop = pa_mainloop_new ();
this->m_mainloopApi = pa_mainloop_get_api (this->m_mainloop);
this->m_context = pa_context_new (this->m_mainloopApi, "wallpaperengine-audioprocessing");
pa_context_set_state_callback (this->m_context, &pa_context_notify_cb, this);
if (pa_context_connect(this->m_context, nullptr, PA_CONTEXT_NOFLAGS, nullptr) < 0) {
sLog.error ("PulseAudio connection failed! Audio processing is disabled");
return;
}
// wait until the context is ready
while (pa_context_get_state (this->m_context) != PA_CONTEXT_READY)
pa_mainloop_iterate (this->m_mainloop, 1, nullptr);
}
CPulseAudioPlaybackRecorder::~CPulseAudioPlaybackRecorder ()
{
pa_context_disconnect(this->m_context);
pa_mainloop_free(this->m_mainloop);
}
pa_stream* CPulseAudioPlaybackRecorder::getCaptureStream ()
{
return this->m_captureStream;
}
void CPulseAudioPlaybackRecorder::setCaptureStream (pa_stream* stream)
{
this->m_captureStream = stream;
}
void CPulseAudioPlaybackRecorder::update ()
{
pa_mainloop_iterate (this->m_mainloop, 0, nullptr);
// interpolate current values to the destination
for (int i = 0; i < 64; i ++) {
this->audio64 [i] = movetowards (this->audio64[i], fft_destination64[i], 0.1f);
if (i >= 32)
continue;
this->audio32 [i] = movetowards (this->audio32[i], fft_destination32[i], 0.1f);
if (i >= 16)
continue;
this->audio16 [i] = movetowards (this->audio16[i], fft_destination16[i], 0.1f);
}
if (!this->fullframeReady)
return;
this->fullframeReady = false;
External::Android::doFft (audio_fft, audio_buffer);
for (int i = 0; i < 64; i ++) {
int paramInt = (i + 2) * 2;
float f1 = audio_fft[paramInt];
float f2 = audio_fft[paramInt + 1];
f2 = f1 * f1 + f2 * f2;
f1 = 0.0F;
if (f2 > 0.0F)
f1 = 0.35F * (float)log10(f2);
this->fft_destination64[i] = fmin(1.0F, f1 * (float)(2.0f - pow(M_E, (1.0F - i / 63.0F) * 1.0f - 0.5f)));
this->fft_destination32[i >> 1] = fmin(1.0F, f1 * (float)(2.0f - pow(M_E, (1.0F - i / 31.0F) * 1.0f - 0.5f)));
this->fft_destination16[i >> 2] = fmin(1.0F, f1 * (float)(2.0f - pow(M_E, (1.0F - i / 15.0F) * 1.0f - 0.5f)));
}
} }
} }
void pa_stream_read_cb (pa_stream* stream, const size_t /*nbytes*/, void* userdata) {
auto* recorder = static_cast<CPulseAudioPlaybackRecorder*> (userdata);
// Careful when to pa_stream_peek() and pa_stream_drop()!
// c.f. https://www.freedesktop.org/software/pulseaudio/doxygen/stream_8h.html#ac2838c449cde56e169224d7fe3d00824
const void* data = nullptr;
size_t currentSize;
if (pa_stream_peek (stream, &data, &currentSize) != 0) {
sLog.error ("Failed to peek at stream data...");
return;
}
if (data == nullptr && currentSize == 0) {
// No data in the buffer, ignore.
return;
}
if (data == nullptr && currentSize > 0) {
// Hole in the buffer. We must drop it.
if (pa_stream_drop (stream) != 0) {
sLog.error ("Failed to drop a hole while capturing!");
return;
}
} else if (currentSize > 0 && data) {
size_t dataToCopy = std::min (currentSize, WAVE_BUFFER_SIZE - recorder->currentWritePointer);
memcpy (&recorder->audio_buffer_tmp [recorder->currentWritePointer], data, dataToCopy * sizeof (uint8_t));
recorder->currentWritePointer += dataToCopy;
if (recorder->currentWritePointer == WAVE_BUFFER_SIZE) {
// copy to the final buffer
memcpy (recorder->audio_buffer, recorder->audio_buffer_tmp, WAVE_BUFFER_SIZE * sizeof (uint8_t));
// reset the write pointer
recorder->currentWritePointer = 0;
recorder->fullframeReady = true;
}
// any data read left?
if (dataToCopy < currentSize) {
while ((currentSize - dataToCopy) > WAVE_BUFFER_SIZE)
dataToCopy += WAVE_BUFFER_SIZE; // there's more than one full frame available, skip it entirely
// data pending, keep it in the buffer
memcpy (recorder->audio_buffer_tmp, data + dataToCopy, (currentSize - dataToCopy) * sizeof (uint8_t));
recorder->currentWritePointer = currentSize - dataToCopy;
}
}
if (pa_stream_drop (stream) != 0) {
sLog.error ("Failed to drop data after peeking");
}
}
void pa_server_info_cb (pa_context* ctx, const pa_server_info* info, void* userdata) {
auto* recorder = static_cast<CPulseAudioPlaybackRecorder*> (userdata);
pa_sample_spec spec;
spec.format = PA_SAMPLE_U8;
spec.rate = 44100;
spec.channels = 1;
if (recorder->getCaptureStream ()) {
pa_stream_unref (recorder->getCaptureStream ());
// get rid of the reference just in case
recorder->setCaptureStream (nullptr);
}
pa_stream* captureStream = pa_stream_new (ctx, "output monitor", &spec, nullptr);
// store the stream first, if the record start fails there'll still be a reference to it
// so it can be free'd later
recorder->setCaptureStream (captureStream),
pa_stream_set_state_callback (captureStream, &pa_stream_notify_cb, userdata);
pa_stream_set_read_callback (captureStream, &pa_stream_read_cb, userdata);
std::string monitor_name (info->default_sink_name);
monitor_name += ".monitor";
if (pa_stream_connect_record (captureStream, monitor_name.c_str (), nullptr, PA_STREAM_NOFLAGS) != 0) {
sLog.error ("Failed to connect to input for recording");
}
}
void pa_context_subscribe_cb (pa_context* ctx, pa_subscription_event_type_t t, uint32_t idx, void* userdata) {
// sink changes mean re-take the stream
pa_context_get_server_info (ctx, &pa_server_info_cb, userdata);
}
void pa_context_notify_cb (pa_context* ctx, void* userdata) {
switch (pa_context_get_state (ctx)) {
case PA_CONTEXT_READY: {
// set callback
pa_context_set_subscribe_callback (ctx, pa_context_subscribe_cb, userdata);
// set events mask and enable event callback.
pa_operation* o = pa_context_subscribe (
ctx, static_cast<pa_subscription_mask_t> (PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE),
nullptr, nullptr);
if (o)
pa_operation_unref (o);
// context being ready means to fetch the sink too
pa_context_get_server_info (ctx, &pa_server_info_cb, userdata);
break;
}
case PA_CONTEXT_FAILED:
sLog.error ("PulseAudio context initialization failed. Audio processing is disabled");
break;
}
}
CPulseAudioPlaybackRecorder::CPulseAudioPlaybackRecorder () : m_captureStream (nullptr) {
this->m_mainloop = pa_mainloop_new ();
this->m_mainloopApi = pa_mainloop_get_api (this->m_mainloop);
this->m_context = pa_context_new (this->m_mainloopApi, "wallpaperengine-audioprocessing");
pa_context_set_state_callback (this->m_context, &pa_context_notify_cb, this);
if (pa_context_connect (this->m_context, nullptr, PA_CONTEXT_NOFLAGS, nullptr) < 0) {
sLog.error ("PulseAudio connection failed! Audio processing is disabled");
return;
}
// wait until the context is ready
while (pa_context_get_state (this->m_context) != PA_CONTEXT_READY)
pa_mainloop_iterate (this->m_mainloop, 1, nullptr);
}
CPulseAudioPlaybackRecorder::~CPulseAudioPlaybackRecorder () {
pa_context_disconnect (this->m_context);
pa_mainloop_free (this->m_mainloop);
}
pa_stream* CPulseAudioPlaybackRecorder::getCaptureStream () {
return this->m_captureStream;
}
void CPulseAudioPlaybackRecorder::setCaptureStream (pa_stream* stream) {
this->m_captureStream = stream;
}
void CPulseAudioPlaybackRecorder::update () {
pa_mainloop_iterate (this->m_mainloop, 0, nullptr);
// interpolate current values to the destination
for (int i = 0; i < 64; i++) {
this->audio64 [i] = movetowards (this->audio64 [i], fft_destination64 [i], 0.1f);
if (i >= 32)
continue;
this->audio32 [i] = movetowards (this->audio32 [i], fft_destination32 [i], 0.1f);
if (i >= 16)
continue;
this->audio16 [i] = movetowards (this->audio16 [i], fft_destination16 [i], 0.1f);
}
if (!this->fullframeReady)
return;
this->fullframeReady = false;
External::Android::doFft (audio_fft, audio_buffer);
for (int i = 0; i < 64; i++) {
const int paramInt = (i + 2) * 2;
float f1 = audio_fft [paramInt];
float f2 = audio_fft [paramInt + 1];
f2 = f1 * f1 + f2 * f2;
f1 = 0.0F;
if (f2 > 0.0F)
f1 = 0.35F * static_cast<float> (log10 (f2));
this->fft_destination64 [i] =
fmin (1.0F, f1 * static_cast<float> (2.0f - pow (M_E, (1.0F - i / 63.0F) * 1.0f - 0.5f)));
this->fft_destination32 [i >> 1] =
fmin (1.0F, f1 * static_cast<float> (2.0f - pow (M_E, (1.0F - i / 31.0F) * 1.0f - 0.5f)));
this->fft_destination16 [i >> 2] =
fmin (1.0F, f1 * static_cast<float> (2.0f - pow (M_E, (1.0F - i / 15.0F) * 1.0f - 0.5f)));
}
}
} // namespace WallpaperEngine::Audio::Drivers::Recorders

View File

@ -1,45 +1,43 @@
#pragma once #pragma once
#include <pulse/pulseaudio.h>
#include "External/Android/fft.h"
#include "CPlaybackRecorder.h" #include "CPlaybackRecorder.h"
#include "External/Android/fft.h"
#include <pulse/pulseaudio.h>
namespace WallpaperEngine::Audio::Drivers::Recorders namespace WallpaperEngine::Audio::Drivers::Recorders {
{ class CPlaybackRecorder;
class CPlaybackRecorder;
class CPulseAudioPlaybackRecorder : public CPlaybackRecorder class CPulseAudioPlaybackRecorder final : public CPlaybackRecorder {
{ public:
public: CPulseAudioPlaybackRecorder ();
CPulseAudioPlaybackRecorder (); ~CPulseAudioPlaybackRecorder () override;
~CPulseAudioPlaybackRecorder ();
void update () override; void update () override;
/** /**
* @return The current stream we're capturing from * @return The current stream we're capturing from
*/ */
[[nodiscard]] pa_stream* getCaptureStream (); [[nodiscard]] pa_stream* getCaptureStream ();
/** /**
* @param stream The new stream to be capturing off from * @param stream The new stream to be capturing off from
*/ */
void setCaptureStream (pa_stream* stream); void setCaptureStream (pa_stream* stream);
uint8_t audio_buffer [WAVE_BUFFER_SIZE] = {0x80}; uint8_t audio_buffer [WAVE_BUFFER_SIZE] = {0x80};
uint8_t audio_buffer_tmp [WAVE_BUFFER_SIZE] = {0x80}; uint8_t audio_buffer_tmp [WAVE_BUFFER_SIZE] = {0x80};
uint8_t audio_fft [WAVE_BUFFER_SIZE] = {0}; uint8_t audio_fft [WAVE_BUFFER_SIZE] = {0};
size_t currentWritePointer = 0; size_t currentWritePointer = 0;
bool fullframeReady = false; bool fullframeReady = false;
private: private:
pa_mainloop* m_mainloop; pa_mainloop* m_mainloop;
pa_mainloop_api* m_mainloopApi; pa_mainloop_api* m_mainloopApi;
pa_context* m_context; pa_context* m_context;
pa_stream* m_captureStream; pa_stream* m_captureStream;
float fft_destination64[64]; float fft_destination64 [64];
float fft_destination32[32]; float fft_destination32 [32];
float fft_destination16[16]; float fft_destination16 [16];
}; };
} } // namespace WallpaperEngine::Audio::Drivers::Recorders

View File

@ -1,13 +1,13 @@
#include "common.h"
#include "CObject.h" #include "CObject.h"
#include "common.h"
#include <utility>
#include "WallpaperEngine/Core/UserSettings/CUserSettingBoolean.h"
#include "WallpaperEngine/Core/Objects/CImage.h"
#include "WallpaperEngine/Core/Objects/CSound.h"
#include "WallpaperEngine/Core/Objects/CParticle.h"
#include "WallpaperEngine/Core/CScene.h"
#include "WallpaperEngine/Core/CProject.h" #include "WallpaperEngine/Core/CProject.h"
#include "WallpaperEngine/Core/CScene.h"
#include "WallpaperEngine/Core/Objects/CImage.h"
#include "WallpaperEngine/Core/Objects/CParticle.h"
#include "WallpaperEngine/Core/Objects/CSound.h"
#include "WallpaperEngine/Core/UserSettings/CUserSettingBoolean.h"
#include <utility>
#include "WallpaperEngine/Assets/CContainer.h" #include "WallpaperEngine/Assets/CContainer.h"
@ -15,35 +15,25 @@ using namespace WallpaperEngine::Core;
using namespace WallpaperEngine::Assets; using namespace WallpaperEngine::Assets;
using namespace WallpaperEngine::Core::UserSettings; using namespace WallpaperEngine::Core::UserSettings;
CObject::CObject ( CObject::CObject (CScene* scene, CUserSettingBoolean* visible, uint32_t id, std::string name, std::string type,
CScene* scene, CUserSettingVector3* origin, CUserSettingVector3* scale, const glm::vec3& angles) :
CUserSettingBoolean* visible,
uint32_t id,
std::string name,
std::string type,
CUserSettingVector3* origin,
CUserSettingVector3* scale,
const glm::vec3& angles) :
m_scene (scene), m_scene (scene),
m_visible (visible), m_visible (visible),
m_id (id), m_id (id),
m_name (std::move(name)), m_name (std::move (name)),
m_type (std::move(type)), m_type (std::move (type)),
m_origin (origin), m_origin (origin),
m_scale (scale), m_scale (scale),
m_angles (angles) m_angles (angles) {}
{
}
CObject* CObject::fromJSON (json data, CScene* scene, CContainer* container) CObject* CObject::fromJSON (json data, CScene* scene, CContainer* container) {
{
std::string json = data.dump (); std::string json = data.dump ();
auto id_it = jsonFindRequired (data, "id", "Objects must have id"); auto id_it = jsonFindRequired (data, "id", "Objects must have id");
auto visible = jsonFindUserConfig <CUserSettingBoolean> (data, "visible", false); auto visible = jsonFindUserConfig<CUserSettingBoolean> (data, "visible", false);
auto origin = jsonFindUserConfig <CUserSettingVector3> (data, "origin", {0, 0, 0}); auto origin = jsonFindUserConfig<CUserSettingVector3> (data, "origin", {0, 0, 0});
auto scale = jsonFindUserConfig <CUserSettingVector3> (data, "scale", {1, 1, 1}); auto scale = jsonFindUserConfig<CUserSettingVector3> (data, "scale", {1, 1, 1});
auto angles_val = jsonFindDefault <std::string> (data, "angles", "0.0 0.0 0.0"); auto angles_val = jsonFindDefault<std::string> (data, "angles", "0.0 0.0 0.0");
auto name_it = jsonFindRequired (data, "name", "Objects must have name"); auto name_it = jsonFindRequired (data, "name", "Objects must have name");
auto effects_it = data.find ("effects"); auto effects_it = data.find ("effects");
auto dependencies_it = data.find ("dependencies"); auto dependencies_it = data.find ("dependencies");
@ -56,142 +46,89 @@ CObject* CObject::fromJSON (json data, CScene* scene, CContainer* container)
CObject* object; CObject* object;
if (image_it != data.end () && !(*image_it).is_null ()) if (image_it != data.end () && !image_it->is_null ()) {
{ object = Objects::CImage::fromJSON (scene, data, container, visible, *id_it, *name_it, origin, scale,
object = Objects::CImage::fromJSON ( WallpaperEngine::Core::aToVector3 (angles_val));
scene, } else if (sound_it != data.end () && !sound_it->is_null ()) {
data, object = Objects::CSound::fromJSON (scene, data, visible, *id_it, *name_it, origin, scale,
container, WallpaperEngine::Core::aToVector3 (angles_val));
visible, } else if (particle_it != data.end () && !particle_it->is_null ()) {
*id_it,
*name_it,
origin,
scale,
WallpaperEngine::Core::aToVector3 (angles_val)
);
}
else if (sound_it != data.end () && !(*sound_it).is_null ())
{
object = Objects::CSound::fromJSON (
scene,
data,
visible,
*id_it,
*name_it,
origin,
scale,
WallpaperEngine::Core::aToVector3 (angles_val)
);
}
else if (particle_it != data.end () && !(*particle_it).is_null ())
{
/// TODO: XXXHACK -- TO REMOVE WHEN PARTICLE SUPPORT IS PROPERLY IMPLEMENTED /// TODO: XXXHACK -- TO REMOVE WHEN PARTICLE SUPPORT IS PROPERLY IMPLEMENTED
try try {
{ object = Objects::CParticle::fromFile (scene, particle_it->get<std::string> (), container, visible, *id_it,
object = Objects::CParticle::fromFile ( *name_it, origin, scale);
scene, } catch (std::runtime_error&) {
(*particle_it).get <std::string> (),
container,
visible,
*id_it,
*name_it,
origin,
scale
);
}
catch (std::runtime_error& ex)
{
return nullptr; return nullptr;
} }
} } else if (text_it != data.end () && !text_it->is_null ()) {
else if (text_it != data.end () && !(*text_it).is_null ())
{
/// TODO: XXXHACK -- TO REMOVE WHEN TEXT SUPPORT IS IMPLEMENTED /// TODO: XXXHACK -- TO REMOVE WHEN TEXT SUPPORT IS IMPLEMENTED
return nullptr; return nullptr;
} } else if (light_it != data.end () && !light_it->is_null ()) {
else if (light_it != data.end () && !(*light_it).is_null ())
{
/// TODO: XXXHACK -- TO REMOVE WHEN LIGHT SUPPORT IS IMPLEMENTED /// TODO: XXXHACK -- TO REMOVE WHEN LIGHT SUPPORT IS IMPLEMENTED
return nullptr; return nullptr;
} } else {
else
{
sLog.exception ("Unknown object type detected: ", *name_it); sLog.exception ("Unknown object type detected: ", *name_it);
} }
if (effects_it != data.end () && (*effects_it).is_array ()) if (effects_it != data.end () && effects_it->is_array ()) {
{ for (auto& cur : *effects_it) {
for (auto& cur : *effects_it) auto effectVisible = jsonFindUserConfig<CUserSettingBoolean> (cur, "visible", true);
{
auto effectVisible = jsonFindUserConfig <CUserSettingBoolean> (cur, "visible", true);
if (!effectVisible->processValue (scene->getProject ().getProperties ())) if (!effectVisible->processValue (scene->getProject ().getProperties ()))
continue; continue;
object->insertEffect ( object->insertEffect (Objects::CEffect::fromJSON (cur, effectVisible, object, container));
Objects::CEffect::fromJSON (cur, effectVisible, object, container)
);
} }
} }
if (dependencies_it != data.end () && (*dependencies_it).is_array ()) if (dependencies_it != data.end () && dependencies_it->is_array ())
for (const auto& cur : *dependencies_it) for (const auto& cur : *dependencies_it)
object->insertDependency (cur); object->insertDependency (cur);
return object; return object;
} }
glm::vec3 CObject::getOrigin () const glm::vec3 CObject::getOrigin () const {
{
return this->m_origin->processValue (this->getScene ()->getProject ().getProperties ()); return this->m_origin->processValue (this->getScene ()->getProject ().getProperties ());
} }
glm::vec3 CObject::getScale () const glm::vec3 CObject::getScale () const {
{
return this->m_scale->processValue (this->getScene ()->getProject ().getProperties ()); return this->m_scale->processValue (this->getScene ()->getProject ().getProperties ());
} }
const glm::vec3& CObject::getAngles () const const glm::vec3& CObject::getAngles () const {
{
return this->m_angles; return this->m_angles;
} }
const std::string& CObject::getName () const const std::string& CObject::getName () const {
{
return this->m_name; return this->m_name;
} }
const std::vector<Objects::CEffect*>& CObject::getEffects () const const std::vector<Objects::CEffect*>& CObject::getEffects () const {
{
return this->m_effects; return this->m_effects;
} }
const std::vector<uint32_t>& CObject::getDependencies () const const std::vector<uint32_t>& CObject::getDependencies () const {
{
return this->m_dependencies; return this->m_dependencies;
} }
bool CObject::isVisible () const bool CObject::isVisible () const {
{
// TODO: cache this // TODO: cache this
return this->m_visible->processValue (this->getScene ()->getProject ().getProperties ()); return this->m_visible->processValue (this->getScene ()->getProject ().getProperties ());
} }
CScene* CObject::getScene () const CScene* CObject::getScene () const {
{
return this->m_scene; return this->m_scene;
} }
int CObject::getId () const int CObject::getId () const {
{
return this->m_id; return this->m_id;
} }
void CObject::insertEffect (Objects::CEffect* effect) void CObject::insertEffect (Objects::CEffect* effect) {
{
this->m_effects.push_back (effect); this->m_effects.push_back (effect);
} }
void CObject::insertDependency (uint32_t dependency)
{ void CObject::insertDependency (uint32_t dependency) {
this->m_dependencies.push_back (dependency); this->m_dependencies.push_back (dependency);
} }

View File

@ -8,76 +8,75 @@
#include "WallpaperEngine/Core/UserSettings/CUserSettingFloat.h" #include "WallpaperEngine/Core/UserSettings/CUserSettingFloat.h"
#include "WallpaperEngine/Core/UserSettings/CUserSettingVector3.h" #include "WallpaperEngine/Core/UserSettings/CUserSettingVector3.h"
namespace WallpaperEngine::Core namespace WallpaperEngine::Core {
{ class CScene;
class CScene;
} }
namespace WallpaperEngine::Core::Objects namespace WallpaperEngine::Core::Objects {
{ class CEffect;
class CEffect;
} }
namespace WallpaperEngine::Core::UserSettings namespace WallpaperEngine::Core::UserSettings {
{ class CUserSettingBoolean;
class CUserSettingBoolean;
} }
namespace WallpaperEngine::Core namespace WallpaperEngine::Core {
{ using json = nlohmann::json;
using json = nlohmann::json; using namespace WallpaperEngine::Assets;
using namespace WallpaperEngine::Assets; using namespace WallpaperEngine::Core::UserSettings;
using namespace WallpaperEngine::Core::UserSettings;
class CObject class CObject {
{ friend class CScene;
friend class CScene;
public:
static CObject* fromJSON (json data, CScene* scene, CContainer* container);
template<class T> const T* as () const { assert (is <T> ()); return (const T*) this; } public:
template<class T> T* as () { assert (is <T> ()); return (T*) this; } static CObject* fromJSON (json data, CScene* scene, CContainer* container);
template<class T> bool is () { return this->m_type == T::Type; } template <class T> const T* as () const {
assert (is<T> ());
return reinterpret_cast<const T*> (this);
}
const std::vector<Objects::CEffect*>& getEffects () const; template <class T> T* as () {
const std::vector<uint32_t>& getDependencies () const; assert (is<T> ());
int getId () const; return reinterpret_cast<T*> (this);
}
glm::vec3 getOrigin () const; template <class T> bool is () {
glm::vec3 getScale () const; return this->m_type == T::Type;
const glm::vec3& getAngles () const; }
const std::string& getName () const;
bool isVisible () const; const std::vector<Objects::CEffect*>& getEffects () const;
CScene* getScene () const; const std::vector<uint32_t>& getDependencies () const;
protected: int getId () const;
CObject (
CScene* scene,
CUserSettingBoolean* visible,
uint32_t id,
std::string name,
std::string type,
CUserSettingVector3* origin,
CUserSettingVector3* scale,
const glm::vec3& angles
);
void insertEffect (Objects::CEffect* effect); glm::vec3 getOrigin () const;
void insertDependency (uint32_t dependency); glm::vec3 getScale () const;
private: const glm::vec3& getAngles () const;
std::string m_type; const std::string& getName () const;
CUserSettingBoolean* m_visible; bool isVisible () const;
uint32_t m_id; CScene* getScene () const;
std::string m_name;
CUserSettingVector3* m_origin;
CUserSettingVector3* m_scale;
glm::vec3 m_angles;
std::vector<Objects::CEffect*> m_effects; protected:
std::vector<uint32_t> m_dependencies; CObject (CScene* scene, CUserSettingBoolean* visible, uint32_t id, std::string name, std::string type,
CUserSettingVector3* origin, CUserSettingVector3* scale, const glm::vec3& angles);
CScene* m_scene; void insertEffect (Objects::CEffect* effect);
}; void insertDependency (uint32_t dependency);
}
private:
std::string m_type;
CUserSettingBoolean* m_visible;
uint32_t m_id;
std::string m_name;
CUserSettingVector3* m_origin;
CUserSettingVector3* m_scale;
glm::vec3 m_angles;
std::vector<Objects::CEffect*> m_effects;
std::vector<uint32_t> m_dependencies;
CScene* m_scene;
};
} // namespace WallpaperEngine::Core

View File

@ -12,18 +12,16 @@ using namespace WallpaperEngine::Assets;
CProject::CProject (std::string title, std::string type, CContainer* container) : CProject::CProject (std::string title, std::string type, CContainer* container) :
m_title (std::move (title)), m_title (std::move (title)),
m_type (std::move (type)), m_type (std::move (type)),
m_container (container) m_wallpaper (nullptr),
{ m_container (container) {}
}
CProject* CProject::fromFile (const std::string& filename, CContainer* container) CProject* CProject::fromFile (const std::string& filename, CContainer* container) {
{
json content = json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container)); json content = json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container));
std::string title = *jsonFindRequired (content, "title", "Project title missing"); const std::string title = *jsonFindRequired (content, "title", "Project title missing");
std::string type = *jsonFindRequired (content, "type", "Project type missing"); std::string type = *jsonFindRequired (content, "type", "Project type missing");
std::string file = *jsonFindRequired (content, "file", "Project's main file missing"); const std::string file = *jsonFindRequired (content, "file", "Project's main file missing");
auto general = content.find ("general"); const auto general = content.find ("general");
CWallpaper* wallpaper; CWallpaper* wallpaper;
std::transform (type.begin (), type.end (), type.begin (), tolower); std::transform (type.begin (), type.end (), type.begin (), tolower);
@ -33,7 +31,7 @@ CProject* CProject::fromFile (const std::string& filename, CContainer* container
if (type == "scene") if (type == "scene")
wallpaper = CScene::fromFile (file, *project, container); wallpaper = CScene::fromFile (file, *project, container);
else if (type == "video") else if (type == "video")
wallpaper = new CVideo (file.c_str (), *project); wallpaper = new CVideo (file, *project);
else if (type == "web") else if (type == "web")
sLog.exception ("Web wallpapers are not supported yet"); sLog.exception ("Web wallpapers are not supported yet");
else else
@ -41,14 +39,11 @@ CProject* CProject::fromFile (const std::string& filename, CContainer* container
project->setWallpaper (wallpaper); project->setWallpaper (wallpaper);
if (general != content.end ()) if (general != content.end ()) {
{ const auto properties = general->find ("properties");
auto properties = (*general).find ("properties");
if (properties != (*general).end ()) if (properties != general->end ()) {
{ for (const auto& cur : properties->items ()) {
for (const auto& cur : (*properties).items ())
{
Projects::CProperty* property = Projects::CProperty::fromJSON (cur.value (), cur.key ()); Projects::CProperty* property = Projects::CProperty::fromJSON (cur.value (), cur.key ());
if (property != nullptr) if (property != nullptr)
@ -60,37 +55,30 @@ CProject* CProject::fromFile (const std::string& filename, CContainer* container
return project; return project;
} }
void CProject::setWallpaper (CWallpaper* wallpaper) void CProject::setWallpaper (CWallpaper* wallpaper) {
{
this->m_wallpaper = wallpaper; this->m_wallpaper = wallpaper;
} }
CWallpaper* CProject::getWallpaper () const CWallpaper* CProject::getWallpaper () const {
{
return this->m_wallpaper; return this->m_wallpaper;
} }
const std::string& CProject::getTitle () const const std::string& CProject::getTitle () const {
{
return this->m_title; return this->m_title;
} }
const std::string& CProject::getType () const const std::string& CProject::getType () const {
{
return this->m_type; return this->m_type;
} }
const std::vector<Projects::CProperty*>& CProject::getProperties () const const std::vector<Projects::CProperty*>& CProject::getProperties () const {
{
return this->m_properties; return this->m_properties;
} }
CContainer* CProject::getContainer () CContainer* CProject::getContainer () {
{
return this->m_container; return this->m_container;
} }
void CProject::insertProperty (Projects::CProperty* property) void CProject::insertProperty (Projects::CProperty* property) {
{
this->m_properties.push_back (property); this->m_properties.push_back (property);
} }

View File

@ -6,37 +6,36 @@
#include "WallpaperEngine/Assets/CContainer.h" #include "WallpaperEngine/Assets/CContainer.h"
namespace WallpaperEngine::Core namespace WallpaperEngine::Core {
{ using json = nlohmann::json;
using json = nlohmann::json; using namespace WallpaperEngine::Assets;
using namespace WallpaperEngine::Assets;
class CWallpaper; class CWallpaper;
class CProject class CProject {
{ public:
public: static CProject* fromFile (const std::string& filename, CContainer* container);
static CProject* fromFile (const std::string& filename, CContainer* container);
CWallpaper* getWallpaper () const; CWallpaper* getWallpaper () const;
const std::string& getTitle () const; const std::string& getTitle () const;
const std::string& getType () const; const std::string& getType () const;
const std::vector<Projects::CProperty*>& getProperties () const; const std::vector<Projects::CProperty*>& getProperties () const;
CContainer* getContainer (); CContainer* getContainer ();
protected: protected:
CProject (std::string title, std::string type, CContainer* container); CProject (std::string title, std::string type, CContainer* container);
void setWallpaper (CWallpaper* wallpaper); void setWallpaper (CWallpaper* wallpaper);
void insertProperty (Projects::CProperty* property); void insertProperty (Projects::CProperty* property);
private:
std::vector<Projects::CProperty*> m_properties;
std::string m_title; private:
std::string m_type; std::vector<Projects::CProperty*> m_properties;
CWallpaper* m_wallpaper;
CContainer* m_container; std::string m_title;
}; std::string m_type;
} CWallpaper* m_wallpaper;
CContainer* m_container;
};
} // namespace WallpaperEngine::Core

View File

@ -8,27 +8,12 @@
using namespace WallpaperEngine::Core; using namespace WallpaperEngine::Core;
CScene::CScene ( CScene::CScene (CProject& project, CContainer* container, Scenes::CCamera* camera, glm::vec3 ambientColor,
CProject& project, CUserSettingBoolean* bloom, CUserSettingFloat* bloomStrength, CUserSettingFloat* bloomThreshold,
CContainer* container, bool cameraFade, bool cameraParallax, double cameraParallaxAmount, double cameraParallaxDelay,
Scenes::CCamera* camera, double cameraParallaxMouseInfluence, bool cameraPreview, bool cameraShake, double cameraShakeAmplitude,
glm::vec3 ambientColor, double cameraShakeRoughness, double cameraShakeSpeed, CUserSettingVector3* clearColor,
CUserSettingBoolean* bloom, Scenes::CProjection* orthogonalProjection, glm::vec3 skylightColor) :
CUserSettingFloat* bloomStrength,
CUserSettingFloat* bloomThreshold,
bool cameraFade,
bool cameraParallax,
double cameraParallaxAmount,
double cameraParallaxDelay,
double cameraParallaxMouseInfluence,
bool cameraPreview,
bool cameraShake,
double cameraShakeAmplitude,
double cameraShakeRoughness,
double cameraShakeSpeed,
CUserSettingVector3* clearColor,
Scenes::CProjection* orthogonalProjection,
glm::vec3 skylightColor) :
CWallpaper (Type, project), CWallpaper (Type, project),
m_container (container), m_container (container),
m_camera (camera), m_camera (camera),
@ -48,60 +33,44 @@ CScene::CScene (
m_cameraShakeSpeed (cameraShakeSpeed), m_cameraShakeSpeed (cameraShakeSpeed),
m_clearColor (clearColor), m_clearColor (clearColor),
m_orthogonalProjection (orthogonalProjection), m_orthogonalProjection (orthogonalProjection),
m_skylightColor (skylightColor) m_skylightColor (skylightColor) {}
{
}
CScene* CScene::fromFile (const std::string& filename, CProject& project, CContainer* container) CScene* CScene::fromFile (const std::string& filename, CProject& project, CContainer* container) {
{
std::string stringContent = WallpaperEngine::FileSystem::loadFullFile (filename, container); std::string stringContent = WallpaperEngine::FileSystem::loadFullFile (filename, container);
json content = json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container)); json content = json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container));
auto camera_it = jsonFindRequired (content, "camera", "Scenes must have a defined camera"); const auto camera_it = jsonFindRequired (content, "camera", "Scenes must have a defined camera");
auto general_it = jsonFindRequired (content, "general", "Scenes must have a general section"); const auto general_it = jsonFindRequired (content, "general", "Scenes must have a general section");
auto objects_it = jsonFindRequired (content, "objects", "Scenes must have a list of objects to display"); const auto objects_it = jsonFindRequired (content, "objects", "Scenes must have a list of objects to display");
// TODO: FIND IF THESE DEFAULTS ARE SENSIBLE OR NOT AND PERFORM PROPER VALIDATION WHEN CAMERA PREVIEW AND CAMERA PARALLAX ARE PRESENT // TODO: FIND IF THESE DEFAULTS ARE SENSIBLE OR NOT AND PERFORM PROPER VALIDATION WHEN CAMERA PREVIEW AND CAMERA
auto ambientcolor = jsonFindDefault <std::string> (*general_it, "ambientcolor", "0 0 0"); // PARALLAX ARE PRESENT
auto bloom = jsonFindUserConfig <CUserSettingBoolean> (*general_it, "bloom", false); const auto ambientcolor = jsonFindDefault<std::string> (*general_it, "ambientcolor", "0 0 0");
auto bloomstrength = jsonFindUserConfig <CUserSettingFloat> (*general_it, "bloomstrength", 0.0); const auto bloom = jsonFindUserConfig<CUserSettingBoolean> (*general_it, "bloom", false);
auto bloomthreshold = jsonFindUserConfig <CUserSettingFloat> (*general_it, "bloomthreshold", 0.0); const auto bloomstrength = jsonFindUserConfig<CUserSettingFloat> (*general_it, "bloomstrength", 0.0);
auto camerafade = jsonFindDefault <bool> (*general_it, "camerafade", false); const auto bloomthreshold = jsonFindUserConfig<CUserSettingFloat> (*general_it, "bloomthreshold", 0.0);
auto cameraparallax = jsonFindDefault <bool> (*general_it, "cameraparallax", true); const auto camerafade = jsonFindDefault<bool> (*general_it, "camerafade", false);
auto cameraparallaxamount = jsonFindDefault <double> (*general_it, "cameraparallaxamount", 1.0f); const auto cameraparallax = jsonFindDefault<bool> (*general_it, "cameraparallax", true);
auto cameraparallaxdelay = jsonFindDefault <double> (*general_it, "cameraparallaxdelay", 0.0f); const auto cameraparallaxamount = jsonFindDefault<double> (*general_it, "cameraparallaxamount", 1.0f);
auto cameraparallaxmouseinfluence = jsonFindDefault <double> (*general_it, "cameraparallaxmouseinfluence", 1.0f); const auto cameraparallaxdelay = jsonFindDefault<double> (*general_it, "cameraparallaxdelay", 0.0f);
auto camerapreview = jsonFindDefault <bool> (*general_it, "camerapreview", false); const auto cameraparallaxmouseinfluence =
auto camerashake = jsonFindDefault <bool> (*general_it, "camerashake", false); jsonFindDefault<double> (*general_it, "cameraparallaxmouseinfluence", 1.0f);
auto camerashakeamplitude = jsonFindDefault <double> (*general_it, "camerashakeamplitude", 0.0f); const auto camerapreview = jsonFindDefault<bool> (*general_it, "camerapreview", false);
auto camerashakeroughness = jsonFindDefault <double> (*general_it, "camerashakeroughness", 0.0f); const auto camerashake = jsonFindDefault<bool> (*general_it, "camerashake", false);
auto camerashakespeed = jsonFindDefault <double> (*general_it, "camerashakespeed", 0.0f); const auto camerashakeamplitude = jsonFindDefault<double> (*general_it, "camerashakeamplitude", 0.0f);
auto clearcolor = jsonFindUserConfig <CUserSettingVector3> (*general_it, "clearcolor", {1, 1, 1}); const auto camerashakeroughness = jsonFindDefault<double> (*general_it, "camerashakeroughness", 0.0f);
auto orthogonalprojection_it = jsonFindRequired (*general_it, "orthogonalprojection", "General section must have orthogonal projection info"); const auto camerashakespeed = jsonFindDefault<double> (*general_it, "camerashakespeed", 0.0f);
auto skylightcolor = jsonFindDefault <std::string> (*general_it, "skylightcolor", "0 0 0"); const auto clearcolor = jsonFindUserConfig<CUserSettingVector3> (*general_it, "clearcolor", {1, 1, 1});
const auto orthogonalprojection_it =
jsonFindRequired (*general_it, "orthogonalprojection", "General section must have orthogonal projection info");
const auto skylightcolor = jsonFindDefault<std::string> (*general_it, "skylightcolor", "0 0 0");
CScene* scene = new CScene ( auto* scene = new CScene (
project, project, container, Scenes::CCamera::fromJSON (*camera_it), WallpaperEngine::Core::aToColorf (ambientcolor),
container, bloom, bloomstrength, bloomthreshold, camerafade, cameraparallax, cameraparallaxamount, cameraparallaxdelay,
Scenes::CCamera::fromJSON (*camera_it), cameraparallaxmouseinfluence, camerapreview, camerashake, camerashakeamplitude, camerashakeroughness,
WallpaperEngine::Core::aToColorf(ambientcolor), camerashakespeed, clearcolor, Scenes::CProjection::fromJSON (*orthogonalprojection_it),
bloom, WallpaperEngine::Core::aToColorf (skylightcolor));
bloomstrength,
bloomthreshold,
camerafade,
cameraparallax,
cameraparallaxamount,
cameraparallaxdelay,
cameraparallaxmouseinfluence,
camerapreview,
camerashake,
camerashakeamplitude,
camerashakeroughness,
camerashakespeed,
clearcolor,
Scenes::CProjection::fromJSON (*orthogonalprojection_it),
WallpaperEngine::Core::aToColorf(skylightcolor)
);
for (const auto& cur : *objects_it) for (const auto& cur : *objects_it)
scene->insertObject (CObject::fromJSON (cur, scene, container)); scene->insertObject (CObject::fromJSON (cur, scene, container));
@ -109,117 +78,95 @@ CScene* CScene::fromFile (const std::string& filename, CProject& project, CConta
return scene; return scene;
} }
const std::map<uint32_t, CObject*>& CScene::getObjects () const const std::map<uint32_t, CObject*>& CScene::getObjects () const {
{
return this->m_objects; return this->m_objects;
} }
const std::vector<CObject*>& CScene::getObjectsByRenderOrder () const
{ const std::vector<CObject*>& CScene::getObjectsByRenderOrder () const {
return this->m_objectsByRenderOrder; return this->m_objectsByRenderOrder;
} }
void CScene::insertObject (CObject* object) void CScene::insertObject (CObject* object) {
{
/// TODO: XXXHACK -- TO REMOVE WHEN PARTICLE SUPPORT IS PROPERLY IMPLEMENTED /// TODO: XXXHACK -- TO REMOVE WHEN PARTICLE SUPPORT IS PROPERLY IMPLEMENTED
if (object != nullptr) if (object != nullptr) {
{
this->m_objects.insert (std::make_pair (object->getId (), object)); this->m_objects.insert (std::make_pair (object->getId (), object));
this->m_objectsByRenderOrder.emplace_back (object); this->m_objectsByRenderOrder.emplace_back (object);
} }
} }
CContainer* CScene::getContainer () CContainer* CScene::getContainer () {
{
return this->m_container; return this->m_container;
} }
const Scenes::CCamera* CScene::getCamera () const const Scenes::CCamera* CScene::getCamera () const {
{
return this->m_camera; return this->m_camera;
} }
const glm::vec3 &CScene::getAmbientColor() const const glm::vec3& CScene::getAmbientColor () const {
{
return this->m_ambientColor; return this->m_ambientColor;
} }
const bool CScene::isBloom () const const bool CScene::isBloom () const {
{
return this->m_bloom->processValue (this->getProject ().getProperties ()); return this->m_bloom->processValue (this->getProject ().getProperties ());
} }
double CScene::getBloomStrength () const double CScene::getBloomStrength () const {
{
return this->m_bloomStrength->processValue (this->getProject ().getProperties ()); return this->m_bloomStrength->processValue (this->getProject ().getProperties ());
} }
double CScene::getBloomThreshold () const double CScene::getBloomThreshold () const {
{
return this->m_bloomThreshold->processValue (this->getProject ().getProperties ()); return this->m_bloomThreshold->processValue (this->getProject ().getProperties ());
} }
const bool CScene::isCameraFade () const const bool CScene::isCameraFade () const {
{
return this->m_cameraFade; return this->m_cameraFade;
} }
const bool CScene::isCameraParallax () const const bool CScene::isCameraParallax () const {
{
return this->m_cameraParallax; return this->m_cameraParallax;
} }
const double CScene::getCameraParallaxAmount () const const double CScene::getCameraParallaxAmount () const {
{
return this->m_cameraParallaxAmount; return this->m_cameraParallaxAmount;
} }
const double CScene::getCameraParallaxDelay () const const double CScene::getCameraParallaxDelay () const {
{
return this->m_cameraParallaxDelay; return this->m_cameraParallaxDelay;
} }
const double CScene::getCameraParallaxMouseInfluence () const const double CScene::getCameraParallaxMouseInfluence () const {
{
return this->m_cameraParallaxMouseInfluence; return this->m_cameraParallaxMouseInfluence;
} }
const bool CScene::isCameraPreview () const const bool CScene::isCameraPreview () const {
{
return this->m_cameraPreview; return this->m_cameraPreview;
} }
const bool CScene::isCameraShake () const const bool CScene::isCameraShake () const {
{
return this->m_cameraShake; return this->m_cameraShake;
} }
const double CScene::getCameraShakeAmplitude () const const double CScene::getCameraShakeAmplitude () const {
{
return this->m_cameraShakeAmplitude; return this->m_cameraShakeAmplitude;
} }
const double CScene::getCameraShakeRoughness () const const double CScene::getCameraShakeRoughness () const {
{
return this->m_cameraShakeRoughness; return this->m_cameraShakeRoughness;
} }
const double CScene::getCameraShakeSpeed () const const double CScene::getCameraShakeSpeed () const {
{
return this->m_cameraShakeSpeed; return this->m_cameraShakeSpeed;
} }
glm::vec3 CScene::getClearColor () const glm::vec3 CScene::getClearColor () const {
{
return this->m_clearColor->processValue (this->getProject ().getProperties ()); return this->m_clearColor->processValue (this->getProject ().getProperties ());
} }
Scenes::CProjection* CScene::getOrthogonalProjection () const Scenes::CProjection* CScene::getOrthogonalProjection () const {
{
return this->m_orthogonalProjection; return this->m_orthogonalProjection;
} }
const glm::vec3& CScene::getSkylightColor () const const glm::vec3& CScene::getSkylightColor () const {
{
return this->m_skylightColor; return this->m_skylightColor;
} }

View File

@ -8,94 +8,77 @@
#include "WallpaperEngine/Core/Scenes/CCamera.h" #include "WallpaperEngine/Core/Scenes/CCamera.h"
#include "WallpaperEngine/Core/Scenes/CProjection.h" #include "WallpaperEngine/Core/Scenes/CProjection.h"
namespace WallpaperEngine::Core namespace WallpaperEngine::Core {
{ using json = nlohmann::json;
using json = nlohmann::json;
class CObject; class CObject;
class CScene : public CWallpaper class CScene : public CWallpaper {
{ public:
public: static CScene* fromFile (const std::string& filename, CProject& project, CContainer* container);
static CScene* fromFile (const std::string& filename, CProject& project, CContainer* container);
const std::map<uint32_t, CObject*>& getObjects () const; const std::map<uint32_t, CObject*>& getObjects () const;
const std::vector<CObject*>& getObjectsByRenderOrder () const; const std::vector<CObject*>& getObjectsByRenderOrder () const;
const glm::vec3& getAmbientColor() const; const glm::vec3& getAmbientColor () const;
const bool isBloom() const; const bool isBloom () const;
double getBloomStrength() const; double getBloomStrength () const;
double getBloomThreshold() const; double getBloomThreshold () const;
const bool isCameraFade() const; const bool isCameraFade () const;
const bool isCameraParallax() const; const bool isCameraParallax () const;
const double getCameraParallaxAmount() const; const double getCameraParallaxAmount () const;
const double getCameraParallaxDelay() const; const double getCameraParallaxDelay () const;
const double getCameraParallaxMouseInfluence() const; const double getCameraParallaxMouseInfluence () const;
const bool isCameraPreview() const; const bool isCameraPreview () const;
const bool isCameraShake() const; const bool isCameraShake () const;
const double getCameraShakeAmplitude() const; const double getCameraShakeAmplitude () const;
const double getCameraShakeRoughness() const; const double getCameraShakeRoughness () const;
const double getCameraShakeSpeed() const; const double getCameraShakeSpeed () const;
glm::vec3 getClearColor() const; glm::vec3 getClearColor () const;
Scenes::CProjection* getOrthogonalProjection() const; Scenes::CProjection* getOrthogonalProjection () const;
const glm::vec3& getSkylightColor() const; const glm::vec3& getSkylightColor () const;
const Scenes::CCamera* getCamera () const; const Scenes::CCamera* getCamera () const;
protected: protected:
friend class CWallpaper; friend class CWallpaper;
CScene ( CScene (CProject& project, CContainer* container, Scenes::CCamera* camera, glm::vec3 ambientColor,
CProject& project, CUserSettingBoolean* bloom, CUserSettingFloat* bloomStrength, CUserSettingFloat* bloomThreshold,
CContainer* container, bool cameraFade, bool cameraParallax, double cameraParallaxAmount, double cameraParallaxDelay,
Scenes::CCamera* camera, double cameraParallaxMouseInfluence, bool cameraPreview, bool cameraShake, double cameraShakeAmplitude,
glm::vec3 ambientColor, double cameraShakeRoughness, double cameraShakeSpeed, CUserSettingVector3* clearColor,
CUserSettingBoolean* bloom, Scenes::CProjection* orthogonalProjection, glm::vec3 skylightColor);
CUserSettingFloat* bloomStrength,
CUserSettingFloat* bloomThreshold,
bool cameraFade,
bool cameraParallax,
double cameraParallaxAmount,
double cameraParallaxDelay,
double cameraParallaxMouseInfluence,
bool cameraPreview,
bool cameraShake,
double cameraShakeAmplitude,
double cameraShakeRoughness,
double cameraShakeSpeed,
CUserSettingVector3* clearColor,
Scenes::CProjection* orthogonalProjection,
glm::vec3 skylightColor
);
static const std::string Type; static const std::string Type;
void insertObject (CObject* object); void insertObject (CObject* object);
CContainer* getContainer (); CContainer* getContainer ();
private:
CContainer* m_container;
Scenes::CCamera* m_camera;
// data from general section on the json private:
glm::vec3 m_ambientColor; CContainer* m_container;
CUserSettingBoolean* m_bloom; Scenes::CCamera* m_camera;
CUserSettingFloat* m_bloomStrength;
CUserSettingFloat* m_bloomThreshold;
bool m_cameraFade;
bool m_cameraParallax;
double m_cameraParallaxAmount;
double m_cameraParallaxDelay;
double m_cameraParallaxMouseInfluence;
bool m_cameraPreview;
bool m_cameraShake;
double m_cameraShakeAmplitude;
double m_cameraShakeRoughness;
double m_cameraShakeSpeed;
CUserSettingVector3* m_clearColor;
Scenes::CProjection* m_orthogonalProjection;
glm::vec3 m_skylightColor;
std::map<uint32_t, CObject*> m_objects; // data from general section on the json
std::vector<CObject*> m_objectsByRenderOrder; glm::vec3 m_ambientColor;
}; CUserSettingBoolean* m_bloom;
} CUserSettingFloat* m_bloomStrength;
CUserSettingFloat* m_bloomThreshold;
bool m_cameraFade;
bool m_cameraParallax;
double m_cameraParallaxAmount;
double m_cameraParallaxDelay;
double m_cameraParallaxMouseInfluence;
bool m_cameraPreview;
bool m_cameraShake;
double m_cameraShakeAmplitude;
double m_cameraShakeRoughness;
double m_cameraShakeSpeed;
CUserSettingVector3* m_clearColor;
Scenes::CProjection* m_orthogonalProjection;
glm::vec3 m_skylightColor;
std::map<uint32_t, CObject*> m_objects;
std::vector<CObject*> m_objectsByRenderOrder;
};
} // namespace WallpaperEngine::Core

View File

@ -6,12 +6,9 @@ using namespace WallpaperEngine::Core;
CVideo::CVideo (std::string filename, CProject& project) : CVideo::CVideo (std::string filename, CProject& project) :
CWallpaper (Type, project), CWallpaper (Type, project),
m_filename (std::move(filename)) m_filename (std::move (filename)) {}
{
}
const std::string& CVideo::getFilename () const std::string& CVideo::getFilename () {
{
return this->m_filename; return this->m_filename;
} }

View File

@ -1,32 +1,27 @@
#pragma once #pragma once
#include "Core.h"
#include "CWallpaper.h" #include "CWallpaper.h"
#include "Core.h"
extern "C" extern "C" {
{
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
#include <libavformat/avformat.h> #include <libavformat/avformat.h>
#include <libavutil/imgutils.h> #include <libavutil/imgutils.h>
#include <libswscale/swscale.h> #include <libswscale/swscale.h>
} }
namespace WallpaperEngine::Core namespace WallpaperEngine::Core {
{ class CVideo : public CWallpaper {
class CVideo : public CWallpaper public:
{ explicit CVideo (std::string filename, CProject& project);
public:
explicit CVideo (std::string filename, CProject& project);
const std::string& getFilename (); const std::string& getFilename ();
protected: protected:
friend class CWallpaper; friend class CWallpaper;
const std::string m_filename; const std::string m_filename;
static const std::string Type; static const std::string Type;
};
private: } // namespace WallpaperEngine::Core
};
}

View File

@ -4,13 +4,8 @@
using namespace WallpaperEngine::Core; using namespace WallpaperEngine::Core;
CWallpaper::CWallpaper (std::string type, CProject& project) : CWallpaper::CWallpaper (std::string type, CProject& project) : m_type (std::move (type)), m_project (project) {}
m_type (std::move(type)),
m_project (project)
{
}
CProject& CWallpaper::getProject () const CProject& CWallpaper::getProject () const {
{
return this->m_project; return this->m_project;
} }

View File

@ -4,28 +4,35 @@
#include "CProject.h" #include "CProject.h"
namespace WallpaperEngine::Core namespace WallpaperEngine::Core {
{ class CProject;
class CProject;
class CWallpaper class CWallpaper {
{ public:
public: template <class T> const T* as () const {
template<class T> const T* as () const { assert (is <T> ()); return (const T*) this; } assert (is<T> ());
template<class T> T* as () { assert (is <T> ()); return (T*) this; } return reinterpret_cast<const T*> (this);
}
template<class T> bool is () { return this->m_type == T::Type; } template <class T> T* as () {
assert (is<T> ());
return reinterpret_cast<T*> (this);
}
CWallpaper (std::string type, CProject& project); template <class T> bool is () {
return this->m_type == T::Type;
}
CProject& getProject () const; CWallpaper (std::string type, CProject& project);
protected: CProject& getProject () const;
friend class CProject;
private: protected:
CProject& m_project; friend class CProject;
std::string m_type; private:
}; CProject& m_project;
}
std::string m_type;
};
} // namespace WallpaperEngine::Core

View File

@ -9,78 +9,87 @@
using namespace WallpaperEngine; using namespace WallpaperEngine;
using namespace WallpaperEngine::Core::UserSettings; using namespace WallpaperEngine::Core::UserSettings;
glm::vec4 Core::aToVector4 (const char* str) glm::vec4 Core::aToVector4 (const char* str) {
{ float x = strtof (str, const_cast<char**> (&str));
float x = strtof (str, const_cast <char**> (&str)); while (*str == ' ') str ++; while (*str == ' ')
float y = strtof (str, const_cast <char**> (&str)); while (*str == ' ') str ++; str++;
float z = strtof (str, const_cast <char**> (&str)); while (*str == ' ') str ++; float y = strtof (str, const_cast<char**> (&str));
float w = strtof (str, const_cast <char**> (&str)); while (*str == ' ')
str++;
float z = strtof (str, const_cast<char**> (&str));
while (*str == ' ')
str++;
float w = strtof (str, const_cast<char**> (&str));
return {x, y, z, w}; return {x, y, z, w};
} }
glm::vec3 Core::aToVector3 (const char* str) glm::vec3 Core::aToVector3 (const char* str) {
{ float x = strtof (str, const_cast<char**> (&str));
float x = strtof (str, const_cast <char**> (&str)); while (*str == ' ') str ++; while (*str == ' ')
float y = strtof (str, const_cast <char**> (&str)); while (*str == ' ') str ++; str++;
float z = strtof (str, const_cast <char**> (&str)); float y = strtof (str, const_cast<char**> (&str));
while (*str == ' ')
str++;
float z = strtof (str, const_cast<char**> (&str));
return {x, y, z}; return {x, y, z};
} }
glm::vec2 Core::aToVector2 (const char* str) glm::vec2 Core::aToVector2 (const char* str) {
{ float x = strtof (str, const_cast<char**> (&str));
float x = strtof (str, const_cast <char**> (&str)); while (*str == ' ') str ++; while (*str == ' ')
float y = strtof (str, const_cast <char**> (&str)); str++;
float y = strtof (str, const_cast<char**> (&str));
return {x, y}; return {x, y};
} }
glm::vec4 Core::aToVector4 (const std::string& str) glm::vec4 Core::aToVector4 (const std::string& str) {
{
return Core::aToVector4 (str.c_str ()); return Core::aToVector4 (str.c_str ());
} }
glm::vec3 Core::aToVector3 (const std::string& str) glm::vec3 Core::aToVector3 (const std::string& str) {
{
return Core::aToVector3 (str.c_str ()); return Core::aToVector3 (str.c_str ());
} }
glm::vec2 Core::aToVector2 (const std::string& str) glm::vec2 Core::aToVector2 (const std::string& str) {
{
return Core::aToVector2 (str.c_str ()); return Core::aToVector2 (str.c_str ());
} }
glm::vec3 Core::aToColorf (const char* str) glm::vec3 Core::aToColorf (const char* str) {
{ float r = strtof (str, const_cast<char**> (&str));
float r = strtof (str, const_cast<char **>(&str)); while (*str == ' ') str ++; while (*str == ' ')
float g = strtof (str, const_cast<char **>(&str)); while (*str == ' ') str ++; str++;
float b = strtof (str, const_cast<char **>(&str)); float g = strtof (str, const_cast<char**> (&str));
while (*str == ' ')
str++;
float b = strtof (str, const_cast<char**> (&str));
return {r, g, b}; return {r, g, b};
} }
glm::vec3 Core::aToColorf (const std::string& str) glm::vec3 Core::aToColorf (const std::string& str) {
{
return aToColorf (str.c_str ()); return aToColorf (str.c_str ());
} }
glm::ivec3 Core::aToColori (const char* str) glm::ivec3 Core::aToColori (const char* str) {
{ auto r = static_cast<uint8_t> (strtol (str, const_cast<char**> (&str), 10));
auto r = static_cast <uint8_t> (strtol (str, const_cast<char **>(&str), 10)); while (*str == ' ') str ++; while (*str == ' ')
auto g = static_cast <uint8_t> (strtol (str, const_cast<char **>(&str), 10)); while (*str == ' ') str ++; str++;
auto b = static_cast <uint8_t> (strtol (str, const_cast<char **>(&str), 10)); auto g = static_cast<uint8_t> (strtol (str, const_cast<char**> (&str), 10));
while (*str == ' ')
str++;
auto b = static_cast<uint8_t> (strtol (str, const_cast<char**> (&str), 10));
return {r, g, b}; return {r, g, b};
} }
glm::ivec3 Core::aToColori (const std::string& str) glm::ivec3 Core::aToColori (const std::string& str) {
{
return aToColori (str.c_str ()); return aToColori (str.c_str ());
} }
nlohmann::json::iterator Core::jsonFindRequired (nlohmann::json& data, const char *key, const char *notFoundMsg) nlohmann::json::iterator Core::jsonFindRequired (nlohmann::json& data, const char* key, const char* notFoundMsg) {
{
auto value = data.find (key); auto value = data.find (key);
if (value == data.end ()) if (value == data.end ())
@ -89,41 +98,34 @@ nlohmann::json::iterator Core::jsonFindRequired (nlohmann::json& data, const cha
return value; return value;
} }
nlohmann::json::iterator Core::jsonFindRequired (nlohmann::json::iterator& data, const char *key, const char *notFoundMsg) nlohmann::json::iterator Core::jsonFindRequired (const nlohmann::json::iterator& data, const char* key,
{ const char* notFoundMsg) {
auto value = (*data).find (key); auto value = data->find (key);
if (value == (*data).end ()) if (value == data->end ())
sLog.exception ("Cannot find required key (", key, ") in json: ", notFoundMsg); sLog.exception ("Cannot find required key (", key, ") in json: ", notFoundMsg);
return value; return value;
} }
template <typename T> T Core::jsonFindDefault (nlohmann::json& data, const char *key, T defaultValue) template <typename T> T Core::jsonFindDefault (nlohmann::json& data, const char* key, T defaultValue) {
{ const auto value = data.find (key);
auto value = data.find (key);
if (value == data.end () || value->type () == nlohmann::detail::value_t::null) if (value == data.end () || value->type () == nlohmann::detail::value_t::null)
return defaultValue; return defaultValue;
// type checks // type checks
if ((std::is_same <T, float>::value || std::is_same <T, double>::value)) if ((std::is_same_v<T, float> || std::is_same_v<T, double>) ) {
{
if (value->type () != nlohmann::detail::value_t::number_float && if (value->type () != nlohmann::detail::value_t::number_float &&
value->type () != nlohmann::detail::value_t::number_integer && value->type () != nlohmann::detail::value_t::number_integer &&
value->type () != nlohmann::detail::value_t::number_unsigned) value->type () != nlohmann::detail::value_t::number_unsigned) {
{
sLog.error (key, " is not of type double or integer, returning default value"); sLog.error (key, " is not of type double or integer, returning default value");
return defaultValue; return defaultValue;
} }
} } else if (std::is_same_v<T, std::string> && value->type () != nlohmann::detail::value_t::string) {
else if (std::is_same <T, std::string>::value && value->type () != nlohmann::detail::value_t::string)
{
sLog.error (key, " is not of type string, returning default value"); sLog.error (key, " is not of type string, returning default value");
return defaultValue; return defaultValue;
} } else if (std::is_same_v<T, bool> && value->type () != nlohmann::detail::value_t::boolean) {
else if (std::is_same <T, bool>::value && value->type () != nlohmann::detail::value_t::boolean)
{
sLog.error (key, " is not of type boolean, returning default value"); sLog.error (key, " is not of type boolean, returning default value");
return defaultValue; return defaultValue;
} }
@ -133,20 +135,20 @@ template <typename T> T Core::jsonFindDefault (nlohmann::json& data, const char
return *value; return *value;
} }
template bool Core::jsonFindDefault (nlohmann::json& data, const char *key, bool defaultValue); template bool Core::jsonFindDefault (nlohmann::json& data, const char* key, bool defaultValue);
template std::string Core::jsonFindDefault (nlohmann::json& data, const char *key, std::string defaultValue); template std::string Core::jsonFindDefault (nlohmann::json& data, const char* key, std::string defaultValue);
template int16_t Core::jsonFindDefault (nlohmann::json& data, const char *key, int16_t defaultValue); template int16_t Core::jsonFindDefault (nlohmann::json& data, const char* key, int16_t defaultValue);
template uint16_t Core::jsonFindDefault (nlohmann::json& data, const char *key, uint16_t defaultValue); template uint16_t Core::jsonFindDefault (nlohmann::json& data, const char* key, uint16_t defaultValue);
template int32_t Core::jsonFindDefault (nlohmann::json& data, const char *key, int32_t defaultValue); template int32_t Core::jsonFindDefault (nlohmann::json& data, const char* key, int32_t defaultValue);
template uint32_t Core::jsonFindDefault (nlohmann::json& data, const char *key, uint32_t defaultValue); template uint32_t Core::jsonFindDefault (nlohmann::json& data, const char* key, uint32_t defaultValue);
template int64_t Core::jsonFindDefault (nlohmann::json& data, const char *key, int64_t defaultValue); template int64_t Core::jsonFindDefault (nlohmann::json& data, const char* key, int64_t defaultValue);
template uint64_t Core::jsonFindDefault (nlohmann::json& data, const char *key, uint64_t defaultValue); template uint64_t Core::jsonFindDefault (nlohmann::json& data, const char* key, uint64_t defaultValue);
template float Core::jsonFindDefault (nlohmann::json& data, const char *key, float defaultValue); template float Core::jsonFindDefault (nlohmann::json& data, const char* key, float defaultValue);
template double Core::jsonFindDefault (nlohmann::json& data, const char *key, double defaultValue); template double Core::jsonFindDefault (nlohmann::json& data, const char* key, double defaultValue);
template <typename T> T* Core::jsonFindUserConfig (nlohmann::json& data, const char *key, typename T::data_type defaultValue) template <typename T>
{ T* Core::jsonFindUserConfig (nlohmann::json& data, const char* key, typename T::data_type defaultValue) {
auto it = data.find (key); const auto it = data.find (key);
if (it == data.end () || it->type () == nlohmann::detail::value_t::null) if (it == data.end () || it->type () == nlohmann::detail::value_t::null)
return T::fromScalar (defaultValue); return T::fromScalar (defaultValue);
@ -154,6 +156,9 @@ template <typename T> T* Core::jsonFindUserConfig (nlohmann::json& data, const c
return T::fromJSON (*it); return T::fromJSON (*it);
} }
template CUserSettingBoolean* Core::jsonFindUserConfig (nlohmann::json& data, const char *key, CUserSettingBoolean::data_type defaultValue); template CUserSettingBoolean* Core::jsonFindUserConfig (nlohmann::json& data, const char* key,
template CUserSettingVector3* Core::jsonFindUserConfig (nlohmann::json& data, const char *key, CUserSettingVector3::data_type defaultValue); CUserSettingBoolean::data_type defaultValue);
template CUserSettingFloat* Core::jsonFindUserConfig (nlohmann::json& data, const char *key, CUserSettingFloat::data_type defaultValue); template CUserSettingVector3* Core::jsonFindUserConfig (nlohmann::json& data, const char* key,
CUserSettingVector3::data_type defaultValue);
template CUserSettingFloat* Core::jsonFindUserConfig (nlohmann::json& data, const char* key,
CUserSettingFloat::data_type defaultValue);

View File

@ -1,29 +1,29 @@
#pragma once #pragma once
#include <string>
#include <nlohmann/json.hpp>
#include <glm/vec3.hpp>
#include <glm/vec2.hpp>
#include <glm/mat4x4.hpp> #include <glm/mat4x4.hpp>
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include <nlohmann/json.hpp>
#include <string>
namespace WallpaperEngine::Core namespace WallpaperEngine::Core {
{ glm::vec4 aToVector4 (const char* str);
glm::vec4 aToVector4 (const char* str); glm::vec3 aToVector3 (const char* str);
glm::vec3 aToVector3 (const char* str); glm::vec2 aToVector2 (const char* str);
glm::vec2 aToVector2 (const char* str);
glm::vec4 aToVector4 (const std::string& str); glm::vec4 aToVector4 (const std::string& str);
glm::vec3 aToVector3 (const std::string& str); glm::vec3 aToVector3 (const std::string& str);
glm::vec2 aToVector2 (const std::string& str); glm::vec2 aToVector2 (const std::string& str);
glm::vec3 aToColorf (const char* str); glm::vec3 aToColorf (const char* str);
glm::vec3 aToColorf (const std::string& str); glm::vec3 aToColorf (const std::string& str);
glm::ivec3 aToColori (const char* str); glm::ivec3 aToColori (const char* str);
glm::ivec3 aToColori (const std::string& str); glm::ivec3 aToColori (const std::string& str);
nlohmann::json::iterator jsonFindRequired (nlohmann::json& data, const char *key, const char *notFoundMsg); nlohmann::json::iterator jsonFindRequired (nlohmann::json& data, const char* key, const char* notFoundMsg);
nlohmann::json::iterator jsonFindRequired (nlohmann::json::iterator& data, const char *key, const char *notFoundMsg); nlohmann::json::iterator jsonFindRequired (const nlohmann::json::iterator& data, const char* key,
template <typename T> T jsonFindDefault (nlohmann::json& data, const char *key, T defaultValue); const char* notFoundMsg);
template <typename T> T* jsonFindUserConfig (nlohmann::json& data, const char *key, typename T::data_type defaultValue); template <typename T> T jsonFindDefault (nlohmann::json& data, const char* key, T defaultValue);
} template <typename T> T* jsonFindUserConfig (nlohmann::json& data, const char* key, typename T::data_type defaultValue);
} // namespace WallpaperEngine::Core

View File

@ -1,16 +1,16 @@
#include "common.h"
#include "CEffect.h" #include "CEffect.h"
#include "common.h"
#include <utility>
#include <iostream> #include <iostream>
#include <utility>
#include "WallpaperEngine/Core/CScene.h"
#include "WallpaperEngine/Core/CProject.h" #include "WallpaperEngine/Core/CProject.h"
#include "WallpaperEngine/Core/CScene.h"
#include "WallpaperEngine/Core/Objects/CImage.h" #include "WallpaperEngine/Core/Objects/CImage.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.h" #include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantFloat.h" #include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantFloat.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector4.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.h" #include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector4.h"
#include "WallpaperEngine/Core/UserSettings/CUserSettingBoolean.h" #include "WallpaperEngine/Core/UserSettings/CUserSettingBoolean.h"
@ -20,45 +20,30 @@ using namespace WallpaperEngine;
using namespace WallpaperEngine::Core::Objects; using namespace WallpaperEngine::Core::Objects;
using namespace WallpaperEngine::Core::UserSettings; using namespace WallpaperEngine::Core::UserSettings;
CEffect::CEffect ( CEffect::CEffect (std::string name, std::string description, std::string group, std::string preview, CObject* object,
std::string name, CUserSettingBoolean* visible) :
std::string description, m_name (std::move (name)),
std::string group, m_description (std::move (description)),
std::string preview, m_group (std::move (group)),
CObject* object, m_preview (std::move (preview)),
CUserSettingBoolean* visible):
m_name (std::move(name)),
m_description (std::move(description)),
m_group (std::move(group)),
m_preview (std::move(preview)),
m_object (object), m_object (object),
m_visible (visible) m_visible (visible) {}
{
}
CEffect* CEffect::fromJSON (json data, CUserSettingBoolean* visible, CObject* object, CContainer* container) CEffect* CEffect::fromJSON (json data, CUserSettingBoolean* visible, CObject* object, CContainer* container) {
{
auto file_it = jsonFindRequired (data, "file", "Object effect must have a file"); auto file_it = jsonFindRequired (data, "file", "Object effect must have a file");
auto effectpasses_it = data.find ("passes"); auto effectpasses_it = data.find ("passes");
json content = json::parse (WallpaperEngine::FileSystem::loadFullFile ((*file_it).get <std::string> (), container)); json content = json::parse (WallpaperEngine::FileSystem::loadFullFile (file_it->get<std::string> (), container));
auto name_it = jsonFindRequired (content, "name", "Effect must have a name"); auto name_it = jsonFindRequired (content, "name", "Effect must have a name");
auto description = jsonFindDefault <std::string> (content, "description", ""); auto description = jsonFindDefault<std::string> (content, "description", "");
auto group_it = jsonFindRequired (content, "group", "Effect must have a group"); auto group_it = jsonFindRequired (content, "group", "Effect must have a group");
auto preview = jsonFindDefault <std::string> (content, "preview", ""); auto preview = jsonFindDefault<std::string> (content, "preview", "");
auto passes_it = jsonFindRequired (content, "passes", "Effect must have a pass list"); auto passes_it = jsonFindRequired (content, "passes", "Effect must have a pass list");
auto dependencies_it = jsonFindRequired (content, "dependencies", ""); auto dependencies_it = jsonFindRequired (content, "dependencies", "");
auto fbos_it = content.find ("fbos"); auto fbos_it = content.find ("fbos");
auto* effect = new CEffect ( auto* effect = new CEffect (*name_it, description, *group_it, preview, object, visible);
*name_it,
description,
*group_it,
preview,
object,
visible
);
CEffect::materialsFromJSON (passes_it, effect, container); CEffect::materialsFromJSON (passes_it, effect, container);
CEffect::dependencyFromJSON (dependencies_it, effect); CEffect::dependencyFromJSON (dependencies_it, effect);
@ -66,47 +51,36 @@ CEffect* CEffect::fromJSON (json data, CUserSettingBoolean* visible, CObject* ob
if (fbos_it != content.end ()) if (fbos_it != content.end ())
CEffect::fbosFromJSON (fbos_it, effect); CEffect::fbosFromJSON (fbos_it, effect);
if (effectpasses_it != data.end ()) if (effectpasses_it != data.end ()) {
{ auto cur = effectpasses_it->begin ();
auto cur = (*effectpasses_it).begin (); auto end = effectpasses_it->end ();
auto end = (*effectpasses_it).end ();
for (int passNumber = 0; cur != end; cur ++, passNumber ++) for (int passNumber = 0; cur != end; ++cur, passNumber++) {
{ auto constants_it = cur->find ("constantshadervalues");
auto constants_it = (*cur).find ("constantshadervalues"); auto combos_it = cur->find ("combos");
auto combos_it = (*cur).find ("combos"); auto textures_it = cur->find ("textures");
auto textures_it = (*cur).find ("textures");
if (constants_it == (*cur).end () && combos_it == (*cur).end () && textures_it == (*cur).end ()) if (constants_it == cur->end () && combos_it == cur->end () && textures_it == cur->end ())
continue; continue;
Images::CMaterial* material = effect->getMaterials ().at (passNumber); Images::CMaterial* material = effect->getMaterials ().at (passNumber);
for (const auto& passCur : material->getPasses ()) for (const auto& passCur : material->getPasses ()) {
{ if (textures_it != cur->end ()) {
if (textures_it != (*cur).end ())
{
int textureNumber = 0; int textureNumber = 0;
for (const auto& texturesCur : (*textures_it)) for (const auto& texturesCur : (*textures_it)) {
{
std::string texture; std::string texture;
if (texturesCur.is_null ()) if (texturesCur.is_null ()) {
{ if (textureNumber == 0) {
if (textureNumber == 0) auto* image = object->as<CImage> ();
{
auto* image = object->as <CImage> ();
texture = (*(*image->getMaterial ()->getPasses ().begin ())->getTextures ().begin ()); texture = (*(*image->getMaterial ()->getPasses ().begin ())->getTextures ().begin ());
} } else {
else
{
texture = ""; texture = "";
} }
} } else {
else
{
texture = texturesCur; texture = texturesCur;
} }
@ -117,17 +91,15 @@ CEffect* CEffect::fromJSON (json data, CUserSettingBoolean* visible, CObject* ob
else else
passCur->insertTexture (texture); passCur->insertTexture (texture);
textureNumber ++; textureNumber++;
} }
} }
if (combos_it != (*cur).end ()) if (combos_it != cur->end ()) {
{
CEffect::combosFromJSON (combos_it, passCur); CEffect::combosFromJSON (combos_it, passCur);
} }
if (constants_it != (*cur).end ()) if (constants_it != cur->end ()) {
{
CEffect::constantsFromJSON (constants_it, passCur); CEffect::constantsFromJSON (constants_it, passCur);
} }
} }
@ -137,16 +109,14 @@ CEffect* CEffect::fromJSON (json data, CUserSettingBoolean* visible, CObject* ob
return effect; return effect;
} }
void CEffect::combosFromJSON (json::const_iterator combos_it, Core::Objects::Images::Materials::CPass* pass) void CEffect::combosFromJSON (const json::const_iterator& combos_it, Core::Objects::Images::Materials::CPass* pass) {
{ for (const auto& cur : combos_it->items ())
for (const auto& cur : (*combos_it).items ())
pass->insertCombo (cur.key (), cur.value ()); pass->insertCombo (cur.key (), cur.value ());
} }
void CEffect::constantsFromJSON (json::const_iterator constants_it, Core::Objects::Images::Materials::CPass* pass) void CEffect::constantsFromJSON (const json::const_iterator& constants_it,
{ Core::Objects::Images::Materials::CPass* pass) {
for (auto& cur : (*constants_it).items ()) for (auto& cur : constants_it->items ()) {
{
auto val = cur.value (); auto val = cur.value ();
Effects::Constants::CShaderConstant* constant; Effects::Constants::CShaderConstant* constant;
@ -155,12 +125,10 @@ void CEffect::constantsFromJSON (json::const_iterator constants_it, Core::Object
// for the UI, take the value, which is what we need // for the UI, take the value, which is what we need
// TODO: SUPPORT USER SETTINGS HERE // TODO: SUPPORT USER SETTINGS HERE
if (cur.value ().is_object ()) if (cur.value ().is_object ()) {
{
auto it = cur.value ().find ("value"); auto it = cur.value ().find ("value");
if (it == cur.value ().end ()) if (it == cur.value ().end ()) {
{
sLog.error ("Found object for shader constant without \"value\" member"); sLog.error ("Found object for shader constant without \"value\" member");
continue; continue;
} }
@ -168,21 +136,14 @@ void CEffect::constantsFromJSON (json::const_iterator constants_it, Core::Object
val = it.value (); val = it.value ();
} }
if (val.is_number_float ()) if (val.is_number_float ()) {
{ constant = new Effects::Constants::CShaderConstantFloat (val.get<float> ());
constant = new Effects::Constants::CShaderConstantFloat (val.get <float> ()); } else if (val.is_number_integer ()) {
} constant = new Effects::Constants::CShaderConstantInteger (val.get<int> ());
else if (val.is_number_integer ()) } else if (val.is_string ()) {
{
constant = new Effects::Constants::CShaderConstantInteger (val.get <int> ());
}
else if (val.is_string ())
{
// try a vector 4 first, then a vector3 and then a vector 2 // try a vector 4 first, then a vector3 and then a vector 2
constant = new Effects::Constants::CShaderConstantVector4 (WallpaperEngine::Core::aToVector4 (val)); constant = new Effects::Constants::CShaderConstantVector4 (WallpaperEngine::Core::aToVector4 (val));
} } else {
else
{
sLog.exception ("unknown shader constant type ", val); sLog.exception ("unknown shader constant type ", val);
} }
@ -190,22 +151,18 @@ void CEffect::constantsFromJSON (json::const_iterator constants_it, Core::Object
} }
} }
void CEffect::fbosFromJSON (json::const_iterator fbos_it, CEffect* effect) void CEffect::fbosFromJSON (const json::const_iterator& fbos_it, CEffect* effect) {
{
for (const auto& cur : (*fbos_it)) for (const auto& cur : (*fbos_it))
effect->insertFBO (Effects::CFBO::fromJSON (cur)); effect->insertFBO (Effects::CFBO::fromJSON (cur));
} }
void CEffect::dependencyFromJSON (json::const_iterator dependencies_it, CEffect* effect) void CEffect::dependencyFromJSON (const json::const_iterator& dependencies_it, CEffect* effect) {
{
for (const auto& cur : (*dependencies_it)) for (const auto& cur : (*dependencies_it))
effect->insertDependency (cur); effect->insertDependency (cur);
} }
void CEffect::materialsFromJSON (json::const_iterator passes_it, CEffect* effect, CContainer* container) void CEffect::materialsFromJSON (const json::const_iterator& passes_it, CEffect* effect, CContainer* container) {
{ for (const auto& cur : (*passes_it)) {
for (const auto& cur : (*passes_it))
{
auto materialfile = cur.find ("material"); auto materialfile = cur.find ("material");
auto target = cur.find ("target"); auto target = cur.find ("target");
auto bind = cur.find ("bind"); auto bind = cur.find ("bind");
@ -216,12 +173,11 @@ void CEffect::materialsFromJSON (json::const_iterator passes_it, CEffect* effect
Images::CMaterial* material; Images::CMaterial* material;
if (target == cur.end ()) if (target == cur.end ())
material = Images::CMaterial::fromFile ((*materialfile).get <std::string> (), container); material = Images::CMaterial::fromFile (materialfile->get<std::string> (), container);
else else
material = Images::CMaterial::fromFile ((*materialfile).get <std::string> (), *target, container); material = Images::CMaterial::fromFile (materialfile->get<std::string> (), *target, container);
if (bind != cur.end ()) if (bind != cur.end ()) {
{
for (const auto& bindCur : (*bind)) for (const auto& bindCur : (*bind))
material->insertTextureBind (Effects::CBind::fromJSON (bindCur)); material->insertTextureBind (Effects::CBind::fromJSON (bindCur));
} }
@ -230,28 +186,23 @@ void CEffect::materialsFromJSON (json::const_iterator passes_it, CEffect* effect
} }
} }
const std::vector<std::string>& CEffect::getDependencies () const const std::vector<std::string>& CEffect::getDependencies () const {
{
return this->m_dependencies; return this->m_dependencies;
} }
const std::vector<Images::CMaterial*>& CEffect::getMaterials () const const std::vector<Images::CMaterial*>& CEffect::getMaterials () const {
{
return this->m_materials; return this->m_materials;
} }
const std::vector<Effects::CFBO*>& CEffect::getFbos () const const std::vector<Effects::CFBO*>& CEffect::getFbos () const {
{
return this->m_fbos; return this->m_fbos;
} }
bool CEffect::isVisible () const bool CEffect::isVisible () const {
{
return this->m_visible->processValue (this->m_object->getScene ()->getProject ().getProperties ()); return this->m_visible->processValue (this->m_object->getScene ()->getProject ().getProperties ());
} }
Effects::CFBO* CEffect::findFBO (const std::string& name) Effects::CFBO* CEffect::findFBO (const std::string& name) {
{
for (const auto& cur : this->m_fbos) for (const auto& cur : this->m_fbos)
if (cur->getName () == name) if (cur->getName () == name)
return cur; return cur;
@ -259,17 +210,14 @@ Effects::CFBO* CEffect::findFBO (const std::string& name)
sLog.exception ("cannot find fbo ", name); sLog.exception ("cannot find fbo ", name);
} }
void CEffect::insertDependency (const std::string& dep) void CEffect::insertDependency (const std::string& dep) {
{
this->m_dependencies.push_back (dep); this->m_dependencies.push_back (dep);
} }
void CEffect::insertMaterial (Images::CMaterial* material) void CEffect::insertMaterial (Images::CMaterial* material) {
{
this->m_materials.push_back (material); this->m_materials.push_back (material);
} }
void CEffect::insertFBO (Effects::CFBO* fbo) void CEffect::insertFBO (Effects::CFBO* fbo) {
{
this->m_fbos.push_back (fbo); this->m_fbos.push_back (fbo);
} }

View File

@ -1,99 +1,92 @@
#pragma once #pragma once
#include "WallpaperEngine/Assets/CContainer.h"
#include "WallpaperEngine/Core/CObject.h"
#include "WallpaperEngine/Core/Core.h" #include "WallpaperEngine/Core/Core.h"
#include "WallpaperEngine/Core/Objects/Effects/CFBO.h" #include "WallpaperEngine/Core/Objects/Effects/CFBO.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.h" #include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.h"
#include "WallpaperEngine/Core/CObject.h"
#include "WallpaperEngine/Core/Objects/Images/CMaterial.h" #include "WallpaperEngine/Core/Objects/Images/CMaterial.h"
#include "WallpaperEngine/Assets/CContainer.h"
namespace WallpaperEngine::Core namespace WallpaperEngine::Core {
{ class CObject;
class CObject;
} }
namespace WallpaperEngine::Core::UserSettings namespace WallpaperEngine::Core::UserSettings {
{ class CUserSettingBoolean;
class CUserSettingBoolean;
} }
namespace WallpaperEngine::Core::Objects namespace WallpaperEngine::Core::Objects {
{ using json = nlohmann::json;
using json = nlohmann::json; using namespace WallpaperEngine::Assets;
using namespace WallpaperEngine::Assets; using namespace WallpaperEngine::Core::UserSettings;
using namespace WallpaperEngine::Core::UserSettings;
/**
* Represents an effect applied to background objects
*/
class CEffect {
public:
CEffect (std::string name, std::string description, std::string group, std::string preview, CObject* object,
CUserSettingBoolean* visible);
static CEffect* fromJSON (json data, UserSettings::CUserSettingBoolean* visible, CObject* object,
CContainer* container);
/** /**
* Represents an effect applied to background objects * @return List of dependencies for the effect to work
*/ */
class CEffect [[nodiscard]] const std::vector<std::string>& getDependencies () const;
{ /**
public: * @return List of materials the effect applies
CEffect ( */
std::string name, [[nodiscard]] const std::vector<Images::CMaterial*>& getMaterials () const;
std::string description, /**
std::string group, * @return The list of FBOs to be used for this effect
std::string preview, */
CObject* object, [[nodiscard]] const std::vector<Effects::CFBO*>& getFbos () const;
CUserSettingBoolean* visible /**
); * @return If the effect is visible or not
*/
[[nodiscard]] bool isVisible () const;
/**
* Searches the FBOs list for the given FBO
*
* @param name The FBO to search for
*
* @return
*/
Effects::CFBO* findFBO (const std::string& name);
static CEffect* fromJSON (json data, UserSettings::CUserSettingBoolean* visible, CObject* object, CContainer* container); protected:
static void constantsFromJSON (const json::const_iterator& constants_it,
Core::Objects::Images::Materials::CPass* pass);
static void combosFromJSON (const json::const_iterator& combos_it, Core::Objects::Images::Materials::CPass* pass);
static void fbosFromJSON (const json::const_iterator& fbos_it, CEffect* effect);
static void dependencyFromJSON (const json::const_iterator& dependencies_it, CEffect* effect);
static void materialsFromJSON (const json::const_iterator& passes_it, CEffect* effect, CContainer* container);
/** void insertDependency (const std::string& dep);
* @return List of dependencies for the effect to work void insertMaterial (Images::CMaterial* material);
*/ void insertFBO (Effects::CFBO* fbo);
[[nodiscard]] const std::vector<std::string>& getDependencies () const;
/**
* @return List of materials the effect applies
*/
[[nodiscard]] const std::vector<Images::CMaterial*>& getMaterials () const;
/**
* @return The list of FBOs to be used for this effect
*/
[[nodiscard]] const std::vector<Effects::CFBO*>& getFbos () const;
/**
* @return If the effect is visible or not
*/
[[nodiscard]] bool isVisible () const;
/**
* Searches the FBOs list for the given FBO
*
* @param name The FBO to search for
*
* @return
*/
Effects::CFBO* findFBO (const std::string& name);
protected:
static void constantsFromJSON (json::const_iterator constants_it, Core::Objects::Images::Materials::CPass* pass);
static void combosFromJSON (json::const_iterator combos_it, Core::Objects::Images::Materials::CPass* pass);
static void fbosFromJSON (json::const_iterator fbos_it, CEffect* effect);
static void dependencyFromJSON (json::const_iterator dependencies_it, CEffect* effect);
static void materialsFromJSON (json::const_iterator passes_it, CEffect* effect, CContainer* container);
void insertDependency (const std::string& dep); private:
void insertMaterial (Images::CMaterial* material); /** Effect's name */
void insertFBO (Effects::CFBO* fbo); std::string m_name;
/** Effect's description used in the UI */
std::string m_description;
/** Effect's group used in the UI */
std::string m_group;
/** A project that previews the given effect, used in the UI */
std::string m_preview;
/** The object the effect applies to */
CObject* m_object;
/** If the effect is visible or not */
UserSettings::CUserSettingBoolean* m_visible;
private: /** List of dependencies for the effect */
/** Effect's name */ std::vector<std::string> m_dependencies;
std::string m_name; /** List of materials the effect applies */
/** Effect's description used in the UI */ std::vector<Images::CMaterial*> m_materials;
std::string m_description; /** List of FBOs required for this effect */
/** Effect's group used in the UI */ std::vector<Effects::CFBO*> m_fbos;
std::string m_group; };
/** A project that previews the given effect, used in the UI */ } // namespace WallpaperEngine::Core::Objects
std::string m_preview;
/** The object the effect applies to */
CObject* m_object;
/** If the effect is visible or not */
UserSettings::CUserSettingBoolean* m_visible;
/** List of dependencies for the effect */
std::vector<std::string> m_dependencies;
/** List of materials the effect applies */
std::vector<Images::CMaterial*> m_materials;
/** List of FBOs required for this effect */
std::vector<Effects::CFBO*> m_fbos;
};
}

View File

@ -12,143 +12,91 @@
using namespace WallpaperEngine::Core::Objects; using namespace WallpaperEngine::Core::Objects;
using namespace WallpaperEngine::Core::UserSettings; using namespace WallpaperEngine::Core::UserSettings;
CImage::CImage ( CImage::CImage (CScene* scene, Images::CMaterial* material, CUserSettingBoolean* visible, uint32_t id, std::string name,
CScene* scene, CUserSettingVector3* origin, CUserSettingVector3* scale, const glm::vec3& angles, const glm::vec2& size,
Images::CMaterial* material, std::string alignment, CUserSettingVector3* color, CUserSettingFloat* alpha, float brightness,
CUserSettingBoolean* visible, uint32_t colorBlendMode, const glm::vec2& parallaxDepth, bool fullscreen, bool passthrough,
uint32_t id, bool autosize) :
std::string name, CObject (scene, visible, id, std::move (name), Type, origin, scale, angles),
CUserSettingVector3* origin,
CUserSettingVector3* scale,
const glm::vec3& angles,
const glm::vec2& size,
std::string alignment,
CUserSettingVector3* color,
CUserSettingFloat* alpha,
float brightness,
uint32_t colorBlendMode,
const glm::vec2& parallaxDepth,
bool fullscreen,
bool passthrough,
bool autosize
) :
CObject (scene, visible, id, std::move(name), Type, origin, scale, angles),
m_size (size), m_size (size),
m_material (material), m_material (material),
m_alignment (std::move(alignment)), m_alignment (std::move (alignment)),
m_color (color), m_color (color),
m_alpha (alpha), m_alpha (alpha),
m_brightness (brightness), m_brightness (brightness),
m_colorBlendMode (colorBlendMode), m_colorBlendMode (colorBlendMode),
m_parallaxDepth(parallaxDepth), m_parallaxDepth (parallaxDepth),
m_fullscreen (fullscreen), m_fullscreen (fullscreen),
m_passthrough (passthrough), m_passthrough (passthrough),
m_autosize (autosize) m_autosize (autosize) {}
{
WallpaperEngine::Core::CObject* CImage::fromJSON (CScene* scene, json data, CContainer* container,
CUserSettingBoolean* visible, uint32_t id, std::string name,
CUserSettingVector3* origin, CUserSettingVector3* scale,
const glm::vec3& angles) {
const auto image_it = data.find ("image");
const auto size_val = jsonFindDefault<std::string> (data, "size", "0.0 0.0"); // this one might need some adjustment
const auto alignment = jsonFindDefault<std::string> (data, "alignment", "center");
const auto alpha = jsonFindUserConfig<CUserSettingFloat> (data, "alpha", 1.0);
const auto color = jsonFindUserConfig<CUserSettingVector3> (data, "color", {1, 1, 1});
const auto brightness_val = jsonFindDefault<float> (data, "brightness", 1.0);
const auto colorBlendMode_val = jsonFindDefault<uint32_t> (data, "colorBlendMode", 0);
const auto parallaxDepth_val = jsonFindDefault<std::string> (data, "parallaxDepth", "0 0");
json content = json::parse (WallpaperEngine::FileSystem::loadFullFile (image_it->get<std::string> (), container));
const auto material_it = jsonFindRequired (content, "material", "Image must have a material");
const auto fullscreen = jsonFindDefault<bool> (content, "fullscreen", false);
const auto passthrough = jsonFindDefault<bool> (content, "passthrough", false);
const auto autosize = jsonFindDefault<bool> (content, "autosize", false);
return new CImage (scene, Images::CMaterial::fromFile (material_it->get<std::string> (), container), visible, id,
std::move (name), origin, scale, angles, WallpaperEngine::Core::aToVector2 (size_val), alignment,
color, alpha, brightness_val, colorBlendMode_val,
WallpaperEngine::Core::aToVector2 (parallaxDepth_val), fullscreen, passthrough, autosize);
} }
WallpaperEngine::Core::CObject* CImage::fromJSON ( const Images::CMaterial* CImage::getMaterial () const {
CScene* scene,
json data,
CContainer* container,
CUserSettingBoolean* visible,
uint32_t id,
std::string name,
CUserSettingVector3* origin,
CUserSettingVector3* scale,
const glm::vec3& angles)
{
auto image_it = data.find ("image");
auto size_val = jsonFindDefault <std::string> (data, "size", "0.0 0.0"); // this one might need some adjustment
auto alignment = jsonFindDefault <std::string> (data, "alignment", "center");
auto alpha = jsonFindUserConfig <CUserSettingFloat> (data, "alpha", 1.0);
auto color = jsonFindUserConfig <CUserSettingVector3> (data, "color", {1, 1, 1});
auto brightness_val = jsonFindDefault <float> (data, "brightness", 1.0);
auto colorBlendMode_val = jsonFindDefault <uint32_t> (data, "colorBlendMode", 0);
auto parallaxDepth_val = jsonFindDefault <std::string> (data, "parallaxDepth", "0 0");
json content = json::parse (WallpaperEngine::FileSystem::loadFullFile ((*image_it).get <std::string> (), container));
auto material_it = jsonFindRequired (content, "material", "Image must have a material");
auto fullscreen = jsonFindDefault <bool> (content, "fullscreen", false);
auto passthrough = jsonFindDefault <bool> (content, "passthrough", false);
auto autosize = jsonFindDefault <bool> (content, "autosize", false);
return new CImage (
scene,
Images::CMaterial::fromFile ((*material_it).get <std::string> (), container),
visible,
id,
std::move(name),
origin,
scale,
angles,
WallpaperEngine::Core::aToVector2 (size_val),
alignment,
color,
alpha,
brightness_val,
colorBlendMode_val,
WallpaperEngine::Core::aToVector2 (parallaxDepth_val),
fullscreen,
passthrough,
autosize
);
}
const Images::CMaterial* CImage::getMaterial () const
{
return this->m_material; return this->m_material;
} }
const glm::vec2& CImage::getSize () const const glm::vec2& CImage::getSize () const {
{
return this->m_size; return this->m_size;
} }
const std::string& CImage::getAlignment () const const std::string& CImage::getAlignment () const {
{
return this->m_alignment; return this->m_alignment;
} }
float CImage::getAlpha () const float CImage::getAlpha () const {
{
return this->m_alpha->processValue (this->getScene ()->getProject ().getProperties ()); return this->m_alpha->processValue (this->getScene ()->getProject ().getProperties ());
} }
glm::vec3 CImage::getColor () const glm::vec3 CImage::getColor () const {
{
return this->m_color->processValue (this->getScene ()->getProject ().getProperties ()); return this->m_color->processValue (this->getScene ()->getProject ().getProperties ());
} }
float CImage::getBrightness () const float CImage::getBrightness () const {
{
return this->m_brightness; return this->m_brightness;
} }
uint32_t CImage::getColorBlendMode () const uint32_t CImage::getColorBlendMode () const {
{
return this->m_colorBlendMode; return this->m_colorBlendMode;
} }
const glm::vec2& CImage::getParallaxDepth () const {
const glm::vec2& CImage::getParallaxDepth () const
{
return this->m_parallaxDepth; return this->m_parallaxDepth;
} }
bool CImage::isFullscreen () const bool CImage::isFullscreen () const {
{
return this->m_fullscreen; return this->m_fullscreen;
} }
bool CImage::isPassthrough () const bool CImage::isPassthrough () const {
{
return this->m_passthrough; return this->m_passthrough;
} }
bool CImage::isAutosize () const bool CImage::isAutosize () const {
{
return this->m_autosize; return this->m_autosize;
} }

View File

@ -2,8 +2,8 @@
#include "WallpaperEngine/Core/Objects/Images/CMaterial.h" #include "WallpaperEngine/Core/Objects/Images/CMaterial.h"
#include "WallpaperEngine/Core/Core.h"
#include "WallpaperEngine/Core/CObject.h" #include "WallpaperEngine/Core/CObject.h"
#include "WallpaperEngine/Core/Core.h"
#include "WallpaperEngine/Assets/CContainer.h" #include "WallpaperEngine/Assets/CContainer.h"
@ -11,109 +11,104 @@
#include "WallpaperEngine/Core/UserSettings/CUserSettingFloat.h" #include "WallpaperEngine/Core/UserSettings/CUserSettingFloat.h"
#include "WallpaperEngine/Core/UserSettings/CUserSettingVector3.h" #include "WallpaperEngine/Core/UserSettings/CUserSettingVector3.h"
namespace WallpaperEngine::Core namespace WallpaperEngine::Core {
{ class CScene;
class CScene;
} }
namespace WallpaperEngine::Core::Objects namespace WallpaperEngine::Core::Objects {
{ using json = nlohmann::json;
using json = nlohmann::json; using namespace WallpaperEngine::Assets;
using namespace WallpaperEngine::Assets; using namespace WallpaperEngine::Core::UserSettings;
using namespace WallpaperEngine::Core::UserSettings;
/**
* Represents an image in a background
*/
class CImage : public CObject {
friend class CObject;
public:
static CObject* fromJSON (CScene* scene, json data, CContainer* container, CUserSettingBoolean* visible,
uint32_t id, std::string name, CUserSettingVector3* origin, CUserSettingVector3* scale,
const glm::vec3& angles);
/** /**
* Represents an image in a background * @return The base material to use for the image
*/ */
class CImage : public CObject [[nodiscard]] const Images::CMaterial* getMaterial () const;
{ /**
friend class CObject; * @return The size of the image
public: */
static CObject* fromJSON ( [[nodiscard]] const glm::vec2& getSize () const;
CScene* scene, json data, CContainer* container, CUserSettingBoolean* visible, uint32_t id, /**
std::string name, CUserSettingVector3* origin, CUserSettingVector3* scale, const glm::vec3& angles * @return The type of alignment to use for image positioning
); */
[[nodiscard]] const std::string& getAlignment () const;
/**
* @return The alpha value for the image's rendering
*/
[[nodiscard]] float getAlpha () const;
/**
* @return The color to use for the image
*/
[[nodiscard]] glm::vec3 getColor () const;
/**
* @return The brightness to use for the image
*/
[[nodiscard]] float getBrightness () const;
/**
* @return The color blending mode to be used, special value for shaders
*/
[[nodiscard]] uint32_t getColorBlendMode () const;
/**
* @return Parallax depth of the image
*/
[[nodiscard]] const glm::vec2& getParallaxDepth () const;
/**
* @return If the image is fullscreen or not
*/
[[nodiscard]] bool isFullscreen () const;
/**
* @return If the image is passthrough or not
*/
[[nodiscard]] bool isPassthrough () const;
/**
* @return If the image is autosized or not
*/
[[nodiscard]] bool isAutosize () const;
/** protected:
* @return The base material to use for the image CImage (CScene* scene, Images::CMaterial* material, CUserSettingBoolean* visible, uint32_t id, std::string name,
*/
[[nodiscard]] const Images::CMaterial* getMaterial () const;
/**
* @return The size of the image
*/
[[nodiscard]] const glm::vec2& getSize () const;
/**
* @return The type of alignment to use for image positioning
*/
[[nodiscard]] const std::string& getAlignment () const;
/**
* @return The alpha value for the image's rendering
*/
[[nodiscard]] float getAlpha () const;
/**
* @return The color to use for the image
*/
[[nodiscard]] glm::vec3 getColor () const;
/**
* @return The brightness to use for the image
*/
[[nodiscard]] float getBrightness () const;
/**
* @return The color blending mode to be used, special value for shaders
*/
[[nodiscard]] uint32_t getColorBlendMode () const;
/**
* @return Parallax depth of the image
*/
[[nodiscard]] const glm::vec2& getParallaxDepth () const;
/**
* @return If the image is fullscreen or not
*/
[[nodiscard]] bool isFullscreen () const;
/**
* @return If the image is passthrough or not
*/
[[nodiscard]] bool isPassthrough () const;
/**
* @return If the image is autosized or not
*/
[[nodiscard]] bool isAutosize () const;
protected:
CImage (
CScene* scene, Images::CMaterial* material, CUserSettingBoolean* visible, uint32_t id, std::string name,
CUserSettingVector3* origin, CUserSettingVector3* scale, const glm::vec3& angles, const glm::vec2& size, CUserSettingVector3* origin, CUserSettingVector3* scale, const glm::vec3& angles, const glm::vec2& size,
std::string alignment, CUserSettingVector3* color, CUserSettingFloat* alpha, float brightness, std::string alignment, CUserSettingVector3* color, CUserSettingFloat* alpha, float brightness,
uint32_t colorBlendMode, const glm::vec2& parallaxDepth, bool fullscreen, bool passthrough, bool autosize uint32_t colorBlendMode, const glm::vec2& parallaxDepth, bool fullscreen, bool passthrough, bool autosize);
);
/** /**
* Type value used to differentiate the different types of objects in a background * Type value used to differentiate the different types of objects in a background
*/ */
static const std::string Type; static const std::string Type;
private: private:
/** The image's size */ /** The image's size */
glm::vec2 m_size; glm::vec2 m_size;
/** Parallax depth */ /** Parallax depth */
const glm::vec2 m_parallaxDepth; const glm::vec2 m_parallaxDepth;
/** Base material for the image */ /** Base material for the image */
Images::CMaterial* m_material; Images::CMaterial* m_material;
/** What type of alignment to use for the image's position */ /** What type of alignment to use for the image's position */
std::string m_alignment; std::string m_alignment;
/** The alpha value for the image */ /** The alpha value for the image */
CUserSettingFloat* m_alpha; CUserSettingFloat* m_alpha;
/** The brightness for the image */ /** The brightness for the image */
float m_brightness; float m_brightness;
/** The color to use for the image */ /** The color to use for the image */
CUserSettingVector3* m_color; CUserSettingVector3* m_color;
/** The color blending mode used for the image, special value for shaders */ /** The color blending mode used for the image, special value for shaders */
uint32_t m_colorBlendMode; uint32_t m_colorBlendMode;
/** If the image is fullscreen or not */ /** If the image is fullscreen or not */
bool m_fullscreen; bool m_fullscreen;
/** If the image is passthrough or not */ /** If the image is passthrough or not */
bool m_passthrough; bool m_passthrough;
/** If the image's size should be automatically determined */ /** If the image's size should be automatically determined */
bool m_autosize; bool m_autosize;
}; };
} } // namespace WallpaperEngine::Core::Objects

View File

@ -1,37 +1,21 @@
#include "CParticle.h" #include "CParticle.h"
#include <utility>
#include "WallpaperEngine/FileSystem/FileSystem.h" #include "WallpaperEngine/FileSystem/FileSystem.h"
#include <utility>
using namespace WallpaperEngine::Core::Objects; using namespace WallpaperEngine::Core::Objects;
CParticle* CParticle::fromFile ( CParticle* CParticle::fromFile (CScene* scene, const std::string& filename, CContainer* container,
CScene* scene, CUserSettingBoolean* visible, uint32_t id, std::string name,
const std::string& filename, CUserSettingVector3* origin, CUserSettingVector3* scale) {
CContainer* container,
CUserSettingBoolean* visible,
uint32_t id,
std::string name,
CUserSettingVector3* origin,
CUserSettingVector3* scale)
{
json data = json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container)); json data = json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container));
auto controlpoint_it = data.find ("controlpoint"); const auto controlpoint_it = data.find ("controlpoint");
auto starttime_it = jsonFindRequired (data, "starttime", "Particles must have start time"); const auto starttime_it = jsonFindRequired (data, "starttime", "Particles must have start time");
auto maxcount_it = jsonFindRequired (data, "maxcount", "Particles must have maximum count"); const auto maxcount_it = jsonFindRequired (data, "maxcount", "Particles must have maximum count");
auto emitter_it = jsonFindRequired (data, "emitter", "Particles must have emitters"); const auto emitter_it = jsonFindRequired (data, "emitter", "Particles must have emitters");
auto initializer_it = jsonFindRequired (data, "initializer", "Particles must have initializers"); const auto initializer_it = jsonFindRequired (data, "initializer", "Particles must have initializers");
auto* particle = new CParticle ( auto* particle = new CParticle (scene, *starttime_it, *maxcount_it, visible, id, std::move (name), origin, scale);
scene,
*starttime_it,
*maxcount_it,
visible,
id,
std::move(name),
origin,
scale
);
if (controlpoint_it != data.end ()) if (controlpoint_it != data.end ())
for (const auto& cur : (*controlpoint_it)) for (const auto& cur : (*controlpoint_it))
@ -39,54 +23,39 @@ CParticle* CParticle::fromFile (
for (const auto& cur : (*emitter_it)) for (const auto& cur : (*emitter_it))
particle->insertEmitter (Particles::CEmitter::fromJSON (cur)); particle->insertEmitter (Particles::CEmitter::fromJSON (cur));
for (const auto&cur : (*initializer_it)) for (const auto& cur : (*initializer_it))
particle->insertInitializer (Particles::CInitializer::fromJSON (cur)); particle->insertInitializer (Particles::CInitializer::fromJSON (cur));
return particle; return particle;
} }
CParticle::CParticle ( CParticle::CParticle (CScene* scene, uint32_t starttime, uint32_t maxcount, CUserSettingBoolean* visible, uint32_t id,
CScene* scene, std::string name, CUserSettingVector3* origin, CUserSettingVector3* scale) :
uint32_t starttime, CObject (scene, visible, id, std::move (name), Type, origin, scale, glm::vec3 ()),
uint32_t maxcount,
CUserSettingBoolean* visible,
uint32_t id,
std::string name,
CUserSettingVector3* origin,
CUserSettingVector3* scale):
CObject (scene, visible, id, std::move(name), Type, origin, scale, glm::vec3 ()),
m_starttime (starttime), m_starttime (starttime),
m_maxcount (maxcount) m_maxcount (maxcount) {}
{
}
const std::vector<Particles::CEmitter*>& CParticle::getEmitters () const const std::vector<Particles::CEmitter*>& CParticle::getEmitters () const {
{
return this->m_emitters; return this->m_emitters;
} }
const std::vector<Particles::CControlPoint*>& CParticle::getControlPoints () const const std::vector<Particles::CControlPoint*>& CParticle::getControlPoints () const {
{
return this->m_controlpoints; return this->m_controlpoints;
} }
const std::vector<Particles::CInitializer*>& CParticle::getInitializers () const const std::vector<Particles::CInitializer*>& CParticle::getInitializers () const {
{
return this->m_initializers; return this->m_initializers;
} }
void CParticle::insertControlPoint (Particles::CControlPoint* controlpoint) void CParticle::insertControlPoint (Particles::CControlPoint* controlpoint) {
{
this->m_controlpoints.push_back (controlpoint); this->m_controlpoints.push_back (controlpoint);
} }
void CParticle::insertEmitter (Particles::CEmitter* emitter) void CParticle::insertEmitter (Particles::CEmitter* emitter) {
{
this->m_emitters.push_back (emitter); this->m_emitters.push_back (emitter);
} }
void CParticle::insertInitializer (Particles::CInitializer* initializer) void CParticle::insertInitializer (Particles::CInitializer* initializer) {
{
this->m_initializers.push_back (initializer); this->m_initializers.push_back (initializer);
} }

View File

@ -4,85 +4,68 @@
#include "WallpaperEngine/Core/Objects/Particles/CEmitter.h" #include "WallpaperEngine/Core/Objects/Particles/CEmitter.h"
#include "WallpaperEngine/Core/Objects/Particles/CInitializer.h" #include "WallpaperEngine/Core/Objects/Particles/CInitializer.h"
#include "WallpaperEngine/Core/Core.h"
#include "WallpaperEngine/Core/CObject.h" #include "WallpaperEngine/Core/CObject.h"
#include "WallpaperEngine/Core/Core.h"
namespace WallpaperEngine::Core::Objects namespace WallpaperEngine::Core::Objects {
{ using json = nlohmann::json;
using json = nlohmann::json;
/**
* Represents a particle system in the background
*/
class CParticle : public CObject {
friend class CObject;
public:
static CParticle* fromFile (CScene* scene, const std::string& filename, CContainer* container,
CUserSettingBoolean* visible, uint32_t id, std::string name,
CUserSettingVector3* origin, CUserSettingVector3* scale);
/** /**
* Represents a particle system in the background * @return The list of emitters for the particle system
*/ */
class CParticle : public CObject [[nodiscard]] const std::vector<Particles::CEmitter*>& getEmitters () const;
{ /**
friend class CObject; * @return The list of control points for the particle system
*/
[[nodiscard]] const std::vector<Particles::CControlPoint*>& getControlPoints () const;
/**
* @return The list of initializers for the particle system
*/
[[nodiscard]] const std::vector<Particles::CInitializer*>& getInitializers () const;
public: protected:
static CParticle* fromFile ( CParticle (CScene* scene, uint32_t starttime, uint32_t maxcount, CUserSettingBoolean* visible, uint32_t id,
CScene* scene, std::string name, CUserSettingVector3* origin, CUserSettingVector3* scale);
const std::string& filename,
CContainer* container,
CUserSettingBoolean* visible,
uint32_t id,
std::string name,
CUserSettingVector3* origin,
CUserSettingVector3* scale
);
/** /**
* @return The list of emitters for the particle system * @param controlpoint The control point to add to the particle system
*/ */
[[nodiscard]] const std::vector<Particles::CEmitter*>& getEmitters () const; void insertControlPoint (Particles::CControlPoint* controlpoint);
/** /**
* @return The list of control points for the particle system * @param emitter The emitter to add to the particle system
*/ */
[[nodiscard]] const std::vector<Particles::CControlPoint*>& getControlPoints () const; void insertEmitter (Particles::CEmitter* emitter);
/** /**
* @return The list of initializers for the particle system * @param initializer The initializer to add to the particle system
*/ */
[[nodiscard]] const std::vector<Particles::CInitializer*>& getInitializers () const; void insertInitializer (Particles::CInitializer* initializer);
protected: /**
CParticle ( * Type value used to differentiate the different types of objects in a background
CScene* scene, */
uint32_t starttime, static const std::string Type;
uint32_t maxcount,
CUserSettingBoolean* visible,
uint32_t id,
std::string name,
CUserSettingVector3* origin,
CUserSettingVector3* scale
);
/** private:
* @param controlpoint The control point to add to the particle system /** The time at which the particle system should start emitting */
*/ uint32_t m_starttime;
void insertControlPoint (Particles::CControlPoint* controlpoint); /** Maximum number of particles at the same time */
/** uint32_t m_maxcount;
* @param emitter The emitter to add to the particle system /** List of control points */
*/ std::vector<Particles::CControlPoint*> m_controlpoints;
void insertEmitter (Particles::CEmitter* emitter); /** List of emitters */
/** std::vector<Particles::CEmitter*> m_emitters;
* @param initializer The initializer to add to the particle system /** List of initializers */
*/ std::vector<Particles::CInitializer*> m_initializers;
void insertInitializer (Particles::CInitializer* initializer); };
} // namespace WallpaperEngine::Core::Objects
/**
* Type value used to differentiate the different types of objects in a background
*/
static const std::string Type;
private:
/** The time at which the particle system should start emitting */
uint32_t m_starttime;
/** Maximum number of particles at the same time */
uint32_t m_maxcount;
/** List of control points */
std::vector<Particles::CControlPoint*> m_controlpoints;
/** List of emitters */
std::vector<Particles::CEmitter*> m_emitters;
/** List of initializers */
std::vector<Particles::CInitializer*> m_initializers;
};
}

View File

@ -1,55 +1,29 @@
#include "common.h"
#include "WallpaperEngine/Core/CObject.h"
#include "CSound.h" #include "CSound.h"
#include "WallpaperEngine/Core/CObject.h"
#include "common.h"
using namespace WallpaperEngine::Core::Objects; using namespace WallpaperEngine::Core::Objects;
CSound::CSound ( CSound::CSound (CScene* scene, CUserSettingBoolean* visible, uint32_t id, std::string name, CUserSettingVector3* origin,
CScene* scene, CUserSettingVector3* scale, const glm::vec3& angles, bool repeat) :
CUserSettingBoolean* visible, CObject (scene, visible, id, std::move (name), Type, origin, scale, angles),
uint32_t id, m_repeat (repeat) {}
std::string name,
CUserSettingVector3* origin,
CUserSettingVector3* scale,
const glm::vec3& angles,
bool repeat
) :
CObject (scene, visible, id, std::move(name), Type, origin, scale, angles),
m_repeat (repeat)
{
}
WallpaperEngine::Core::CObject* CSound::fromJSON ( WallpaperEngine::Core::CObject* CSound::fromJSON (CScene* scene, json data, CUserSettingBoolean* visible, uint32_t id,
CScene* scene, const std::string& name, CUserSettingVector3* origin,
json data, CUserSettingVector3* scale, const glm::vec3& angles) {
CUserSettingBoolean* visible,
uint32_t id,
const std::string& name,
CUserSettingVector3* origin,
CUserSettingVector3* scale,
const glm::vec3& angles)
{
bool repeat = false; bool repeat = false;
// TODO: PARSE AUDIO VOLUME // TODO: PARSE AUDIO VOLUME
auto sound_it = jsonFindRequired (data, "sound", "Sound information not present"); const auto sound_it = jsonFindRequired (data, "sound", "Sound information not present");
auto playbackmode = jsonFindDefault <std::string> (data, "playbackmode", ""); const auto playbackmode = jsonFindDefault<std::string> (data, "playbackmode", "");
if (playbackmode == "loop") if (playbackmode == "loop")
repeat = true; repeat = true;
if (!(*sound_it).is_array ()) if (!sound_it->is_array ())
sLog.exception ("Expected sound list on element ", name); sLog.exception ("Expected sound list on element ", name);
auto* sound = new CSound ( auto* sound = new CSound (scene, visible, id, name, origin, scale, angles, repeat);
scene,
visible,
id,
name,
origin,
scale,
angles,
repeat
);
for (const auto& cur : (*sound_it)) for (const auto& cur : (*sound_it))
sound->insertSound (cur); sound->insertSound (cur);
@ -57,17 +31,15 @@ WallpaperEngine::Core::CObject* CSound::fromJSON (
return sound; return sound;
} }
void CSound::insertSound (const std::string& filename) void CSound::insertSound (const std::string& filename) {
{
this->m_sounds.push_back (filename); this->m_sounds.push_back (filename);
} }
const std::vector<std::string>& CSound::getSounds () const const std::vector<std::string>& CSound::getSounds () const {
{
return this->m_sounds; return this->m_sounds;
} }
bool CSound::isRepeat () const
{ bool CSound::isRepeat () const {
return this->m_repeat; return this->m_repeat;
} }

View File

@ -1,68 +1,51 @@
#pragma once #pragma once
#include "WallpaperEngine/Core/Core.h"
#include "WallpaperEngine/Core/CObject.h" #include "WallpaperEngine/Core/CObject.h"
#include "WallpaperEngine/Core/Core.h"
#include "WallpaperEngine/Core/UserSettings/CUserSettingBoolean.h" #include "WallpaperEngine/Core/UserSettings/CUserSettingBoolean.h"
namespace WallpaperEngine::Core::Objects namespace WallpaperEngine::Core::Objects {
{ using json = nlohmann::json;
using json = nlohmann::json; using namespace WallpaperEngine::Core::UserSettings;
using namespace WallpaperEngine::Core::UserSettings;
/**
* Represents a sound played while the background is working
*/
class CSound : public CObject {
friend class CObject;
public:
static CObject* fromJSON (CScene* scene, json data, CUserSettingBoolean* visible, uint32_t id,
const std::string& name, CUserSettingVector3* origin, CUserSettingVector3* scale,
const glm::vec3& angles);
/** /**
* Represents a sound played while the background is working * @return The list of sounds to play
*/ */
class CSound : public CObject [[nodiscard]] const std::vector<std::string>& getSounds () const;
{ /**
friend class CObject; * @return If the sound should repeat or not
*/
[[nodiscard]] bool isRepeat () const;
public: protected:
static CObject* fromJSON ( CSound (CScene* scene, CUserSettingBoolean* visible, uint32_t id, std::string name, CUserSettingVector3* origin,
CScene* scene, CUserSettingVector3* scale, const glm::vec3& angles, bool repeat);
json data,
CUserSettingBoolean* visible,
uint32_t id,
const std::string& name,
CUserSettingVector3* origin,
CUserSettingVector3* scale,
const glm::vec3& angles
);
/** /**
* @return The list of sounds to play * @param filename The sound to add
*/ */
[[nodiscard]] const std::vector<std::string>& getSounds () const; void insertSound (const std::string& filename);
/**
* @return If the sound should repeat or not
*/
[[nodiscard]] bool isRepeat () const;
protected: /**
CSound ( * Type value used to differentiate the different types of objects in a background
CScene* scene, */
CUserSettingBoolean* visible, static const std::string Type;
uint32_t id,
std::string name,
CUserSettingVector3* origin,
CUserSettingVector3* scale,
const glm::vec3& angles,
bool repeat
);
/** private:
* @param filename The sound to add /** If the sounds should repeat or not */
*/ bool m_repeat;
void insertSound (const std::string& filename); /** The list of sounds to play */
std::vector<std::string> m_sounds;
/** };
* Type value used to differentiate the different types of objects in a background } // namespace WallpaperEngine::Core::Objects
*/
static const std::string Type;
private:
/** If the sounds should repeat or not */
bool m_repeat;
/** The list of sounds to play */
std::vector<std::string> m_sounds;
};
}

View File

@ -4,26 +4,19 @@
using namespace WallpaperEngine::Core::Objects::Effects; using namespace WallpaperEngine::Core::Objects::Effects;
CBind::CBind (std::string name, uint32_t index) : CBind::CBind (std::string name, uint32_t index) : m_name (std::move (name)), m_index (index) {}
m_name (std::move(name)),
m_index (index)
{
}
CBind* CBind::fromJSON (json data) CBind* CBind::fromJSON (json data) {
{ const auto name_it = jsonFindRequired (data, "name", "bind must have texture name");
auto name_it = jsonFindRequired (data, "name", "bind must have texture name"); const auto index_it = jsonFindRequired (data, "index", "bind must have index");
auto index_it = jsonFindRequired (data, "index", "bind must have index");
return new CBind (*name_it, *index_it); return new CBind (*name_it, *index_it);
} }
const std::string& CBind::getName () const const std::string& CBind::getName () const {
{
return this->m_name; return this->m_name;
} }
const uint32_t& CBind::getIndex () const const uint32_t& CBind::getIndex () const {
{
return this->m_index; return this->m_index;
} }

View File

@ -4,41 +4,39 @@
#include "WallpaperEngine/Core/Core.h" #include "WallpaperEngine/Core/Core.h"
namespace WallpaperEngine::Core::Objects::Effects namespace WallpaperEngine::Core::Objects::Effects {
{ using json = nlohmann::json;
using json = nlohmann::json;
/**
* Material's bind information, describes for passes what textures to bind
* in what positions for shaders. Used to override the textures specified inside
* the object's passes
*/
class CBind {
public:
/**
* Parses bind information off the given json data
*
* @param data
* @return
*/
static CBind* fromJSON (json data);
CBind (std::string name, uint32_t index);
/** /**
* Material's bind information, describes for passes what textures to bind * @return The texture name, previous to use the one already specified by the object's passes
* in what positions for shaders. Used to override the textures specified inside
* the object's passes
*/ */
class CBind [[nodiscard]] const std::string& getName () const;
{ /**
public: * @return The texture index to replace
/** */
* Parses bind information off the given json data [[nodiscard]] const uint32_t& getIndex () const;
*
* @param data
* @return
*/
static CBind* fromJSON (json data);
CBind (std::string name, uint32_t index); private:
/** The texture's name */
/** std::string m_name;
* @return The texture name, previous to use the one already specified by the object's passes /** The texture index to replace */
*/ uint32_t m_index;
[[nodiscard]] const std::string& getName () const; };
/** } // namespace WallpaperEngine::Core::Objects::Effects
* @return The texture index to replace
*/
[[nodiscard]] const uint32_t& getIndex () const;
private:
/** The texture's name */
std::string m_name;
/** The texture index to replace */
uint32_t m_index;
};
}

View File

@ -6,36 +6,26 @@ using namespace WallpaperEngine::Core;
using namespace WallpaperEngine::Core::Objects::Effects; using namespace WallpaperEngine::Core::Objects::Effects;
CFBO::CFBO (std::string name, float scale, std::string format) : CFBO::CFBO (std::string name, float scale, std::string format) :
m_name (std::move(name)), m_name (std::move (name)),
m_scale (scale), m_scale (scale),
m_format(std::move(format)) m_format (std::move (format)) {}
{
CFBO* CFBO::fromJSON (json data) {
const auto name_it = jsonFindRequired (data, "name", "Name for an FBO is required");
const auto scale = jsonFindDefault<float> (data, "scale", 1.0);
const auto format = jsonFindDefault<std::string> (data, "format", "");
return new CFBO (*name_it, scale, format);
} }
CFBO* CFBO::fromJSON (json data) const std::string& CFBO::getName () const {
{
auto name_it = jsonFindRequired (data, "name", "Name for an FBO is required");
auto scale = jsonFindDefault <float> (data, "scale", 1.0);
auto format = jsonFindDefault <std::string> (data, "format", "");
return new CFBO (
*name_it,
scale,
format
);
}
const std::string& CFBO::getName () const
{
return this->m_name; return this->m_name;
} }
const float& CFBO::getScale () const const float& CFBO::getScale () const {
{
return this->m_scale; return this->m_scale;
} }
const std::string& CFBO::getFormat () const const std::string& CFBO::getFormat () const {
{
return this->m_format; return this->m_format;
} }

View File

@ -5,41 +5,39 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <string> #include <string>
namespace WallpaperEngine::Core::Objects::Effects namespace WallpaperEngine::Core::Objects::Effects {
{ using json = nlohmann::json;
using json = nlohmann::json;
/**
* FBO = Frame Buffer Object
*
* Represents a framebuffer object used in objects with multiple effects or render passes
*/
class CFBO {
public:
CFBO (std::string name, float scale, std::string format);
static CFBO* fromJSON (json data);
/** /**
* FBO = Frame Buffer Object * @return The FBO name used to identify it in the background's files
*
* Represents a framebuffer object used in objects with multiple effects or render passes
*/ */
class CFBO [[nodiscard]] const std::string& getName () const;
{ /**
public: * @return The scale factor of the FBO
CFBO (std::string name, float scale, std::string format); */
[[nodiscard]] const float& getScale () const;
/**
* @return The FBO's format for the render
*/
[[nodiscard]] const std::string& getFormat () const;
static CFBO* fromJSON (json data); private:
/** The name of the FBO */
/** std::string m_name;
* @return The FBO name used to identify it in the background's files /** The scale factor of the FBO */
*/ float m_scale;
[[nodiscard]] const std::string& getName () const; /** The FBO's format for the render */
/** std::string m_format;
* @return The scale factor of the FBO };
*/ } // namespace WallpaperEngine::Core::Objects::Effects
[[nodiscard]] const float& getScale () const;
/**
* @return The FBO's format for the render
*/
[[nodiscard]] const std::string& getFormat () const;
private:
/** The name of the FBO */
std::string m_name;
/** The scale factor of the FBO */
float m_scale;
/** The FBO's format for the render */
std::string m_format;
};
}

View File

@ -2,12 +2,8 @@
using namespace WallpaperEngine::Core::Objects::Effects::Constants; using namespace WallpaperEngine::Core::Objects::Effects::Constants;
CShaderConstant::CShaderConstant (std::string type) : CShaderConstant::CShaderConstant (std::string type) : m_type (std::move (type)) {}
m_type (std::move(type))
{
}
const std::string& CShaderConstant::getType () const const std::string& CShaderConstant::getType () const {
{
return this->m_type; return this->m_type;
} }

View File

@ -2,27 +2,34 @@
#include <string> #include <string>
namespace WallpaperEngine::Core::Objects::Effects::Constants namespace WallpaperEngine::Core::Objects::Effects::Constants {
{ /**
* Shader constants base class
*/
class CShaderConstant {
public:
explicit CShaderConstant (std::string type);
template <class T> const T* as () const {
assert (is<T> ());
return reinterpret_cast<const T*> (this);
}
template <class T> T* as () {
assert (is<T> ());
return reinterpret_cast<T*> (this);
}
template <class T> bool is () {
return this->m_type == T::Type;
}
/** /**
* Shader constants base class * @return The type name of this constant
*/ */
class CShaderConstant [[nodiscard]] const std::string& getType () const;
{
public:
explicit CShaderConstant (std::string type);
template<class T> const T* as () const { assert (is <T> ()); return (const T*) this; } private:
template<class T> T* as () { assert (is <T> ()); return (T*) this; } std::string m_type;
};
template<class T> bool is () { return this->m_type == T::Type; } } // namespace WallpaperEngine::Core::Objects::Effects::Constants
/**
* @return The type name of this constant
*/
[[nodiscard]] const std::string& getType () const;
private:
std::string m_type;
};
}

View File

@ -2,14 +2,9 @@
using namespace WallpaperEngine::Core::Objects::Effects::Constants; using namespace WallpaperEngine::Core::Objects::Effects::Constants;
CShaderConstantFloat::CShaderConstantFloat (float value) : CShaderConstantFloat::CShaderConstantFloat (float value) : CShaderConstant (Type), m_value (value) {}
CShaderConstant (Type),
m_value (value)
{
}
float* CShaderConstantFloat::getValue () float* CShaderConstantFloat::getValue () {
{
return &this->m_value; return &this->m_value;
} }

View File

@ -4,27 +4,26 @@
#include <string> #include <string>
namespace WallpaperEngine::Core::Objects::Effects::Constants namespace WallpaperEngine::Core::Objects::Effects::Constants {
{ /**
* Shader constant of type float
*/
class CShaderConstantFloat : public CShaderConstant {
public:
explicit CShaderConstantFloat (float value);
/** /**
* Shader constant of type float * @return A pointer to the actual value of the constant
*/ */
class CShaderConstantFloat : public CShaderConstant float* getValue ();
{
public:
explicit CShaderConstantFloat (float value);
/** /**
* @return A pointer to the actual value of the constant * Type string indicator
*/ */
float* getValue (); static const std::string Type;
/** protected:
* Type string indicator /** The constant's value */
*/ float m_value;
static const std::string Type; };
protected: } // namespace WallpaperEngine::Core::Objects::Effects::Constants
/** The constant's value */
float m_value;
};
}

View File

@ -2,14 +2,9 @@
using namespace WallpaperEngine::Core::Objects::Effects::Constants; using namespace WallpaperEngine::Core::Objects::Effects::Constants;
CShaderConstantInteger::CShaderConstantInteger (int32_t value) : CShaderConstantInteger::CShaderConstantInteger (int32_t value) : CShaderConstant (Type), m_value (value) {}
CShaderConstant (Type),
m_value (value)
{
}
int32_t* CShaderConstantInteger::getValue () int32_t* CShaderConstantInteger::getValue () {
{
return &this->m_value; return &this->m_value;
} }

View File

@ -4,27 +4,26 @@
#include <string> #include <string>
namespace WallpaperEngine::Core::Objects::Effects::Constants namespace WallpaperEngine::Core::Objects::Effects::Constants {
{ /**
* Shader constant of type integer
*/
class CShaderConstantInteger : public CShaderConstant {
public:
explicit CShaderConstantInteger (int32_t value);
/** /**
* Shader constant of type integer * @return A pointer to the actual value of the constant
*/ */
class CShaderConstantInteger : public CShaderConstant int32_t* getValue ();
{
public:
explicit CShaderConstantInteger (int32_t value);
/** /**
* @return A pointer to the actual value of the constant * Type string indicator
*/ */
int32_t* getValue (); static const std::string Type;
/** protected:
* Type string indicator /** The constant's value */
*/ int32_t m_value;
static const std::string Type; };
protected: } // namespace WallpaperEngine::Core::Objects::Effects::Constants
/** The constant's value */
int32_t m_value;
};
}

View File

@ -2,15 +2,9 @@
using namespace WallpaperEngine::Core::Objects::Effects::Constants; using namespace WallpaperEngine::Core::Objects::Effects::Constants;
CShaderConstantVector2::CShaderConstantVector2 (glm::vec2 value) : CShaderConstant (Type), m_value (value) {}
CShaderConstantVector2::CShaderConstantVector2 (glm::vec2 value) : glm::vec2* CShaderConstantVector2::getValue () {
CShaderConstant (Type),
m_value (value)
{
}
glm::vec2* CShaderConstantVector2::getValue ()
{
return &this->m_value; return &this->m_value;
} }

View File

@ -2,31 +2,30 @@
#include "CShaderConstant.h" #include "CShaderConstant.h"
#include <string>
#include <glm/vec2.hpp> #include <glm/vec2.hpp>
#include <glm/vec3.hpp> #include <glm/vec3.hpp>
#include <string>
namespace WallpaperEngine::Core::Objects::Effects::Constants {
/**
* Shader constant of vector2 type
*/
class CShaderConstantVector2 : public CShaderConstant {
public:
explicit CShaderConstantVector2 (glm::vec2 value);
namespace WallpaperEngine::Core::Objects::Effects::Constants
{
/** /**
* Shader constant of vector2 type * @return A pointer to the actual value of the constant
*/ */
class CShaderConstantVector2 : public CShaderConstant glm::vec2* getValue ();
{
public:
explicit CShaderConstantVector2 (glm::vec2 value);
/** /**
* @return A pointer to the actual value of the constant * Type string indicator
*/ */
glm::vec2* getValue (); static const std::string Type;
/** protected:
* Type string indicator /** The constant's value */
*/ glm::vec2 m_value;
static const std::string Type; };
protected: } // namespace WallpaperEngine::Core::Objects::Effects::Constants
/** The constant's value */
glm::vec2 m_value;
};
}

View File

@ -2,14 +2,9 @@
using namespace WallpaperEngine::Core::Objects::Effects::Constants; using namespace WallpaperEngine::Core::Objects::Effects::Constants;
CShaderConstantVector3::CShaderConstantVector3 (glm::vec3 value) : CShaderConstantVector3::CShaderConstantVector3 (glm::vec3 value) : CShaderConstant (Type), m_value (value) {}
CShaderConstant (Type),
m_value (value)
{
}
glm::vec3* CShaderConstantVector3::getValue () glm::vec3* CShaderConstantVector3::getValue () {
{
return &this->m_value; return &this->m_value;
} }

View File

@ -2,30 +2,29 @@
#include "CShaderConstant.h" #include "CShaderConstant.h"
#include <string>
#include <glm/vec3.hpp> #include <glm/vec3.hpp>
#include <string>
namespace WallpaperEngine::Core::Objects::Effects::Constants {
/**
* Shader constant of vector3 type
*/
class CShaderConstantVector3 : public CShaderConstant {
public:
explicit CShaderConstantVector3 (glm::vec3 value);
namespace WallpaperEngine::Core::Objects::Effects::Constants
{
/** /**
* Shader constant of vector3 type * @return A pointer to the actual value of the constant
*/ */
class CShaderConstantVector3 : public CShaderConstant glm::vec3* getValue ();
{
public:
explicit CShaderConstantVector3 (glm::vec3 value);
/** /**
* @return A pointer to the actual value of the constant * Type string indicator
*/ */
glm::vec3* getValue (); static const std::string Type;
/** protected:
* Type string indicator /** The constant's value */
*/ glm::vec3 m_value;
static const std::string Type; };
protected: } // namespace WallpaperEngine::Core::Objects::Effects::Constants
/** The constant's value */
glm::vec3 m_value;
};
}

View File

@ -2,15 +2,9 @@
using namespace WallpaperEngine::Core::Objects::Effects::Constants; using namespace WallpaperEngine::Core::Objects::Effects::Constants;
CShaderConstantVector4::CShaderConstantVector4 (glm::vec4 value) : CShaderConstant (Type), m_value (value) {}
CShaderConstantVector4::CShaderConstantVector4 (glm::vec4 value) : glm::vec4* CShaderConstantVector4::getValue () {
CShaderConstant (Type),
m_value (value)
{
}
glm::vec4* CShaderConstantVector4::getValue ()
{
return &this->m_value; return &this->m_value;
} }

View File

@ -2,30 +2,29 @@
#include "CShaderConstant.h" #include "CShaderConstant.h"
#include <string>
#include <glm/vec4.hpp> #include <glm/vec4.hpp>
#include <string>
namespace WallpaperEngine::Core::Objects::Effects::Constants {
/**
* Shader constant of vector4 type
*/
class CShaderConstantVector4 : public CShaderConstant {
public:
explicit CShaderConstantVector4 (glm::vec4 value);
namespace WallpaperEngine::Core::Objects::Effects::Constants
{
/** /**
* Shader constant of vector4 type * @return A pointer to the actual value of the constant
*/ */
class CShaderConstantVector4 : public CShaderConstant glm::vec4* getValue ();
{
public:
explicit CShaderConstantVector4 (glm::vec4 value);
/** /**
* @return A pointer to the actual value of the constant * Type string indicator
*/ */
glm::vec4* getValue (); static const std::string Type;
/** protected:
* Type string indicator /** The constant's value */
*/ glm::vec4 m_value;
static const std::string Type; };
protected: } // namespace WallpaperEngine::Core::Objects::Effects::Constants
/** The constant's value */
glm::vec4 m_value;
};
}

View File

@ -10,37 +10,26 @@ using namespace WallpaperEngine::Assets;
using namespace WallpaperEngine::Core::Objects; using namespace WallpaperEngine::Core::Objects;
using namespace WallpaperEngine::Core::Objects::Images; using namespace WallpaperEngine::Core::Objects::Images;
CMaterial::CMaterial (std::string name) : CMaterial::CMaterial (std::string name) : m_name (std::move (name)) {}
m_target (),
m_name (std::move(name)) CMaterial* CMaterial::fromFile (const std::string& filename, CContainer* container) {
{ return fromJSON (filename, json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container)));
} }
CMaterial* CMaterial::fromFile (const std::string& filename, CContainer* container) CMaterial* CMaterial::fromFile (const std::string& filename, const std::string& target, CContainer* container) {
{ return fromJSON (filename, json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container)), target);
return fromJSON (
filename, json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container))
);
}
CMaterial* CMaterial::fromFile (const std::string& filename, const std::string& target, CContainer* container)
{
return fromJSON (
filename, json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container)), target
);
} }
CMaterial* CMaterial::fromJSON (const std::string& name, json data, const std::string& target) CMaterial* CMaterial::fromJSON (const std::string& name, json data, const std::string& target) {
{ CMaterial* material = fromJSON (name, std::move (data));
CMaterial* material = fromJSON (name, std::move(data));
material->setTarget (target); material->setTarget (target);
return material; return material;
} }
CMaterial* CMaterial::fromJSON (const std::string& name, json data) CMaterial* CMaterial::fromJSON (const std::string& name, json data) {
{ const auto passes_it = jsonFindRequired (data, "passes", "Material must have at least one pass");
auto passes_it = jsonFindRequired (data, "passes", "Material must have at least one pass");
auto* material = new CMaterial (name); auto* material = new CMaterial (name);
@ -50,41 +39,34 @@ CMaterial* CMaterial::fromJSON (const std::string& name, json data)
return material; return material;
} }
void CMaterial::insertPass (Materials::CPass* mass) void CMaterial::insertPass (Materials::CPass* pass) {
{ this->m_passes.push_back (pass);
this->m_passes.push_back (mass);
} }
void CMaterial::insertTextureBind (Effects::CBind* bind) void CMaterial::insertTextureBind (Effects::CBind* bind) {
{
this->m_textureBindings.insert (std::make_pair (bind->getIndex (), bind)); this->m_textureBindings.insert (std::make_pair (bind->getIndex (), bind));
} }
void CMaterial::setTarget (const std::string& target) void CMaterial::setTarget (const std::string& target) {
{
this->m_target = target; this->m_target = target;
} }
const std::vector <Materials::CPass*>& CMaterial::getPasses () const const std::vector<Materials::CPass*>& CMaterial::getPasses () const {
{
return this->m_passes; return this->m_passes;
} }
const std::map <int, Effects::CBind*>& CMaterial::getTextureBinds () const
{ const std::map<int, Effects::CBind*>& CMaterial::getTextureBinds () const {
return this->m_textureBindings; return this->m_textureBindings;
} }
const std::string& CMaterial::getTarget () const const std::string& CMaterial::getTarget () const {
{
return this->m_target; return this->m_target;
} }
const std::string& CMaterial::getName () const const std::string& CMaterial::getName () const {
{
return this->m_name; return this->m_name;
} }
bool CMaterial::hasTarget () const bool CMaterial::hasTarget () const {
{
return !this->m_target.empty (); return !this->m_target.empty ();
} }

View File

@ -1,74 +1,72 @@
#pragma once #pragma once
#include "WallpaperEngine/Core/Objects/Images/Materials/CPass.h"
#include "WallpaperEngine/Core/Objects/Effects/CBind.h" #include "WallpaperEngine/Core/Objects/Effects/CBind.h"
#include "WallpaperEngine/Core/Objects/Images/Materials/CPass.h"
#include "WallpaperEngine/Core/Core.h"
#include "WallpaperEngine/Assets/CContainer.h" #include "WallpaperEngine/Assets/CContainer.h"
#include "WallpaperEngine/Core/Core.h"
namespace WallpaperEngine::Core::Objects::Images namespace WallpaperEngine::Core::Objects::Images {
{ using json = nlohmann::json;
using json = nlohmann::json; using namespace WallpaperEngine::Assets;
using namespace WallpaperEngine::Assets;
/**
* Represents a material in use in the background
*/
class CMaterial {
public:
static CMaterial* fromFile (const std::string& filename, Assets::CContainer* container);
static CMaterial* fromJSON (const std::string& name, json data);
static CMaterial* fromFile (const std::string& filename, const std::string& target, Assets::CContainer* container);
static CMaterial* fromJSON (const std::string& name, json data, const std::string& target);
/** /**
* Represents a material in use in the background * @param pass The rendering pass to add to the material
*/ */
class CMaterial void insertPass (Materials::CPass* pass);
{ /**
public: * @param bind Texture bind override for the material
static CMaterial* fromFile (const std::string& filename, Assets::CContainer* container); */
static CMaterial* fromJSON (const std::string& name, json data); void insertTextureBind (Effects::CBind* bind);
static CMaterial* fromFile (const std::string& filename, const std::string& target, Assets::CContainer* container);
static CMaterial* fromJSON (const std::string& name, json data, const std::string& target);
/** /**
* @param pass The rendering pass to add to the material * @return All the rendering passes that happen for this material
*/ */
void insertPass (Materials::CPass* pass); [[nodiscard]] const std::vector<Materials::CPass*>& getPasses () const;
/** /**
* @param bind Texture bind override for the material * @return The textures that have to be bound while rendering the material.
*/ * These act as an override of the textures specified by the parent effect
void insertTextureBind (Effects::CBind* bind); */
[[nodiscard]] const std::map<int, Effects::CBind*>& getTextureBinds () const;
/**
* @return The materials destination (fbo) if required
*/
[[nodiscard]] const std::string& getTarget () const;
/**
* @return Indicates if this material has a specific destination (fbo) while rendering
*/
[[nodiscard]] bool hasTarget () const;
/**
* @return The name of the material
*/
[[nodiscard]] const std::string& getName () const;
/** protected:
* @return All the rendering passes that happen for this material explicit CMaterial (std::string name);
*/
[[nodiscard]] const std::vector <Materials::CPass*>& getPasses () const;
/**
* @return The textures that have to be bound while rendering the material.
* These act as an override of the textures specified by the parent effect
*/
[[nodiscard]] const std::map <int, Effects::CBind*>& getTextureBinds () const;
/**
* @return The materials destination (fbo) if required
*/
[[nodiscard]] const std::string& getTarget () const;
/**
* @return Indicates if this material has a specific destination (fbo) while rendering
*/
[[nodiscard]] bool hasTarget () const;
/**
* @return The name of the material
*/
[[nodiscard]] const std::string& getName () const;
protected: /**
explicit CMaterial (std::string name); * @param target The new target while rendering this material
*/
void setTarget (const std::string& target);
/** private:
* @param target The new target while rendering this material /** All the shader passes required to render this material */
*/ std::vector<Materials::CPass*> m_passes;
void setTarget (const std::string& target); /** List of texture bind overrides to use for this material */
std::map<int, Effects::CBind*> m_textureBindings;
private: /** The FBO target to render to (if any) */
/** All the shader passes required to render this material */ std::string m_target;
std::vector <Materials::CPass*> m_passes; /** The material's name */
/** List of texture bind overrides to use for this material */ std::string m_name;
std::map <int, Effects::CBind*> m_textureBindings; };
/** The FBO target to render to (if any) */ } // namespace WallpaperEngine::Core::Objects::Images
std::string m_target;
/** The material's name */
std::string m_name;
};
}

View File

@ -1,54 +1,43 @@
#include "common.h"
#include "CPass.h" #include "CPass.h"
#include "common.h"
#include <utility> #include <utility>
using namespace WallpaperEngine::Core::Objects::Effects::Constants; using namespace WallpaperEngine::Core::Objects::Effects::Constants;
using namespace WallpaperEngine::Core::Objects::Images::Materials; using namespace WallpaperEngine::Core::Objects::Images::Materials;
CPass::CPass (std::string blending, std::string cullmode, std::string depthtest, std::string depthwrite, std::string shader) : CPass::CPass (std::string blending, std::string cullmode, std::string depthtest, std::string depthwrite,
m_blending (std::move(blending)), std::string shader) :
m_cullmode (std::move(cullmode)), m_blending (std::move (blending)),
m_depthtest (std::move(depthtest)), m_cullmode (std::move (cullmode)),
m_depthwrite (std::move(depthwrite)), m_depthtest (std::move (depthtest)),
m_shader (std::move(shader)) m_depthwrite (std::move (depthwrite)),
{ m_shader (std::move (shader)) {}
}
CPass* CPass::fromJSON (json data) CPass* CPass::fromJSON (json data) {
{
// TODO: FIGURE OUT DEFAULT BLENDING MODE // TODO: FIGURE OUT DEFAULT BLENDING MODE
auto blending = jsonFindDefault <std::string> (data, "blending", "normal"); const auto blending = jsonFindDefault<std::string> (data, "blending", "normal");
auto cullmode = jsonFindDefault <std::string> (data, "cullmode", "nocull"); const auto cullmode = jsonFindDefault<std::string> (data, "cullmode", "nocull");
auto depthtest_it = jsonFindRequired (data, "depthtest", "Material pass must have depthtest specified"); const auto depthtest_it = jsonFindRequired (data, "depthtest", "Material pass must have depthtest specified");
auto depthwrite_it = jsonFindRequired (data, "depthwrite", "Material pass must have depthwrite specified"); const auto depthwrite_it = jsonFindRequired (data, "depthwrite", "Material pass must have depthwrite specified");
auto shader_it = jsonFindRequired (data, "shader", "Material pass must have shader specified"); const auto shader_it = jsonFindRequired (data, "shader", "Material pass must have shader specified");
auto textures_it = data.find ("textures"); const auto textures_it = data.find ("textures");
auto combos_it = data.find ("combos"); const auto combos_it = data.find ("combos");
if (textures_it != data.end ()) if (textures_it != data.end ()) {
{
// TODO: FETCH THIS FROM CImage TO MAKE IT COMPATIBLE WITH OLDER WALLPAPERS // TODO: FETCH THIS FROM CImage TO MAKE IT COMPATIBLE WITH OLDER WALLPAPERS
if (!(*textures_it).is_array ()) if (!textures_it->is_array ())
sLog.exception ("Material's textures must be a list"); sLog.exception ("Material's textures must be a list");
} }
auto* pass = new CPass ( auto* pass = new CPass (blending, cullmode, *depthtest_it, *depthwrite_it, *shader_it);
blending,
cullmode,
*depthtest_it,
*depthwrite_it,
*shader_it
);
if (textures_it != data.end ()) if (textures_it != data.end ())
for (const auto& cur : (*textures_it)) for (const auto& cur : (*textures_it))
pass->insertTexture (cur.is_null () ? "" : cur); pass->insertTexture (cur.is_null () ? "" : cur);
if (combos_it != data.end ()) if (combos_it != data.end ()) {
{ for (const auto& cur : combos_it->items ()) {
for (const auto& cur : (*combos_it).items ())
{
if (cur.value ().is_number_integer ()) if (cur.value ().is_number_integer ())
pass->insertCombo (cur.key (), cur.value ()); pass->insertCombo (cur.key (), cur.value ());
else else
@ -59,70 +48,57 @@ CPass* CPass::fromJSON (json data)
return pass; return pass;
} }
void CPass::insertTexture (const std::string& texture) void CPass::insertTexture (const std::string& texture) {
{
this->m_textures.push_back (texture); this->m_textures.push_back (texture);
} }
void CPass::setTexture (int index, const std::string& texture) void CPass::setTexture (int index, const std::string& texture) {
{
this->m_textures.at (index) = texture; this->m_textures.at (index) = texture;
} }
void CPass::insertCombo (const std::string& name, int value) void CPass::insertCombo (const std::string& name, int value) {
{
std::string uppercase = std::string (name); std::string uppercase = std::string (name);
std::transform (uppercase.begin (), uppercase.end (), uppercase.begin (), ::toupper); std::transform (uppercase.begin (), uppercase.end (), uppercase.begin (), ::toupper);
this->m_combos.insert (std::pair <std::string, int> (uppercase, value)); this->m_combos.insert (std::pair (uppercase, value));
} }
const std::vector<std::string>& CPass::getTextures () const const std::vector<std::string>& CPass::getTextures () const {
{
return this->m_textures; return this->m_textures;
} }
const std::map<std::string, CShaderConstant*>& CPass::getConstants () const const std::map<std::string, CShaderConstant*>& CPass::getConstants () const {
{
return this->m_constants; return this->m_constants;
} }
std::map<std::string, int>* CPass::getCombos () std::map<std::string, int>* CPass::getCombos () {
{
return &this->m_combos; return &this->m_combos;
} }
const std::string& CPass::getShader () const const std::string& CPass::getShader () const {
{
return this->m_shader; return this->m_shader;
} }
const std::string& CPass::getBlendingMode () const const std::string& CPass::getBlendingMode () const {
{
return this->m_blending; return this->m_blending;
} }
const std::string& CPass::getCullingMode () const const std::string& CPass::getCullingMode () const {
{
return this->m_cullmode; return this->m_cullmode;
} }
const std::string& CPass::getDepthTest () const const std::string& CPass::getDepthTest () const {
{
return this->m_depthtest; return this->m_depthtest;
} }
const std::string& CPass::getDepthWrite ()const const std::string& CPass::getDepthWrite () const {
{
return this->m_depthwrite; return this->m_depthwrite;
} }
void CPass::setBlendingMode (const std::string& mode) void CPass::setBlendingMode (const std::string& mode) {
{
this->m_blending = mode; this->m_blending = mode;
} }
void CPass::insertConstant (const std::string& name, CShaderConstant* constant) void CPass::insertConstant (const std::string& name, CShaderConstant* constant) {
{ this->m_constants.insert (std::pair (name, constant));
this->m_constants.insert (std::pair <std::string, CShaderConstant*> (name, constant));
} }

View File

@ -4,110 +4,109 @@
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.h" #include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.h"
namespace WallpaperEngine::Core::Objects namespace WallpaperEngine::Core::Objects {
{ class CEffect;
class CEffect;
} }
namespace WallpaperEngine::Core::Objects::Images::Materials namespace WallpaperEngine::Core::Objects::Images::Materials {
{ using json = nlohmann::json;
using json = nlohmann::json;
/**
* Represents a shader pass of an object
*/
class CPass {
friend class WallpaperEngine::Core::Objects::CEffect;
public:
static CPass* fromJSON (json data);
/** /**
* Represents a shader pass of an object * @return The list of textures to bind while rendering
*/ */
class CPass [[nodiscard]] const std::vector<std::string>& getTextures () const;
{ /**
friend class WallpaperEngine::Core::Objects::CEffect; * @return Shader constants that alter how the shader should behave
public: */
static CPass* fromJSON (json data); [[nodiscard]] const std::map<std::string, Effects::Constants::CShaderConstant*>& getConstants () const;
/**
* @return Shader combos that alter how the shader should behave
*/
[[nodiscard]] std::map<std::string, int>* getCombos ();
/**
* @return Shader to be used while rendering the pass
*/
[[nodiscard]] const std::string& getShader () const;
/**
* @return The blending mode to use while rendering
*/
[[nodiscard]] const std::string& getBlendingMode () const;
/**
* @return The culling mode to use while rendering
*/
[[nodiscard]] const std::string& getCullingMode () const;
/**
* @return If depth testing has to happen while rendering
*/
[[nodiscard]] const std::string& getDepthTest () const;
/**
* @return If depth write has to happen while rendering
*/
[[nodiscard]] const std::string& getDepthWrite () const;
/**
* @param mode The new blending mode to use
*/
void setBlendingMode (const std::string& mode);
/** /**
* @return The list of textures to bind while rendering * Add a shader combo value to the list
*/ *
[[nodiscard]] const std::vector<std::string>& getTextures () const; * @param name The combo name
/** * @param value It's value
* @return Shader constants that alter how the shader should behave */
*/ void insertCombo (const std::string& name, int value);
[[nodiscard]] const std::map<std::string, Effects::Constants::CShaderConstant*>& getConstants () const; /**
/** * Adds a shader constant to the list
* @return Shader combos that alter how the shader should behave *
*/ * @param name The constant's name
[[nodiscard]] std::map<std::string, int>* getCombos (); * @param constant It's value
/** */
* @return Shader to be used while rendering the pass void insertConstant (const std::string& name, Effects::Constants::CShaderConstant* constant);
*/
[[nodiscard]] const std::string& getShader () const;
/**
* @return The blending mode to use while rendering
*/
[[nodiscard]] const std::string& getBlendingMode () const;
/**
* @return The culling mode to use while rendering
*/
[[nodiscard]] const std::string& getCullingMode () const;
/**
* @return If depth testing has to happen while rendering
*/
[[nodiscard]] const std::string& getDepthTest () const;
/**
* @return If depth write has to happen while rendering
*/
[[nodiscard]] const std::string& getDepthWrite () const;
/**
* @param mode The new blending mode to use
*/
void setBlendingMode (const std::string& mode);
/** protected:
* Add a shader combo value to the list CPass (std::string blending, std::string cullmode, std::string depthtest, std::string depthwrite,
* std::string shader);
* @param name The combo name
* @param value It's value
*/
void insertCombo (const std::string& name, int value);
/**
* Adds a shader constant to the list
*
* @param name The constant's name
* @param constant It's value
*/
void insertConstant (const std::string& name, Effects::Constants::CShaderConstant* constant);
protected: /**
CPass (std::string blending, std::string cullmode, std::string depthtest, std::string depthwrite, std::string shader); * Adds a new texture to the list of textures to bind while rendering
*
* @param texture
*/
void insertTexture (const std::string& texture);
/**
* Updates a texture in the specified index for binding while rendering
*
* @param index
* @param texture
*/
void setTexture (int index, const std::string& texture);
/** private:
* Adds a new texture to the list of textures to bind while rendering // TODO: CREATE ENUMERATIONS FOR THESE INSTEAD OF USING STRING VALUES!
* /** The blending mode to use */
* @param texture std::string m_blending;
*/ /** The culling mode to use */
void insertTexture (const std::string& texture); std::string m_cullmode;
/** /** If depthtesting has to happen while drawing */
* Updates a texture in the specified index for binding while rendering std::string m_depthtest;
* /** If depthwrite has to happen while drawing */
* @param index std::string m_depthwrite;
* @param texture /** The shader to use */
*/ std::string m_shader;
void setTexture (int index, const std::string& texture); /** The list of textures to use */
std::vector<std::string> m_textures;
private: /** Different combo settings for shader input */
// TODO: CREATE ENUMERATIONS FOR THESE INSTEAD OF USING STRING VALUES! std::map<std::string, int> m_combos;
/** The blending mode to use */ /** Shader constant values to use for the shaders */
std::string m_blending; std::map<std::string, Core::Objects::Effects::Constants::CShaderConstant*> m_constants;
/** The culling mode to use */ };
std::string m_cullmode; } // namespace WallpaperEngine::Core::Objects::Images::Materials
/** If depthtesting has to happen while drawing */
std::string m_depthtest;
/** If depthwrite has to happen while drawing */
std::string m_depthwrite;
/** The shader to use */
std::string m_shader;
/** The list of textures to use */
std::vector<std::string> m_textures;
/** Different combo settings for shader input */
std::map<std::string, int> m_combos;
/** Shader constant values to use for the shaders */
std::map<std::string, Core::Objects::Effects::Constants::CShaderConstant*> m_constants;
};
}

View File

@ -2,11 +2,10 @@
using namespace WallpaperEngine::Core::Objects::Particles; using namespace WallpaperEngine::Core::Objects::Particles;
CControlPoint* CControlPoint::fromJSON (json data) CControlPoint* CControlPoint::fromJSON (json data) {
{ const auto flags_it = data.find ("flags");
auto flags_it = data.find ("flags"); const auto id_it = jsonFindRequired (data, "id", "Particle's control point must have id");
auto id_it = jsonFindRequired (data, "id", "Particle's control point must have id"); const auto offset_it = data.find ("offset");
auto offset_it = data.find ("offset");
auto* controlpoint = new CControlPoint (*id_it, 0); auto* controlpoint = new CControlPoint (*id_it, 0);
@ -19,33 +18,24 @@ CControlPoint* CControlPoint::fromJSON (json data)
return controlpoint; return controlpoint;
} }
CControlPoint::CControlPoint (uint32_t id, uint32_t flags) : CControlPoint::CControlPoint (uint32_t id, uint32_t flags) : m_id (id), m_flags (flags), m_offset (glm::vec3 ()) {}
m_id (id),
m_flags (flags),
m_offset (glm::vec3 ())
{
}
void CControlPoint::setOffset (const glm::vec3& offset) void CControlPoint::setOffset (const glm::vec3& offset) {
{
this->m_offset = offset; this->m_offset = offset;
} }
void CControlPoint::setFlags (uint32_t flags) void CControlPoint::setFlags (uint32_t flags) {
{
this->m_flags = flags; this->m_flags = flags;
} }
uint32_t CControlPoint::getId () const
{ uint32_t CControlPoint::getId () const {
return this->m_id; return this->m_id;
} }
const glm::vec3& CControlPoint::getOffset () const const glm::vec3& CControlPoint::getOffset () const {
{
return this->m_offset; return this->m_offset;
} }
uint32_t CControlPoint::getFlags () const uint32_t CControlPoint::getFlags () const {
{
return this->m_flags; return this->m_flags;
} }

View File

@ -2,49 +2,47 @@
#include "WallpaperEngine/Core/Core.h" #include "WallpaperEngine/Core/Core.h"
namespace WallpaperEngine::Core::Objects::Particles namespace WallpaperEngine::Core::Objects::Particles {
{ using json = nlohmann::json;
using json = nlohmann::json;
/**
* Control point for particles
*/
class CControlPoint {
public:
static CControlPoint* fromJSON (json data);
/** /**
* Control point for particles * @return The id of the controlpoint used for ordering purposes
*/ */
class CControlPoint [[nodiscard]] uint32_t getId () const;
{ /**
public: * @return The offset from origin
static CControlPoint* fromJSON (json data); */
[[nodiscard]] const glm::vec3& getOffset () const;
/**
* @return Flags for the control point, controls how it should behave
*/
[[nodiscard]] uint32_t getFlags () const;
/** protected:
* @return The id of the controlpoint used for ordering purposes explicit CControlPoint (uint32_t id, uint32_t flags = 0);
*/
[[nodiscard]] uint32_t getId () const;
/**
* @return The offset from origin
*/
[[nodiscard]] const glm::vec3& getOffset () const;
/**
* @return Flags for the control point, controls how it should behave
*/
[[nodiscard]] uint32_t getFlags () const;
protected: /**
explicit CControlPoint (uint32_t id, uint32_t flags = 0); * @param offset The new offset
*/
void setOffset (const glm::vec3& offset);
/**
* @param flags The new flags
*/
void setFlags (uint32_t flags);
/** private:
* @param offset The new offset /** ID used for ordering purposes */
*/ uint32_t m_id;
void setOffset (const glm::vec3& offset); /** Flags that control how it behaves */
/** uint32_t m_flags;
* @param flags The new flags /** The offset from starting position */
*/ glm::vec3 m_offset;
void setFlags (uint32_t flags); };
} // namespace WallpaperEngine::Core::Objects::Particles
private:
/** ID used for ordering purposes */
uint32_t m_id;
/** Flags that control how it behaves */
uint32_t m_flags;
/** The offset from starting position */
glm::vec3 m_offset;
};
}

View File

@ -2,76 +2,54 @@
using namespace WallpaperEngine::Core::Objects::Particles; using namespace WallpaperEngine::Core::Objects::Particles;
CEmitter* CEmitter::fromJSON (json data) CEmitter* CEmitter::fromJSON (json data) {
{ const auto directions_it = jsonFindRequired (data, "directions", "Particle emitter must have direction specified");
auto directions_it = jsonFindRequired (data, "directions", "Particle emitter must have direction specified"); const auto distancemax_it = jsonFindRequired (data, "distancemax", "Particle emitter must have maximum distance");
auto distancemax_it = jsonFindRequired (data, "distancemax", "Particle emitter must have maximum distance"); const auto distancemin_it = jsonFindRequired (data, "distancemin", "Particle emitter must have minimum distance");
auto distancemin_it = jsonFindRequired (data, "distancemin", "Particle emitter must have minimum distance"); const auto id_it = data.find ("id");
auto id_it = data.find ("id"); const auto name_it = jsonFindRequired (data, "name", "Particle emitter must have a name");
auto name_it = jsonFindRequired (data, "name", "Particle emitter must have a name"); const auto origin_it = jsonFindRequired (data, "origin", "Particle emitter must have an origin");
auto origin_it = jsonFindRequired (data, "origin", "Particle emitter must have an origin"); const auto rate_it = jsonFindRequired (data, "rate", "Particle emitter must have a rate");
auto rate_it = jsonFindRequired (data, "rate", "Particle emitter must have a rate");
return new CEmitter ( return new CEmitter (WallpaperEngine::Core::aToVector3 (*directions_it), *distancemax_it, *distancemin_it,
WallpaperEngine::Core::aToVector3 (*directions_it), (id_it == data.end () ? 0 : static_cast<uint32_t> (*id_it)), *name_it,
*distancemax_it, WallpaperEngine::Core::aToVector3 (*origin_it), *rate_it);
*distancemin_it,
(id_it == data.end () ? 0 : (uint32_t) (*id_it)),
*name_it,
WallpaperEngine::Core::aToVector3 (*origin_it),
*rate_it
);
} }
CEmitter::CEmitter ( CEmitter::CEmitter (const glm::vec3& directions, uint32_t distancemax, uint32_t distancemin, uint32_t id,
const glm::vec3& directions, std::string name, const glm::vec3& origin, double rate) :
uint32_t distancemax,
uint32_t distancemin,
uint32_t id,
std::string name,
const glm::vec3& origin,
double rate):
m_directions (directions), m_directions (directions),
m_distancemax (distancemax), m_distancemax (distancemax),
m_distancemin (distancemin), m_distancemin (distancemin),
m_id (id), m_id (id),
m_name (std::move(name)), m_name (std::move (name)),
m_origin (origin), m_origin (origin),
m_rate (rate) m_rate (rate) {}
{
}
uint32_t CEmitter::getId () const uint32_t CEmitter::getId () const {
{
return this->m_id; return this->m_id;
} }
const std::string& CEmitter::getName () const const std::string& CEmitter::getName () const {
{
return this->m_name; return this->m_name;
} }
const uint32_t CEmitter::getDistanceMax () const const uint32_t CEmitter::getDistanceMax () const {
{
return this->m_distancemax; return this->m_distancemax;
} }
const uint32_t CEmitter::getDistanceMin () const const uint32_t CEmitter::getDistanceMin () const {
{
return this->m_distancemin; return this->m_distancemin;
} }
const glm::vec3& CEmitter::getDirections () const const glm::vec3& CEmitter::getDirections () const {
{
return this->m_directions; return this->m_directions;
} }
const glm::vec3& CEmitter::getOrigin () const const glm::vec3& CEmitter::getOrigin () const {
{
return this->m_origin; return this->m_origin;
} }
const double CEmitter::getRate () const const double CEmitter::getRate () const {
{
return this->m_rate; return this->m_rate;
} }

View File

@ -2,67 +2,63 @@
#include "WallpaperEngine/Core/Core.h" #include "WallpaperEngine/Core/Core.h"
namespace WallpaperEngine::Core::Objects::Particles namespace WallpaperEngine::Core::Objects::Particles {
{ using json = nlohmann::json;
using json = nlohmann::json;
/**
* Particle emitter, controls the area where the particles have to be created
*/
class CEmitter {
public:
static CEmitter* fromJSON (json data);
/** /**
* Particle emitter, controls the area where the particles have to be created * @return The ID of the emitter
*/ */
class CEmitter [[nodiscard]] uint32_t getId () const;
{ /**
public: * @return The name of the emitter, indicates what type of emission to do
static CEmitter* fromJSON (json data); */
[[nodiscard]] const std::string& getName () const;
/**
* @return The maximum distance a particle can travel before being dead
*/
[[nodiscard]] const uint32_t getDistanceMax () const;
/**
* @return The minimum distance a particle can travel before being dead
*/
[[nodiscard]] const uint32_t getDistanceMin () const;
/**
* @return The direction a particle should move to
*/
[[nodiscard]] const glm::vec3& getDirections () const;
/**
* @return The center of the particle emission
*/
[[nodiscard]] const glm::vec3& getOrigin () const;
/**
* @return The rate of particle emission
*/
[[nodiscard]] const double getRate () const;
/** protected:
* @return The ID of the emitter CEmitter (const glm::vec3& directions, uint32_t distancemax, uint32_t distancemin, uint32_t id, std::string name,
*/ const glm::vec3& origin, double rate);
[[nodiscard]] uint32_t getId () const;
/**
* @return The name of the emitter, indicates what type of emission to do
*/
[[nodiscard]] const std::string& getName () const;
/**
* @return The maximum distance a particle can travel before being dead
*/
[[nodiscard]] const uint32_t getDistanceMax () const;
/**
* @return The minimum distance a particle can travel before being dead
*/
[[nodiscard]] const uint32_t getDistanceMin () const;
/**
* @return The direction a particle should move to
*/
[[nodiscard]] const glm::vec3& getDirections () const;
/**
* @return The center of the particle emission
*/
[[nodiscard]] const glm::vec3& getOrigin () const;
/**
* @return The rate of particle emission
*/
[[nodiscard]] const double getRate () const;
protected: private:
CEmitter ( /** Direction the particles should move to */
const glm::vec3& directions, uint32_t distancemax, uint32_t distancemin, uint32_t id, std::string name, glm::vec3 m_directions;
const glm::vec3& origin, double rate /** Maximum distance before the particle is dead */
); uint32_t m_distancemax;
/** Minimum distance before the particle is dead */
private: uint32_t m_distancemin;
/** Direction the particles should move to */ /** ID of the emitter */
glm::vec3 m_directions; uint32_t m_id;
/** Maximum distance before the particle is dead */ /** Name of the emitter, indicates the type of emitter */
uint32_t m_distancemax; std::string m_name;
/** Minimum distance before the particle is dead */ /** The center of the emitter */
uint32_t m_distancemin; glm::vec3 m_origin;
/** ID of the emitter */ /** The rate of emission */
uint32_t m_id; double m_rate;
/** Name of the emitter, indicates the type of emitter */ };
std::string m_name; } // namespace WallpaperEngine::Core::Objects::Particles
/** The center of the emitter */
glm::vec3 m_origin;
/** The rate of emission */
double m_rate;
};
}

View File

@ -1,75 +1,56 @@
#include "common.h"
#include "CInitializer.h" #include "CInitializer.h"
#include "common.h"
#include "WallpaperEngine/Core/Objects/Particles/Initializers/CLifeTimeRandom.h"
#include "WallpaperEngine/Core/Objects/Particles/Initializers/CSizeRandom.h"
#include "WallpaperEngine/Core/Objects/Particles/Initializers/CRotationRandom.h"
#include "WallpaperEngine/Core/Objects/Particles/Initializers/CVelocityRandom.h"
#include "WallpaperEngine/Core/Objects/Particles/Initializers/CColorRandom.h"
#include "WallpaperEngine/Core/Objects/Particles/Initializers/CAlphaRandom.h" #include "WallpaperEngine/Core/Objects/Particles/Initializers/CAlphaRandom.h"
#include "WallpaperEngine/Core/Objects/Particles/Initializers/CAngularVelocityRandom.h" #include "WallpaperEngine/Core/Objects/Particles/Initializers/CAngularVelocityRandom.h"
#include "WallpaperEngine/Core/Objects/Particles/Initializers/CColorRandom.h"
#include "WallpaperEngine/Core/Objects/Particles/Initializers/CLifeTimeRandom.h"
#include "WallpaperEngine/Core/Objects/Particles/Initializers/CRotationRandom.h"
#include "WallpaperEngine/Core/Objects/Particles/Initializers/CSizeRandom.h"
#include "WallpaperEngine/Core/Objects/Particles/Initializers/CTurbulentVelocityRandom.h" #include "WallpaperEngine/Core/Objects/Particles/Initializers/CTurbulentVelocityRandom.h"
#include "WallpaperEngine/Core/Objects/Particles/Initializers/CVelocityRandom.h"
using namespace WallpaperEngine::Core::Objects::Particles; using namespace WallpaperEngine::Core::Objects::Particles;
CInitializer* CInitializer::fromJSON (json data) CInitializer* CInitializer::fromJSON (json data) {
{ const auto id_it = data.find ("id");
auto id_it = data.find ("id"); const auto name_it = jsonFindRequired (data, "name", "Particle's initializer must have a name");
auto name_it = jsonFindRequired (data, "name", "Particle's initializer must have a name"); const uint32_t id = ((id_it == data.end ()) ? 0 : static_cast<uint32_t> (*id_it));
uint32_t id = ((id_it == data.end ()) ? 0 : (uint32_t) (*id_it));
if (*name_it == "lifetimerandom") if (*name_it == "lifetimerandom") {
{
return Initializers::CLifeTimeRandom::fromJSON (data, id); return Initializers::CLifeTimeRandom::fromJSON (data, id);
} }
else if (*name_it == "sizerandom") if (*name_it == "sizerandom") {
{
return Initializers::CSizeRandom::fromJSON (data, id); return Initializers::CSizeRandom::fromJSON (data, id);
} }
else if (*name_it == "rotationrandom") if (*name_it == "rotationrandom") {
{
return Initializers::CRotationRandom::fromJSON (data, id); return Initializers::CRotationRandom::fromJSON (data, id);
} }
else if (*name_it == "velocityrandom") if (*name_it == "velocityrandom") {
{
return Initializers::CVelocityRandom::fromJSON (data, id); return Initializers::CVelocityRandom::fromJSON (data, id);
} }
else if (*name_it == "colorrandom") if (*name_it == "colorrandom") {
{
return Initializers::CColorRandom::fromJSON (data, id); return Initializers::CColorRandom::fromJSON (data, id);
} }
else if (*name_it == "alpharandom") if (*name_it == "alpharandom") {
{
return Initializers::CAlphaRandom::fromJSON (data, id); return Initializers::CAlphaRandom::fromJSON (data, id);
} }
else if (*name_it == "angularvelocityrandom") if (*name_it == "angularvelocityrandom") {
{
return Initializers::CAngularVelocityRandom::fromJSON (data, id); return Initializers::CAngularVelocityRandom::fromJSON (data, id);
} }
else if (*name_it == "turbulentvelocityrandom") if (*name_it == "turbulentvelocityrandom") {
{
return Initializers::CTurbulentVelocityRandom::fromJSON (data, id); return Initializers::CTurbulentVelocityRandom::fromJSON (data, id);
} }
else
{ sLog.exception ("Found unknown initializer for particles: ", *name_it);
sLog.exception ("Found unknown initializer for particles: ", *name_it);
}
} }
CInitializer::CInitializer (uint32_t id, std::string name) : m_id (id), m_name (std::move (name)) {}
CInitializer::CInitializer (uint32_t id, std::string name) : const std::string& CInitializer::getName () const {
m_id (id),
m_name (std::move(name))
{
}
const std::string& CInitializer::getName () const
{
return this->m_name; return this->m_name;
} }
uint32_t CInitializer::getId () const uint32_t CInitializer::getId () const {
{
return this->m_id; return this->m_id;
} }

View File

@ -2,35 +2,33 @@
#include "WallpaperEngine/Core/Core.h" #include "WallpaperEngine/Core/Core.h"
namespace WallpaperEngine::Core::Objects::Particles namespace WallpaperEngine::Core::Objects::Particles {
{ using json = nlohmann::json;
using json = nlohmann::json;
/**
* Initializer for particles, controls the different attributes a particle will have
* on emission
*/
class CInitializer {
public:
static CInitializer* fromJSON (json data);
/** /**
* Initializer for particles, controls the different attributes a particle will have * @return The name of the particle initializer, indicates what type of initialization to do
* on emission
*/ */
class CInitializer [[nodiscard]] const std::string& getName () const;
{ /**
public: * @return The id of the initializer
static CInitializer* fromJSON (json data); */
[[nodiscard]] uint32_t getId () const;
/** protected:
* @return The name of the particle initializer, indicates what type of initialization to do CInitializer (uint32_t id, std::string name);
*/
[[nodiscard]] const std::string& getName () const;
/**
* @return The id of the initializer
*/
[[nodiscard]] uint32_t getId () const;
protected: private:
CInitializer (uint32_t id, std::string name); /** ID for ordering purposes */
uint32_t m_id;
private: /** The name of the initializer, indicates what type of initialization to do */
/** ID for ordering purposes */ std::string m_name;
uint32_t m_id; };
/** The name of the initializer, indicates what type of initialization to do */ } // namespace WallpaperEngine::Core::Objects::Particles
std::string m_name;
};
}

View File

@ -2,27 +2,22 @@
using namespace WallpaperEngine::Core::Objects::Particles::Initializers; using namespace WallpaperEngine::Core::Objects::Particles::Initializers;
CAlphaRandom* CAlphaRandom::fromJSON (json data, uint32_t id) CAlphaRandom* CAlphaRandom::fromJSON (json data, uint32_t id) {
{ const auto min_it = jsonFindRequired (data, "min", "Alpharandom initializer must have a minimum value");
auto min_it = jsonFindRequired (data, "min", "Alpharandom initializer must have a minimum value"); const auto max_it = jsonFindRequired (data, "max", "Alpharandom initializer must have a maximum value");
auto max_it = jsonFindRequired (data, "max", "Alpharandom initializer must have a maximum value");
return new CAlphaRandom (id, *min_it, *max_it); return new CAlphaRandom (id, *min_it, *max_it);
} }
CAlphaRandom::CAlphaRandom (uint32_t id, double min, double max) : CAlphaRandom::CAlphaRandom (uint32_t id, double min, double max) :
CInitializer (id, "alpharandom"), CInitializer (id, "alpharandom"),
m_min (min), m_min (min),
m_max (max) m_max (max) {}
{
}
double CAlphaRandom::getMinimum () const double CAlphaRandom::getMinimum () const {
{
return this->m_min; return this->m_min;
} }
double CAlphaRandom::getMaximum () const double CAlphaRandom::getMaximum () const {
{
return this->m_max; return this->m_max;
} }

View File

@ -3,34 +3,32 @@
#include "WallpaperEngine/Core/Core.h" #include "WallpaperEngine/Core/Core.h"
#include "WallpaperEngine/Core/Objects/Particles/CInitializer.h" #include "WallpaperEngine/Core/Objects/Particles/CInitializer.h"
namespace WallpaperEngine::Core::Objects::Particles::Initializers namespace WallpaperEngine::Core::Objects::Particles::Initializers {
{ /**
/** * Initializer for particles that decides the base alpha for the particles
* Initializer for particles that decides the base alpha for the particles */
*/ class CAlphaRandom : CInitializer {
class CAlphaRandom : CInitializer public:
{ /**
public: * @return The minimum alpha value to be used
/** */
* @return The minimum alpha value to be used [[nodiscard]] double getMinimum () const;
*/ /**
[[nodiscard]] double getMinimum () const; * @return The maximum alpha value to be used
/** */
* @return The maximum alpha value to be used [[nodiscard]] double getMaximum () const;
*/
[[nodiscard]] double getMaximum () const;
protected: protected:
friend class CInitializer; friend class CInitializer;
static CAlphaRandom* fromJSON (json data, uint32_t id); static CAlphaRandom* fromJSON (json data, uint32_t id);
CAlphaRandom (uint32_t id, double min, double max); CAlphaRandom (uint32_t id, double min, double max);
private: private:
/** Maximum alpha */ /** Maximum alpha */
double m_max; double m_max;
/** Minimum alpha */ /** Minimum alpha */
double m_min; double m_min;
}; };
} } // namespace WallpaperEngine::Core::Objects::Particles::Initializers

View File

@ -2,32 +2,23 @@
using namespace WallpaperEngine::Core::Objects::Particles::Initializers; using namespace WallpaperEngine::Core::Objects::Particles::Initializers;
CAngularVelocityRandom* CAngularVelocityRandom::fromJSON (json data, uint32_t id) CAngularVelocityRandom* CAngularVelocityRandom::fromJSON (json data, uint32_t id) {
{ const auto min_it = jsonFindRequired (data, "min", "Angularvelocityrandom initializer must have a minimum value");
auto min_it = jsonFindRequired (data, "min", "Angularvelocityrandom initializer must have a minimum value"); const auto max_it = jsonFindRequired (data, "max", "Angularvelocityrandom initializer must have a maximum value");
auto max_it = jsonFindRequired (data, "max", "Angularvelocityrandom initializer must have a maximum value");
return new CAngularVelocityRandom ( return new CAngularVelocityRandom (id, WallpaperEngine::Core::aToVector3 (*min_it),
id, WallpaperEngine::Core::aToVector3 (*max_it));
WallpaperEngine::Core::aToVector3 (*min_it),
WallpaperEngine::Core::aToVector3 (*max_it)
);
} }
CAngularVelocityRandom::CAngularVelocityRandom (uint32_t id, glm::vec3 min, glm::vec3 max) : CAngularVelocityRandom::CAngularVelocityRandom (uint32_t id, glm::vec3 min, glm::vec3 max) :
CInitializer (id, "angularvelocityrandom"), CInitializer (id, "angularvelocityrandom"),
m_min (min), m_min (min),
m_max (max) m_max (max) {}
{
}
const glm::vec3& CAngularVelocityRandom::getMinimum () const const glm::vec3& CAngularVelocityRandom::getMinimum () const {
{
return this->m_min; return this->m_min;
} }
const glm::vec3& CAngularVelocityRandom::getMaximum () const const glm::vec3& CAngularVelocityRandom::getMaximum () const {
{
return this->m_max; return this->m_max;
} }

View File

@ -3,34 +3,32 @@
#include "WallpaperEngine/Core/Core.h" #include "WallpaperEngine/Core/Core.h"
#include "WallpaperEngine/Core/Objects/Particles/CInitializer.h" #include "WallpaperEngine/Core/Objects/Particles/CInitializer.h"
namespace WallpaperEngine::Core::Objects::Particles::Initializers namespace WallpaperEngine::Core::Objects::Particles::Initializers {
{ /**
/** * Initializer for particles that decides the base angular velocity for particles
* Initializer for particles that decides the base angular velocity for particles */
*/ class CAngularVelocityRandom : CInitializer {
class CAngularVelocityRandom : CInitializer public:
{ /**
public: * @return Minimum angular velocity (direction * speed)
/** */
* @return Minimum angular velocity (direction * speed) [[nodiscard]] const glm::vec3& getMinimum () const;
*/ /**
[[nodiscard]] const glm::vec3& getMinimum () const; * @return Maximum angular velocity (direction * speed)
/** */
* @return Maximum angular velocity (direction * speed) [[nodiscard]] const glm::vec3& getMaximum () const;
*/
[[nodiscard]] const glm::vec3& getMaximum () const;
protected: protected:
friend class CInitializer; friend class CInitializer;
static CAngularVelocityRandom* fromJSON (json data, uint32_t id); static CAngularVelocityRandom* fromJSON (json data, uint32_t id);
CAngularVelocityRandom (uint32_t id, glm::vec3 min, glm::vec3 max); CAngularVelocityRandom (uint32_t id, glm::vec3 min, glm::vec3 max);
private: private:
/** Maximum velocity (direction * speed) */ /** Maximum velocity (direction * speed) */
glm::vec3 m_max; glm::vec3 m_max;
/** Minimum velocity (direction * speed) */ /** Minimum velocity (direction * speed) */
glm::vec3 m_min; glm::vec3 m_min;
}; };
} } // namespace WallpaperEngine::Core::Objects::Particles::Initializers

View File

@ -2,32 +2,23 @@
using namespace WallpaperEngine::Core::Objects::Particles::Initializers; using namespace WallpaperEngine::Core::Objects::Particles::Initializers;
CColorRandom* CColorRandom::fromJSON (json data, uint32_t id) CColorRandom* CColorRandom::fromJSON (json data, uint32_t id) {
{ const auto min_it = jsonFindRequired (data, "min", "Colorrandom initializer must have a minimum value");
auto min_it = jsonFindRequired (data, "min", "Colorrandom initializer must have a minimum value"); const auto max_it = jsonFindRequired (data, "max", "Colorrandom initializer must have a maximum value");
auto max_it = jsonFindRequired (data, "max", "Colorrandom initializer must have a maximum value");
return new CColorRandom ( return new CColorRandom (id, WallpaperEngine::Core::aToColori (*min_it),
id, WallpaperEngine::Core::aToColori (*max_it));
WallpaperEngine::Core::aToColori (*min_it),
WallpaperEngine::Core::aToColori (*max_it)
);
} }
CColorRandom::CColorRandom (uint32_t id, glm::ivec3 min, glm::ivec3 max) : CColorRandom::CColorRandom (uint32_t id, glm::ivec3 min, glm::ivec3 max) :
CInitializer (id, "colorrandom"), CInitializer (id, "colorrandom"),
m_min (min), m_min (min),
m_max (max) m_max (max) {}
{
}
const glm::ivec3& CColorRandom::getMinimum () const const glm::ivec3& CColorRandom::getMinimum () const {
{
return this->m_min; return this->m_min;
} }
const glm::ivec3& CColorRandom::getMaximum () const const glm::ivec3& CColorRandom::getMaximum () const {
{
return this->m_max; return this->m_max;
} }

View File

@ -4,34 +4,32 @@
#include "WallpaperEngine/Core/Core.h" #include "WallpaperEngine/Core/Core.h"
namespace WallpaperEngine::Core::Objects::Particles::Initializers namespace WallpaperEngine::Core::Objects::Particles::Initializers {
{ /**
/** * Initializer for particles that decides the base color
* Initializer for particles that decides the base color */
*/ class CColorRandom : CInitializer {
class CColorRandom : CInitializer public:
{ /**
public: * @return The minimum color to use (RGB)
/** */
* @return The minimum color to use (RGB) [[nodiscard]] const glm::ivec3& getMinimum () const;
*/ /**
[[nodiscard]] const glm::ivec3& getMinimum () const; * @return The maximum color to use (RGB)
/** */
* @return The maximum color to use (RGB) [[nodiscard]] const glm::ivec3& getMaximum () const;
*/
[[nodiscard]] const glm::ivec3& getMaximum () const;
protected: protected:
friend class CInitializer; friend class CInitializer;
static CColorRandom* fromJSON (json data, uint32_t id); static CColorRandom* fromJSON (json data, uint32_t id);
CColorRandom (uint32_t id, glm::ivec3 min, glm::ivec3 max); CColorRandom (uint32_t id, glm::ivec3 min, glm::ivec3 max);
private: private:
/** Maximum color */ /** Maximum color */
glm::ivec3 m_max; glm::ivec3 m_max;
/** Minimum color */ /** Minimum color */
glm::ivec3 m_min; glm::ivec3 m_min;
}; };
} } // namespace WallpaperEngine::Core::Objects::Particles::Initializers

View File

@ -2,28 +2,22 @@
using namespace WallpaperEngine::Core::Objects::Particles::Initializers; using namespace WallpaperEngine::Core::Objects::Particles::Initializers;
CLifeTimeRandom* CLifeTimeRandom::fromJSON (json data, uint32_t id) CLifeTimeRandom* CLifeTimeRandom::fromJSON (json data, uint32_t id) {
{ const auto min_it = jsonFindRequired (data, "min", "Lifetimerandom initializer must have a minimum value");
auto min_it = jsonFindRequired (data, "min", "Lifetimerandom initializer must have a minimum value"); const auto max_it = jsonFindRequired (data, "max", "Lifetimerandom initializer must have a maximum value");
auto max_it = jsonFindRequired (data, "max", "Lifetimerandom initializer must have a maximum value");
return new CLifeTimeRandom (id, *min_it, *max_it); return new CLifeTimeRandom (id, *min_it, *max_it);
} }
CLifeTimeRandom::CLifeTimeRandom (uint32_t id, uint32_t min, uint32_t max) : CLifeTimeRandom::CLifeTimeRandom (uint32_t id, uint32_t min, uint32_t max) :
CInitializer (id, "lifetimerandom"), CInitializer (id, "lifetimerandom"),
m_min (min), m_min (min),
m_max (max) m_max (max) {}
{
}
uint32_t CLifeTimeRandom::getMinimum () const uint32_t CLifeTimeRandom::getMinimum () const {
{
return this->m_min; return this->m_min;
} }
uint32_t CLifeTimeRandom::getMaximum () const uint32_t CLifeTimeRandom::getMaximum () const {
{
return this->m_max; return this->m_max;
} }

View File

@ -4,33 +4,32 @@
#include "WallpaperEngine/Core/Core.h" #include "WallpaperEngine/Core/Core.h"
namespace WallpaperEngine::Core::Objects::Particles::Initializers namespace WallpaperEngine::Core::Objects::Particles::Initializers {
{ /**
* Initializer for particles that decides the lifetime of each particle on startup
*/
class CLifeTimeRandom : CInitializer {
public:
/** /**
* Initializer for particles that decides the lifetime of each particle on startup * @return The minimum lifetime to be used
*/ */
class CLifeTimeRandom : CInitializer [[nodiscard]] uint32_t getMinimum () const;
{ /**
public: * @return The maximum lifetime to be used
/** */
* @return The minimum lifetime to be used [[nodiscard]] uint32_t getMaximum () const;
*/
[[nodiscard]] uint32_t getMinimum () const;
/**
* @return The maximum lifetime to be used
*/
[[nodiscard]] uint32_t getMaximum () const;
protected:
friend class CInitializer;
static CLifeTimeRandom* fromJSON (json data, uint32_t id); protected:
friend class CInitializer;
CLifeTimeRandom (uint32_t id, uint32_t min, uint32_t max); static CLifeTimeRandom* fromJSON (json data, uint32_t id);
private: CLifeTimeRandom (uint32_t id, uint32_t min, uint32_t max);
/** Maximum lifetime */
uint32_t m_max; private:
/** Minimum lifetime */ /** Maximum lifetime */
uint32_t m_min; uint32_t m_max;
}; /** Minimum lifetime */
} uint32_t m_min;
};
} // namespace WallpaperEngine::Core::Objects::Particles::Initializers

View File

@ -4,10 +4,9 @@
using namespace WallpaperEngine::Core::Objects::Particles::Initializers; using namespace WallpaperEngine::Core::Objects::Particles::Initializers;
CRotationRandom* CRotationRandom::fromJSON (json data, uint32_t id) CRotationRandom* CRotationRandom::fromJSON (json data, uint32_t id) {
{ const auto min_it = data.find ("minVector");
auto min_it = data.find ("minVector"); const auto max_it = data.find ("max");
auto max_it = data.find ("max");
glm::vec3 minVector = glm::vec3 (); glm::vec3 minVector = glm::vec3 ();
glm::vec3 maxVector = glm::vec3 (); glm::vec3 maxVector = glm::vec3 ();
@ -16,24 +15,18 @@ CRotationRandom* CRotationRandom::fromJSON (json data, uint32_t id)
bool isMinVector = false; bool isMinVector = false;
bool isMaxVector = false; bool isMaxVector = false;
if (min_it != data.end () && min_it->is_string ()) if (min_it != data.end () && min_it->is_string ()) {
{
minVector = WallpaperEngine::Core::aToVector3 (*min_it); minVector = WallpaperEngine::Core::aToVector3 (*min_it);
isMinVector = true; isMinVector = true;
} } else if (min_it != data.end () && min_it->is_number ()) {
else if (min_it != data.end () && min_it->is_number ())
{
minNumber = *min_it; minNumber = *min_it;
isMinVector = false; isMinVector = false;
} }
if (max_it != data.end () && max_it->is_string ()) if (max_it != data.end () && max_it->is_string ()) {
{
maxVector = WallpaperEngine::Core::aToVector3 (*max_it); maxVector = WallpaperEngine::Core::aToVector3 (*max_it);
isMaxVector = true; isMaxVector = true;
} } else if (max_it != data.end () && max_it->is_number ()) {
else if(max_it != data.end () && max_it->is_number ())
{
maxNumber = *max_it; maxNumber = *max_it;
isMaxVector = false; isMaxVector = false;
} }
@ -41,61 +34,44 @@ CRotationRandom* CRotationRandom::fromJSON (json data, uint32_t id)
return new CRotationRandom (id, minVector, minNumber, isMinVector, maxVector, maxNumber, isMaxVector); return new CRotationRandom (id, minVector, minNumber, isMinVector, maxVector, maxNumber, isMaxVector);
} }
CRotationRandom::CRotationRandom ( CRotationRandom::CRotationRandom (uint32_t id, glm::vec3 minVector, double minNumber, bool isMinimumVector,
uint32_t id, glm::vec3 maxVector, double maxNumber, bool isMaximumVector) :
glm::vec3 minVector,
double minNumber,
bool isMinimumVector,
glm::vec3 maxVector,
double maxNumber,
bool isMaximumVector
) :
CInitializer (id, "rotationrandom"), CInitializer (id, "rotationrandom"),
m_minVector (minVector), m_minVector (minVector),
m_maxVector (maxVector), m_maxVector (maxVector),
m_minNumber (minNumber), m_minNumber (minNumber),
m_maxNumber (maxNumber), m_maxNumber (maxNumber),
m_isMinimumVector (isMinimumVector), m_isMinimumVector (isMinimumVector),
m_isMaximumVector (isMaximumVector) m_isMaximumVector (isMaximumVector) {}
{
}
glm::vec3 CRotationRandom::getMinimumVector () const glm::vec3 CRotationRandom::getMinimumVector () const {
{
return this->m_minVector; return this->m_minVector;
} }
glm::vec3 CRotationRandom::getMaximumVector () const glm::vec3 CRotationRandom::getMaximumVector () const {
{
return this->m_maxVector; return this->m_maxVector;
} }
double CRotationRandom::getMinimumNumber () const double CRotationRandom::getMinimumNumber () const {
{
return this->m_minNumber; return this->m_minNumber;
} }
double CRotationRandom::getMaximumNumber () const double CRotationRandom::getMaximumNumber () const {
{
return this->m_maxNumber; return this->m_maxNumber;
} }
bool CRotationRandom::isMinimumVector () const bool CRotationRandom::isMinimumVector () const {
{
return this->m_isMinimumVector; return this->m_isMinimumVector;
} }
bool CRotationRandom::isMinimumNumber () const bool CRotationRandom::isMinimumNumber () const {
{
return !this->m_isMinimumVector; return !this->m_isMinimumVector;
} }
bool CRotationRandom::isMaximumVector () const bool CRotationRandom::isMaximumVector () const {
{
return this->m_isMaximumVector; return this->m_isMaximumVector;
} }
bool CRotationRandom::isMaximumNumber () const bool CRotationRandom::isMaximumNumber () const {
{
return !this->m_isMaximumVector; return !this->m_isMaximumVector;
} }

View File

@ -4,76 +4,67 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
namespace WallpaperEngine::Core::Objects::Particles::Initializers namespace WallpaperEngine::Core::Objects::Particles::Initializers {
{ /**
* Initializer for particles that decides the base rotation for the particles
*/
class CRotationRandom : CInitializer {
public:
/** /**
* Initializer for particles that decides the base rotation for the particles * @return The minimum rotation in vector format if available
*/ */
class CRotationRandom : CInitializer [[nodiscard]] glm::vec3 getMinimumVector () const;
{ /**
public: * @return The maximum rotation in vector format if available
/** */
* @return The minimum rotation in vector format if available [[nodiscard]] glm::vec3 getMaximumVector () const;
*/ /**
[[nodiscard]] glm::vec3 getMinimumVector () const; * @return The minimum rotation in angle format if available
/** */
* @return The maximum rotation in vector format if available [[nodiscard]] double getMinimumNumber () const;
*/ /**
[[nodiscard]] glm::vec3 getMaximumVector () const; * @return The maximum rotation in angle format if available
/** */
* @return The minimum rotation in angle format if available [[nodiscard]] double getMaximumNumber () const;
*/
[[nodiscard]] double getMinimumNumber () const;
/**
* @return The maximum rotation in angle format if available
*/
[[nodiscard]] double getMaximumNumber () const;
/** /**
* @return Indicates if the minimum rotation is a vector * @return Indicates if the minimum rotation is a vector
*/ */
[[nodiscard]] bool isMinimumVector () const; [[nodiscard]] bool isMinimumVector () const;
/** /**
* @return Indicates if the minimum rotation is an angle * @return Indicates if the minimum rotation is an angle
*/ */
[[nodiscard]] bool isMinimumNumber () const; [[nodiscard]] bool isMinimumNumber () const;
/** /**
* @return Indicates if the maximum rotation is a vector * @return Indicates if the maximum rotation is a vector
*/ */
[[nodiscard]] bool isMaximumVector () const; [[nodiscard]] bool isMaximumVector () const;
/** /**
* @return Indicates if the maximum rotation is an angle * @return Indicates if the maximum rotation is an angle
*/ */
[[nodiscard]] bool isMaximumNumber () const; [[nodiscard]] bool isMaximumNumber () const;
protected: protected:
friend class CInitializer; friend class CInitializer;
static CRotationRandom* fromJSON (json data, uint32_t id); static CRotationRandom* fromJSON (json data, uint32_t id);
CRotationRandom ( CRotationRandom (uint32_t id, glm::vec3 minVector, double minNumber, bool isMinimumVector, glm::vec3 maxVector,
uint32_t id, double maxNumber, bool isMaximumVector);
glm::vec3 minVector,
double minNumber,
bool isMinimumVector,
glm::vec3 maxVector,
double maxNumber,
bool isMaximumVector
);
private: private:
/** Maximum rotation vector */ /** Maximum rotation vector */
glm::vec3 m_maxVector; glm::vec3 m_maxVector;
/** Maximum rotation angle */ /** Maximum rotation angle */
double m_maxNumber; double m_maxNumber;
/** Minimum rotation vector */ /** Minimum rotation vector */
glm::vec3 m_minVector; glm::vec3 m_minVector;
/** Minimum rotation angle */ /** Minimum rotation angle */
double m_minNumber; double m_minNumber;
/** If minimum is a vector */ /** If minimum is a vector */
bool m_isMinimumVector; bool m_isMinimumVector;
/** If maximum is a vector */ /** If maximum is a vector */
bool m_isMaximumVector; bool m_isMaximumVector;
}; };
} } // namespace WallpaperEngine::Core::Objects::Particles::Initializers

View File

@ -2,10 +2,9 @@
using namespace WallpaperEngine::Core::Objects::Particles::Initializers; using namespace WallpaperEngine::Core::Objects::Particles::Initializers;
CSizeRandom* CSizeRandom::fromJSON (json data, uint32_t id) CSizeRandom* CSizeRandom::fromJSON (json data, uint32_t id) {
{ const auto min_it = jsonFindRequired (data, "min", "Sizerandom initializer must have a minimum value");
auto min_it = jsonFindRequired (data, "min", "Sizerandom initializer must have a minimum value"); const auto max_it = jsonFindRequired (data, "max", "Sizerandom initializer must have a maximum value");
auto max_it = jsonFindRequired (data, "max", "Sizerandom initializer must have a maximum value");
return new CSizeRandom (id, *min_it, *max_it); return new CSizeRandom (id, *min_it, *max_it);
} }
@ -13,16 +12,12 @@ CSizeRandom* CSizeRandom::fromJSON (json data, uint32_t id)
CSizeRandom::CSizeRandom (uint32_t id, uint32_t min, uint32_t max) : CSizeRandom::CSizeRandom (uint32_t id, uint32_t min, uint32_t max) :
CInitializer (id, "sizerandom"), CInitializer (id, "sizerandom"),
m_min (min), m_min (min),
m_max (max) m_max (max) {}
{
}
uint32_t CSizeRandom::getMinimum () const uint32_t CSizeRandom::getMinimum () const {
{
return this->m_min; return this->m_min;
} }
uint32_t CSizeRandom::getMaximum () const uint32_t CSizeRandom::getMaximum () const {
{
return this->m_max; return this->m_max;
} }

Some files were not shown because too many files have changed in this diff Show More