初始化内容
@@ -0,0 +1,295 @@
|
||||
---
|
||||
BasedOnStyle: WebKit
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionDeclarations: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionDeclarations: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionDeclarations: true
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionDeclarations: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveShortCaseStatements:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCaseArrows: false
|
||||
AlignCaseColons: false
|
||||
AlignConsecutiveTableGenBreakingDAGArgColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionDeclarations: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveTableGenCondOperatorColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionDeclarations: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveTableGenDefinitionColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionDeclarations: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: DontAlign
|
||||
AlignTrailingComments:
|
||||
Kind: Never
|
||||
OverEmptyLines: 0
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowBreakBeforeNoexceptSpecifier: Never
|
||||
AllowShortBlocksOnASingleLine: Empty
|
||||
AllowShortCaseExpressionOnASingleLine: true
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortCompoundRequirementOnASingleLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AllowShortNamespacesOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackLongBracedList: true
|
||||
BinPackParameters: BinPack
|
||||
BitFieldColonSpacing: Both
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: true
|
||||
AfterClass: true
|
||||
AfterControlStatement: Always
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterObjCDeclaration: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
AfterExternBlock: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: true
|
||||
IndentBraces: true
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BracedInitializerIndentWidth: -1
|
||||
BreakAdjacentStringLiterals: true
|
||||
BreakAfterAttributes: Leave
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakAfterReturnType: None
|
||||
BreakArrays: true
|
||||
BreakBeforeBinaryOperators: All
|
||||
BreakBeforeBraces: Allman
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakBeforeTemplateCloser: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakBinaryOperations: Never
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakFunctionDefinitionParameters: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakStringLiterals: true
|
||||
BreakTemplateDeclarations: MultiLine
|
||||
ColumnLimit: 0
|
||||
CommentPragmas: "^ IWYU pragma:"
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
EnumTrailingComma: Leave
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: false
|
||||
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: false
|
||||
IndentExportBlock: 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
|
||||
KeepEmptyLines:
|
||||
AtEndOfFile: false
|
||||
AtStartOfBlock: true
|
||||
AtStartOfFile: true
|
||||
KeepFormFeed: false
|
||||
LambdaBodyIndentation: Signature
|
||||
LineEnding: DeriveLF
|
||||
MacroBlockBegin: ""
|
||||
MacroBlockEnd: ""
|
||||
MainIncludeChar: Quote
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: Inner
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 4
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
OneLineFormatOffRegex: ""
|
||||
PPIndentWidth: -1
|
||||
PackConstructorInitializers: BinPack
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakBeforeMemberAccess: 150
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakScopeResolution: 500
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Left
|
||||
QualifierAlignment: Leave
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: Always
|
||||
RemoveBracesLLVM: false
|
||||
RemoveEmptyLinesInUnwrappedLines: false
|
||||
RemoveParentheses: Leave
|
||||
RemoveSemicolon: false
|
||||
RequiresClausePosition: OwnLine
|
||||
RequiresExpressionIndentation: OuterScope
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SkipMacroDefinitionBody: false
|
||||
SortIncludes:
|
||||
Enabled: true
|
||||
IgnoreCase: false
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: LexicographicNumeric
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterOperatorKeyword: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: true
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeJsonColon: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterForeachMacros: true
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterIfMacros: true
|
||||
AfterNot: false
|
||||
AfterOverloadedOperator: false
|
||||
AfterPlacementOperator: true
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: true
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: Never
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParens: Never
|
||||
SpacesInParensOptions:
|
||||
ExceptDoubleParentheses: false
|
||||
InConditionalStatements: false
|
||||
InCStyleCasts: false
|
||||
InEmptyParentheses: false
|
||||
Other: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Latest
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 4
|
||||
TableGenBreakInsideDAGArg: DontBreak
|
||||
UseTab: Always
|
||||
VerilogBreakBetweenInstancePorts: true
|
||||
WhitespaceSensitiveMacros:
|
||||
- BOOST_PP_STRINGIZE
|
||||
- CF_SWIFT_NAME
|
||||
- NS_SWIFT_NAME
|
||||
- PP_STRINGIZE
|
||||
- STRINGIZE
|
||||
WrapNamespaceBodyWithEmptyLines: Leave
|
||||
@@ -0,0 +1,3 @@
|
||||
document/** linguist-vendored
|
||||
build/** linguist-vendored
|
||||
third/** linguist-vendored
|
||||
@@ -0,0 +1,61 @@
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
/.vs
|
||||
/dl/.vs
|
||||
/out
|
||||
/build/*.user
|
||||
/build/x64
|
||||
/build/.vs
|
||||
/build/dl/Debug
|
||||
/build/dl/dl.dir
|
||||
/build/dltest/Debug
|
||||
/build/dltest/dltest.dir
|
||||
/build/third/fmt/fmt.dir
|
||||
/build/third/fmt/Debug
|
||||
/build/third/glfw/src/Debug
|
||||
/build/third/glfw/src/glfw.dir
|
||||
/build/dltest/*.user
|
||||
/build/android/.idea
|
||||
/build/android/app/release
|
||||
/project/dl_test/res/screen_shot.png
|
||||
/tools/cmgen/output
|
||||
/.idea
|
||||
/build/library/bin
|
||||
/build/library/include
|
||||
/build/library/lib
|
||||
.cache/
|
||||
log/
|
||||
project/dl_test/res/dl_test
|
||||
project/dl_console/res/dl_console
|
||||
/project/dl_unit_test/res/dl_unit_test.pdb
|
||||
/hs_build.log
|
||||
@@ -0,0 +1,27 @@
|
||||
[submodule "project/dl_editor"]
|
||||
path = project/dl_editor
|
||||
url = https://gitee.com/lveyou/dl_editor.git
|
||||
[submodule "project/dl_midi"]
|
||||
path = project/dl_midi
|
||||
url = https://gitee.com/lveyou/dl_midi.git
|
||||
[submodule "project/dl_chess"]
|
||||
path = project/dl_chess
|
||||
url = https://gitee.com/lveyou/dl_chess.git
|
||||
[submodule "project/dl_config"]
|
||||
path = project/dl_config
|
||||
url = https://gitee.com/lveyou/dl_config
|
||||
[submodule "project/history-simulator"]
|
||||
path = project/history-simulator
|
||||
url = https://gitee.com/lveyou/history-simulator.git
|
||||
[submodule "project/hs"]
|
||||
path = project/hs
|
||||
url = https://gitee.com/lveyou/hs.git
|
||||
[submodule "project/ds"]
|
||||
path = project/ds
|
||||
url = https://gitee.com/lveyou/ds.git
|
||||
[submodule "project/dl_chess_server"]
|
||||
path = project/dl_chess_server
|
||||
url = https://gitee.com/lveyou/dl_chess_server.git
|
||||
[submodule "project/dl_taros"]
|
||||
path = project/dl_taros
|
||||
url = https://gitee.com/lveyou/dl_taros.git
|
||||
@@ -0,0 +1,30 @@
|
||||
import lldb
|
||||
|
||||
def __lldb_init_module(debugger, internal_dict):
|
||||
# 为你的类添加摘要
|
||||
debugger.HandleCommand('type summary add -x "dl::PointU" -F custom_printers.PointU_summary')
|
||||
debugger.HandleCommand('type summary add -x "dl::Point" -F custom_printers.Point_summary')
|
||||
debugger.HandleCommand('type summary add -x "dl::Position" -F custom_printers.Position_summary')
|
||||
debugger.HandleCommand('type summary add -x "dl::Point4" -F custom_printers.Point4_summary')
|
||||
|
||||
def PointU_summary(valobj, internal_dict):
|
||||
x = valobj.GetChildMemberWithName('x').GetValueAsUnsigned()
|
||||
y = valobj.GetChildMemberWithName('y').GetValueAsUnsigned()
|
||||
return f'PointU: {x, y}'
|
||||
|
||||
def Point_summary(valobj, internal_dict):
|
||||
x = valobj.GetChildMemberWithName('x').GetValueAsUnsigned()
|
||||
y = valobj.GetChildMemberWithName('y').GetValueAsUnsigned()
|
||||
return f'Point: {x, y}'
|
||||
|
||||
def Position_summary(valobj, internal_dict):
|
||||
x = valobj.GetChildMemberWithName('x').GetValue()
|
||||
y = valobj.GetChildMemberWithName('y').GetValue()
|
||||
return f'Position: {x, y}'
|
||||
|
||||
def Point4_summary(valobj, internal_dict):
|
||||
x = valobj.GetChildMemberWithName('x').GetValue()
|
||||
y = valobj.GetChildMemberWithName('y').GetValue()
|
||||
z = valobj.GetChildMemberWithName('z').GetValue()
|
||||
w = valobj.GetChildMemberWithName('w').GetValue()
|
||||
return f'Point4: {x, y, z, w}'
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
// 使用 IntelliSense 了解相关属性。
|
||||
// 悬停以查看现有属性的描述。
|
||||
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "dl_test (Windows)",
|
||||
"type": "cppvsdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/project/dl_test/res/dl_test.exe",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/project/dl_test/res",
|
||||
"console": "externalTerminal"
|
||||
},
|
||||
{
|
||||
"name": "dl_test (Linux)",
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/out/linux/project/dl_test/bin/dl_test",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/out/linux/project/dl_test/bin"
|
||||
},
|
||||
{
|
||||
"name": "HistorySim",
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/out/linux/project/hs/bin/HistorySim",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/out/linux/project/hs/bin",
|
||||
"initCommands": [
|
||||
"command script import ${workspaceFolder}/.vscode/custom_printers.py"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "dl_console",
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/out/linux/project/dl_console/bin/dl_console",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/out/linux/project/dl_console/bin"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,396 @@
|
||||
cmake_minimum_required (VERSION 3.5)
|
||||
|
||||
# 使MT设置生效
|
||||
if (POLICY CMP0091)
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
endif (POLICY CMP0091)
|
||||
# LTO链接时优化
|
||||
if(POLICY CMP0069)
|
||||
cmake_policy(SET CMP0069 NEW)
|
||||
endif()
|
||||
|
||||
project ("dlx")
|
||||
|
||||
|
||||
set(LIBTYPE STATIC)
|
||||
message("生成目标平台:${CMAKE_SYSTEM}")
|
||||
|
||||
message("------------------dl option------------------")
|
||||
set(DL_VULKAN_DIR AUTO)
|
||||
#set(DL_VULKAN_DIR D:/VulkanSDK/1.3.268.0)
|
||||
#set(DL_VULKAN_DIR D:/VulkanSDK/1.3.250.0)
|
||||
message("------------------dl option------------------")
|
||||
|
||||
# 传递 DL_EASY 禁用绘图
|
||||
#set(DL_EASY false)
|
||||
if(NOT DEFINED DL_EASY)
|
||||
set(DL_EASY false)
|
||||
endif()
|
||||
|
||||
if(DL_EASY)
|
||||
set(DL_DISABLE_RENDER true)
|
||||
set(DL_DISABLE_AUDIO true)
|
||||
set(DL_USE_MT true)
|
||||
#set(DL_USE_MT false)
|
||||
else()
|
||||
set(DL_DISABLE_RENDER false)
|
||||
set(DL_DISABLE_AUDIO false)
|
||||
set(DL_USE_MT true)
|
||||
endif()
|
||||
|
||||
if(DL_USE_MT)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
endif()
|
||||
|
||||
# 输出使clangd可以智能提示的 compile_commands.json
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
# 关闭 /showIncludes
|
||||
# string(REPLACE "/showIncludes" "" CMAKE_DEPFILE_FLAGS_C "${CMAKE_DEPFILE_FLAGS_C}")
|
||||
# string(REPLACE "/showIncludes" "" CMAKE_DEPFILE_FLAGS_CXX "${CMAKE_DEPFILE_FLAGS_CXX}")
|
||||
endif()
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Zi")
|
||||
# release生成pdb
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF")
|
||||
endif()
|
||||
|
||||
# 使用C++最新标准
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
if (APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -lc++abi")
|
||||
endif()
|
||||
|
||||
# JoltPhysic 安卓编译需要
|
||||
set(CPP_RTTI_ENABLED ON)
|
||||
# 预编译Jolt需要此定义
|
||||
set(CPP_EXCEPTIONS_ENABLED ON)
|
||||
set(CMAKE_DISABLE_PRECOMPILE_HEADERS ON)
|
||||
# Jolt在linux使用了LTO,需要全局开启
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
|
||||
|
||||
# 暂时不太清楚以下哪个变量导致jolt安卓异常
|
||||
set(USE_SSE4_1 OFF CACHE BOOL "" FORCE)
|
||||
set(USE_SSE4_2 OFF CACHE BOOL "" FORCE)
|
||||
set(USE_AVX OFF CACHE BOOL "" FORCE)
|
||||
set(USE_AVX2 OFF CACHE BOOL "" FORCE)
|
||||
set(USE_AVX512 OFF CACHE BOOL "" FORCE)
|
||||
set(USE_LZCNT OFF CACHE BOOL "" FORCE)
|
||||
set(USE_TZCNT OFF CACHE BOOL "" FORCE)
|
||||
set(USE_F16C OFF CACHE BOOL "" FORCE)
|
||||
set(USE_FMADD OFF CACHE BOOL "" FORCE)
|
||||
|
||||
#set(FLOATING_POINT_EXCEPTIONS_ENABLED OFF CACHE BOOL "" FORCE)
|
||||
|
||||
#set(CROSS_COMPILE_ARM OFF CACHE BOOL "" FORCE)
|
||||
|
||||
message("------------------第三方库option------------------")
|
||||
option(BUILD_DOCS "关闭第三方库的文档生成" OFF)
|
||||
option(INSTALL_MANPAGES "解决flac报错" OFF)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Android")
|
||||
option(ALSOFT_INSTALL "解决安卓openal报错" OFF)
|
||||
endif()
|
||||
option(FT_DISABLE_ZLIB "freetype禁用内部zlib" ON)
|
||||
option(FT_REQUIRE_ZLIB "freetype查找外部zlib" ON)
|
||||
option(CURL_USE_LIBPSL "不使用libpsl" OFF)
|
||||
option(CURL_USE_OPENSSL "使用openssl" ON)
|
||||
|
||||
# 关闭第三方库的额外生成
|
||||
option(ALSOFT_UTILS "Build utility programs" OFF)
|
||||
option(ALSOFT_NO_CONFIG_UTIL "Disable building the alsoft-config utility" ON)
|
||||
option(ALSOFT_EXAMPLES "Build example programs" OFF)
|
||||
|
||||
option(RTMIDI_BUILD_TESTING "Build test programs" OFF)
|
||||
|
||||
option(WEBP_BUILD_ANIM_UTILS "Build animation utilities." OFF)
|
||||
option(WEBP_BUILD_CWEBP "Build the cwebp command line tool." OFF)
|
||||
option(WEBP_BUILD_DWEBP "Build the dwebp command line tool." OFF)
|
||||
option(WEBP_BUILD_GIF2WEBP "Build the gif2webp conversion tool." OFF)
|
||||
option(WEBP_BUILD_IMG2WEBP "Build the img2webp animation tool." OFF)
|
||||
option(WEBP_BUILD_VWEBP "Build the vwebp viewer tool." OFF)
|
||||
option(WEBP_BUILD_WEBPINFO "Build the webpinfo command line tool." OFF)
|
||||
option(WEBP_BUILD_LIBWEBPMUX "Build the libwebpmux library." OFF)
|
||||
option(WEBP_BUILD_WEBPMUX "Build the webpmux command line tool." OFF)
|
||||
option(WEBP_BUILD_EXTRAS "Build extras." OFF)
|
||||
option(WEBP_BUILD_WEBP_JS "Emscripten build of webp.js." OFF)
|
||||
|
||||
option(BUILD_PROGRAMS "Build and install programs" OFF)
|
||||
option(BUILD_EXAMPLES "Build and install examples" OFF)
|
||||
option(BUILD_TESTING "Build tests" OFF)
|
||||
option(BUILD_DOCS "Build and install doxygen documents" OFF)
|
||||
option(INSTALL_MANPAGES "Install MAN pages" OFF)
|
||||
option(INSTALL_PKGCONFIG_MODULES "Install PkgConfig modules" OFF)
|
||||
option(INSTALL_CMAKE_CONFIG_MODULE "Install CMake package-config module" OFF)
|
||||
|
||||
option(INFOWARE_EXAMPLES "Add infoware examples to the build." OFF)
|
||||
option(INFOWARE_TESTS "Input tests for infoware." OFF)
|
||||
|
||||
option(ZLIB_BUILD_EXAMPLES "Enable Zlib Examples" OFF)
|
||||
|
||||
option(TINYGLTF_BUILD_LOADER_EXAMPLE "Build loader_example(load glTF and dump infos)" OFF)
|
||||
option(TINYGLTF_BUILD_GL_EXAMPLES "Build GL exampels(requires glfw, OpenGL, etc)" OFF)
|
||||
option(TINYGLTF_BUILD_TESTS "Build unit tests" OFF)
|
||||
option(TINYGLTF_INSTALL "Install tinygltf files during install step. Usually set to OFF if you include tinygltf through add_subdirectory()" ON)
|
||||
option(TINYGLTF_INSTALL_VENDOR "Install vendored nlohmann/json and nothings/stb headers" OFF)
|
||||
|
||||
option(LUNASVG_BUILD_EXAMPLES "Build examples" OFF)
|
||||
|
||||
option(BUILD_CURL_EXE "Build curl executable" OFF)
|
||||
option(CURL_DISABLE_INSTALL "Disable installation targets" OFF)
|
||||
|
||||
# mimalloc 只使用静态库;强制关闭共享库/重定向,避免生成 mimalloc-debug.dll 与 mimalloc-redirect.lib
|
||||
set(MI_BUILD_SHARED OFF CACHE BOOL "Build shared library" FORCE)
|
||||
set(MI_BUILD_STATIC ON CACHE BOOL "Build static library" FORCE)
|
||||
set(MI_BUILD_OBJECT OFF CACHE BOOL "Build object library" FORCE)
|
||||
set(MI_BUILD_TESTS OFF CACHE BOOL "Build test executables" FORCE)
|
||||
set(MI_WIN_REDIRECT OFF CACHE BOOL "Use redirection module on Windows" FORCE)
|
||||
|
||||
message("------------------解析第三方库------------------")
|
||||
message("------------------lz4 压缩库-------------------")
|
||||
add_subdirectory ("third/lz4")
|
||||
message("------------------zlib 压缩库---------")
|
||||
add_subdirectory ("third/zlib")
|
||||
message("------------------fmt 文本格式化库--------------")
|
||||
option(FMT_INSTALL "开启fmt的安装" ON)
|
||||
add_subdirectory ("third/fmt")
|
||||
|
||||
message("------------------lunasvg svg格式库-----------")
|
||||
add_subdirectory ("third/lunasvg")
|
||||
message("------------------libwebp webp格式库-----------")
|
||||
add_subdirectory ("third/libwebp")
|
||||
message("------------------OpenXLSX xlsx格式库-----------")
|
||||
add_subdirectory ("third/OpenXLSX")
|
||||
|
||||
if (NOT CMAKE_SYSTEM_NAME MATCHES "Android"
|
||||
AND NOT DL_DISABLE_RENDER)
|
||||
message("------------------glfw 窗口库------------------")
|
||||
add_subdirectory ("third/glfw")
|
||||
endif()
|
||||
|
||||
if(NOT DL_DISABLE_RENDER)
|
||||
message("------------------freetype 字体解析库-----------")
|
||||
add_subdirectory ("third/freetype")
|
||||
message("------------------tinygltf gltf格式库-----------")
|
||||
add_subdirectory ("third/tinygltf")
|
||||
endif()
|
||||
|
||||
message("------------------ogg vorbis 音频格式库-----------")
|
||||
add_subdirectory ("third/ogg")
|
||||
set (OGG_LIBRARY "third/ogg")
|
||||
set (OGG_INCLUDE_DIR "third/ogg")
|
||||
add_subdirectory ("third/vorbis")
|
||||
message("------------------flac 音频格式库-----------")
|
||||
add_subdirectory ("third/flac")
|
||||
message("------------------openal-soft 音频库-----------")
|
||||
if (NOT CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
# Mac系统(Darwin)下,先修复openal-soft的dl依赖问题
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
# 定义CMAKE_DL_LIBS(Mac下指向系统dl库),避免openal-soft找不到dl目标
|
||||
set(CMAKE_DL_LIBS "-ldl")
|
||||
# 强制跳过openal-soft的export/install(核心报错点)
|
||||
set(OPENAL_BUILD_INSTALL OFF CACHE BOOL "Disable OpenAL install" FORCE)
|
||||
set(OPENAL_BUILD_EXAMPLES OFF CACHE BOOL "Disable OpenAL examples" FORCE)
|
||||
endif()
|
||||
# 再添加openal-soft子目录
|
||||
add_subdirectory ("third/openal-soft")
|
||||
endif()
|
||||
message("------------------rtmidi midi库-----------")
|
||||
if (NOT CMAKE_SYSTEM_NAME MATCHES "Android")
|
||||
add_subdirectory ("third/rtmidi")
|
||||
endif()
|
||||
|
||||
if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
message("------------------iconv 文本编码转换库-----------")
|
||||
#add_subdirectory ("third/libiconv")
|
||||
endif()
|
||||
message("------------------angelscript 脚本语言库-----------")
|
||||
add_subdirectory ("third/angelscript/angelscript/projects/cmake")
|
||||
message("------------------lua 脚本语言库-----------")
|
||||
add_subdirectory ("third/lua")
|
||||
add_subdirectory ("third/LuaBridge3")
|
||||
message("------------------infoware 硬件信息库-----------")
|
||||
if (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "AMD64")
|
||||
set(INFOWARE_PCI_IDS_PATH ${CMAKE_SOURCE_DIR}/third/infoware/pci.ids CACHE FILEPATH "使用本地piiids" FORCE)
|
||||
add_subdirectory ("third/infoware")
|
||||
endif()
|
||||
|
||||
message("------------------wcwidth 字符宽度检测-----------")
|
||||
add_subdirectory ("third/wcwidth")
|
||||
message("------------------simde 向量化计算-----------")
|
||||
add_subdirectory ("third/simde")
|
||||
message("------------------magic_enum 枚举静态反射-----------")
|
||||
add_subdirectory ("third/magic_enum")
|
||||
message("------------------cpp-subprocess 进程库-----------")
|
||||
add_subdirectory ("third/cpp-subprocess")
|
||||
message("------------------ktx ktx格式库-----------")
|
||||
add_subdirectory ("third/ktx")
|
||||
message("------------------JoltPhysics 物理引擎-----------")
|
||||
add_subdirectory ("third/JoltPhysics/Build")
|
||||
message("------------------mimalloc 内存分配-----------")
|
||||
add_subdirectory ("third/mimalloc")
|
||||
message("------------------GoogleTest 单元测试库-----------")
|
||||
add_subdirectory ("third/googletest")
|
||||
message("------------------curl http协议库-----------")
|
||||
set(OPENSSL_ROOT_DIR ${CMAKE_SOURCE_DIR}/third/openssl)
|
||||
|
||||
# 先锁死 libcurl 编译选项
|
||||
set(CURL_USE_OPENSSL ON CACHE BOOL "" FORCE)
|
||||
set(CURL_USE_SCHANNEL OFF CACHE BOOL "" FORCE)
|
||||
set(CURL_USE_LIBPSL OFF CACHE BOOL "" FORCE)
|
||||
set(CURL_USE_LIBSSH2 OFF CACHE BOOL "" FORCE)
|
||||
set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
|
||||
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||
|
||||
if(WIN32)
|
||||
# 1. 自动判断架构 x64/x86
|
||||
if(CMAKE_CL_64)
|
||||
set(ARCH x64)
|
||||
else()
|
||||
set(ARCH x86)
|
||||
endif()
|
||||
|
||||
# 2. 自动判断运行库 MT/MD
|
||||
if(DL_USE_MT)
|
||||
set(RT MT)
|
||||
else()
|
||||
set(RT MD)
|
||||
endif()
|
||||
|
||||
# 3. 自动路径
|
||||
set(OPENSSL_INCLUDE_DIR ${OPENSSL_ROOT_DIR}/include)
|
||||
set(OPENSSL_LIB_DIR ${OPENSSL_ROOT_DIR}/${ARCH}/${RT})
|
||||
|
||||
# 4. 精确 lib 文件
|
||||
set(OPENSSL_SSL_LIBRARY ${OPENSSL_LIB_DIR}/libssl_static.lib)
|
||||
set(OPENSSL_CRYPTO_LIBRARY ${OPENSSL_LIB_DIR}/libcrypto_static.lib)
|
||||
|
||||
# ==============================
|
||||
# 关键:创建 OpenSSL::SSL OpenSSL::Crypto 目标
|
||||
# ==============================
|
||||
if(NOT TARGET OpenSSL::SSL)
|
||||
add_library(OpenSSL::SSL UNKNOWN IMPORTED)
|
||||
set_target_properties(OpenSSL::SSL PROPERTIES
|
||||
IMPORTED_LOCATION ${OPENSSL_SSL_LIBRARY}
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${OPENSSL_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
if(NOT TARGET OpenSSL::Crypto)
|
||||
add_library(OpenSSL::Crypto UNKNOWN IMPORTED)
|
||||
set_target_properties(OpenSSL::Crypto PROPERTIES
|
||||
IMPORTED_LOCATION ${OPENSSL_CRYPTO_LIBRARY}
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${OPENSSL_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
# 强制写入缓存
|
||||
set(OPENSSL_FOUND TRUE CACHE BOOL "" FORCE)
|
||||
set(OPENSSL_INCLUDE_DIR ${OPENSSL_INCLUDE_DIR} CACHE PATH "" FORCE)
|
||||
set(OPENSSL_SSL_LIBRARY ${OPENSSL_SSL_LIBRARY} CACHE FILEPATH "" FORCE)
|
||||
set(OPENSSL_CRYPTO_LIBRARY ${OPENSSL_CRYPTO_LIBRARY} CACHE FILEPATH "" FORCE)
|
||||
|
||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||
link_directories(${OPENSSL_LIB_DIR})
|
||||
endif()
|
||||
|
||||
# Linux / Mac
|
||||
if(UNIX AND NOT APPLE AND NOT ANDROID)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(OPENSSL_ROOT_DIR "/opt/homebrew/opt/openssl@3")
|
||||
find_package(OpenSSL REQUIRED)
|
||||
endif()
|
||||
|
||||
# Android
|
||||
if(ANDROID)
|
||||
set(OPENSSL_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/third/openssl/android/${ANDROID_ABI}/include)
|
||||
set(OPENSSL_SSL_LIBRARY ${CMAKE_SOURCE_DIR}/third/openssl/android/${ANDROID_ABI}/lib/libssl.a)
|
||||
set(OPENSSL_CRYPTO_LIBRARY ${CMAKE_SOURCE_DIR}/third/openssl/android/${ANDROID_ABI}/lib/libcrypto.a)
|
||||
add_library(OpenSSL::SSL UNKNOWN IMPORTED)
|
||||
set_target_properties(OpenSSL::SSL PROPERTIES IMPORTED_LOCATION ${OPENSSL_SSL_LIBRARY} INTERFACE_INCLUDE_DIRECTORIES ${OPENSSL_INCLUDE_DIR})
|
||||
add_library(OpenSSL::Crypto UNKNOWN IMPORTED)
|
||||
set_target_properties(OpenSSL::Crypto PROPERTIES IMPORTED_LOCATION ${OPENSSL_CRYPTO_LIBRARY} INTERFACE_INCLUDE_DIRECTORIES ${OPENSSL_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
# 最后编译 libcurl
|
||||
add_subdirectory(third/libcurl)
|
||||
|
||||
message("------------------其余库以其他形式链接----------")
|
||||
message("------------------nlohmann-json json库---------")
|
||||
message("------------------stb_image 图像解析库----------")
|
||||
message("------------------qrcodegen 二维码生成库-----------")
|
||||
message("------------------vld 内存泄漏检测库----------")
|
||||
message("------------------asio 网络库-----------")
|
||||
message("------------------tinyxml2 xml格式库-----------")
|
||||
message("------------------openssl 库-----------")
|
||||
message("------------------curl 库-----------")
|
||||
message("------------------sqlite 数据库-----------")
|
||||
message("------------------tinyobjloader obj格式库-----------")
|
||||
message("------------------mp3 音频格式库-----------")
|
||||
message("------------------ktx 解析库-----------")
|
||||
message("------------------CrashRpt 崩溃采集库-----------")
|
||||
|
||||
|
||||
message("------------------解析dl-----------------------")
|
||||
add_subdirectory ("dl")
|
||||
if(NOT DL_DISABLE_RENDER)
|
||||
message("------------------解析dl_test-----------------------")
|
||||
add_subdirectory ("project/dl_test")
|
||||
|
||||
message("------------------解析dl_unit_test(此项目由ai生成)-----------")
|
||||
add_subdirectory ("project/dl_unit_test")
|
||||
|
||||
if(NOT CMAKE_SYSTEM_NAME MATCHES "Android")
|
||||
message("------------------解析dl_console-----------------------")
|
||||
add_subdirectory ("project/dl_console")
|
||||
endif()
|
||||
|
||||
if(EXISTS ${CMAKE_SOURCE_DIR}/project/dl_editor/CMakeLists.txt)
|
||||
message("------------------解析dl_editor-----------------------")
|
||||
add_subdirectory ("project/dl_editor")
|
||||
endif()
|
||||
if(EXISTS ${CMAKE_SOURCE_DIR}/project/dl_midi/CMakeLists.txt)
|
||||
message("------------------解析dl_midi-----------------------")
|
||||
add_subdirectory ("project/dl_midi")
|
||||
endif()
|
||||
if(EXISTS ${CMAKE_SOURCE_DIR}/project/dl_chess/CMakeLists.txt)
|
||||
message("------------------解析dl_chess-----------------------")
|
||||
add_subdirectory ("project/dl_chess")
|
||||
endif()
|
||||
if(EXISTS ${CMAKE_SOURCE_DIR}/project/dl_snake/CMakeLists.txt)
|
||||
message("------------------解析dl_snake-----------------------")
|
||||
add_subdirectory ("project/dl_snake")
|
||||
endif()
|
||||
if(EXISTS ${CMAKE_SOURCE_DIR}/project/hs/CMakeLists.txt)
|
||||
message("------------------解析HistorySim-----------------------")
|
||||
add_subdirectory ("project/hs")
|
||||
endif()
|
||||
if(EXISTS ${CMAKE_SOURCE_DIR}/project/ds/CMakeLists.txt)
|
||||
message("------------------解析DreamSandbox-----------------------")
|
||||
add_subdirectory ("project/ds")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# 无界面程序
|
||||
|
||||
if(EXISTS ${CMAKE_SOURCE_DIR}/project/dl_config/CMakeLists.txt AND
|
||||
NOT CMAKE_SYSTEM_NAME MATCHES "Android")
|
||||
message("------------------解析dl_config-----------------------")
|
||||
add_subdirectory ("project/dl_config")
|
||||
endif()
|
||||
|
||||
if(EXISTS ${CMAKE_SOURCE_DIR}/project/dl_chess_server/CMakeLists.txt)
|
||||
message("------------------解析dl_chess_server-----------------------")
|
||||
add_subdirectory ("project/dl_chess_server")
|
||||
endif()
|
||||
|
||||
message("若解析Cmake失败,有以下几个常见原因:")
|
||||
message("1.未安装VulkanSDK")
|
||||
message("CMake生成完成后,可选择dl_test项目调试")
|
||||
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"version": 3,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "windows-base",
|
||||
"hidden": true,
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
||||
"installDir": "${sourceDir}/out/install/${presetName}",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "cl.exe",
|
||||
"CMAKE_CXX_COMPILER": "cl.exe",
|
||||
"ODE_WITH_DEMOS": false
|
||||
},
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x64-debug",
|
||||
"displayName": "A.Windows x64 Debug",
|
||||
"inherits": "windows-base",
|
||||
"architecture": {
|
||||
"value": "x64",
|
||||
"strategy": "external"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x64-release",
|
||||
"displayName": "A.Windows x64 Release",
|
||||
"inherits": "x64-debug",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x86-debug",
|
||||
"displayName": "A.Windows x86 Debug",
|
||||
"inherits": "windows-base",
|
||||
"architecture": {
|
||||
"value": "x86",
|
||||
"strategy": "external"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x86-release",
|
||||
"displayName": "A.Windows x86 Release",
|
||||
"inherits": "x86-debug",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux",
|
||||
"displayName": "B.Clang x64 Debug",
|
||||
"description": "正在使用编译器: C = /usr/bin/clang, CXX = /usr/bin/clang++",
|
||||
"binaryDir": "${sourceDir}/out/${presetName}",
|
||||
"cacheVariables": {
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}",
|
||||
"CMAKE_C_COMPILER": "/usr/bin/clang",
|
||||
"CMAKE_CXX_COMPILER": "/usr/bin/clang++",
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-release",
|
||||
"displayName": "B.Clang x64 Release",
|
||||
"description": "正在使用编译器: C = /usr/bin/clang, CXX = /usr/bin/clang++",
|
||||
"binaryDir": "${sourceDir}/out/${presetName}",
|
||||
"cacheVariables": {
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}",
|
||||
"CMAKE_C_COMPILER": "/usr/bin/clang",
|
||||
"CMAKE_CXX_COMPILER": "/usr/bin/clang++",
|
||||
"CMAKE_BUILD_TYPE": "Release",
|
||||
"CMAKE_C_FLAGS_RELEASE": "-O3 -DNDEBUG",
|
||||
"CMAKE_CXX_FLAGS_RELEASE": "-O3 -DNDEBUG",
|
||||
"CMAKE_EXE_LINKER_FLAGS_RELEASE": "-s"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,304 +1,21 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license document.
|
||||
|
||||
4. Combined Works.
|
||||
You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
“This License” refers to version 3 of the GNU General Public License.
|
||||
|
||||
“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
|
||||
|
||||
“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations.
|
||||
|
||||
To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work.
|
||||
|
||||
A “covered work” means either the unmodified Program or a work based on the Program.
|
||||
|
||||
To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.
|
||||
|
||||
To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work.
|
||||
|
||||
A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.
|
||||
|
||||
The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”.
|
||||
|
||||
c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.
|
||||
|
||||
A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.
|
||||
|
||||
“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.
|
||||
|
||||
An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”.
|
||||
|
||||
A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.
|
||||
|
||||
A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.
|
||||
|
||||
dl
|
||||
Copyright (C) 2026 lveyou
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:
|
||||
|
||||
dl Copyright (C) 2026 lveyou
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 略游
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
# dl engine
|
||||
|
||||
## Language / 语言
|
||||
- [English](README.EN.md)
|
||||
- [中文](README.md)
|
||||
|
||||
## Framework Introduction
|
||||
dl (drawing library) is a development framework based on C++ language, integrating various C/C++ open source libraries.
|
||||
|
||||
## Core Design Principles
|
||||
1. Use the latest C++ standards
|
||||
2. Non-commercial, free
|
||||
3. Integrate various open source libraries for easy use
|
||||
4. Suitable for developing various native applications, biased towards game engine scenarios
|
||||
5. Interface uniformity, cross-platform compatibility
|
||||
|
||||
#### Supported Platforms
|
||||
|
||||
| Platform | Windows10 | Linux | Android | MacOS | IOS |
|
||||
|----------|-----------|-------|---------|-------|-----|
|
||||
| Compilation | OK | OK | OK | OK | TODO |
|
||||
| Drawing | OK | OK | OK | OK | TODO |
|
||||
| File | OK | OK | OK | OK | TODO |
|
||||
| Audio | OK | OK | OK | OK | TODO |
|
||||
| OPENSSL | OK | OK | TODO | OK | TODO |
|
||||
| Input | OK | OK | Partial | OK | TODO |
|
||||
| Network | OK | OK | OK | OK | TODO |
|
||||
|
||||
## Directory Structure
|
||||
```text
|
||||
├── build/ # Build-related files and scripts
|
||||
├── dl/ # Core engine code
|
||||
│ ├── base/ # Basic data structures and tools
|
||||
│ ├── io/ # Input/output functionality
|
||||
│ ├── math/ # Math library
|
||||
│ ├── memory/ # Memory management
|
||||
│ ├── misc/ # Miscellaneous functionality
|
||||
│ ├── render/ # Rendering system
|
||||
│ ├── script/ # Script support
|
||||
│ ├── system/ # System functionality
|
||||
│ ├── tool/ # Tool classes
|
||||
│ ├── ui/ # UI system
|
||||
│ └── vk/ # Vulkan rendering
|
||||
├── document/ # Documentation
|
||||
├── project/ # Project examples and tests
|
||||
├── redist/ # Runtime libraries
|
||||
├── res/ # Required resource files
|
||||
├── shader/ # Shader code
|
||||
└── third/ # Third-party libraries
|
||||
```
|
||||
## Notes
|
||||
:heavy_exclamation_mark: `Do not check the option to pull submodules when cloning the repository`
|
||||
|
||||
:heavy_exclamation_mark: `No release version yet, non-commercial, welcome to join`
|
||||
|
||||
## Third-party Library List
|
||||
| Function Category | Library | Description |
|
||||
| :---------------- | :------ | :---------- |
|
||||
| 📜 Script Related | angelscript | C++-like strongly typed scripting language (no longer used) |
|
||||
| 📜 Script Related | lua | Lua scripting language |
|
||||
| 📜 Script Related | LuaBridge3 | Lua binding library |
|
||||
| 🌐 Network Communication | asio | Network library, may enter standard library in the future |
|
||||
| 🌐 Network Communication | curl | Communication protocol library (supports https with OpenSSL) |
|
||||
| 🌐 Network Communication | openssl | Encryption library |
|
||||
| 🎵 Audio Processing | flac | FLAC audio format library |
|
||||
| 🎵 Audio Processing | ogg | OGG audio format library |
|
||||
| 🎵 Audio Processing | openal-soft | OpenAL audio library |
|
||||
| 🎵 Audio Processing | vorbis | OGG format related library |
|
||||
| 🎵 Audio Processing | minimp3 | MP3 format library |
|
||||
| 🎵 Audio Processing | midifile | MIDI library (not yet used) |
|
||||
| 🎵 Audio Processing | rtmidi | MIDI library |
|
||||
| 🎨 Graphics/Image | freetype | Font parsing library |
|
||||
| 🎨 Graphics/Image | libwebp | WebP format library |
|
||||
| 🎨 Graphics/Image | lunasvg | SVG format library |
|
||||
| 🎨 Graphics/Image | stb_image | Common image format parsing library |
|
||||
| 🎨 Graphics/Image | tinygltf | GLTF format library |
|
||||
| 🎨 Graphics/Image | tinyobjloader | OBJ format parsing library |
|
||||
| 🚜 Physics Engine | box2d | 2D rigid body physics engine (not yet integrated, planned) |
|
||||
| 🚜 Physics Engine | JoltPhysics | 3D physics engine |
|
||||
| 📊 Data Parsing | json | JSON parsing library |
|
||||
| 📊 Data Parsing | libiconv | Character encoding conversion library |
|
||||
| 📊 Data Parsing | OpenXLSX | XLSX format parsing library |
|
||||
| 📊 Data Parsing | tinyxml2 | XML format parsing library |
|
||||
| 📊 Data Parsing | uchardet | Character set detection (not yet used) |
|
||||
| 🗜️ Compression | lz4 | LZ4 compression algorithm library |
|
||||
| 🗜️ Compression | zlib | Compression format library |
|
||||
| 🛠️ Development & Debugging | CrashRpt | Crash collection tool (Windows only) |
|
||||
| 🛠️ Development & Debugging | googletest | Unit test library |
|
||||
| 🛠️ Development & Debugging | infoware | Hardware information retrieval |
|
||||
| 🛠️ Development & Debugging | mimalloc | Memory allocator |
|
||||
| 🛠️ Development & Debugging | vld | Memory leak detection (Windows only) |
|
||||
| 🔧 General Tools | fmt | Format library, similar to std::format |
|
||||
| 🔧 General Tools | glfw | Window library (doesn't support Android, needs separate handling) |
|
||||
| 🔧 General Tools | qrcodegen | QR code generation library |
|
||||
| 🔧 General Tools | simde | SIMD instruction library |
|
||||
| 🔧 General Tools | sqlite | SQLite library |
|
||||
| 🔧 General Tools | wcwidth | Character width detection |
|
||||
| 🔧 General Tools | cpp-subprocess | Subprocess library |
|
||||
| 🔧 General Tools | ktx | KTX texture compression format library |
|
||||
| 🔧 General Tools | magic_enum | Enum static reflection |
|
||||
| 📋 Unused/Planned | better-enums | Better enums (not yet used) |
|
||||
| 📋 Unused/Planned | BigNumber | Big number class (not yet used) |
|
||||
|
||||
## Installation Guide
|
||||
|
||||
### Windows
|
||||
1. Install VS2022+ (including C++ environment, CMake tools)
|
||||
2. Install Vulkan SDK: https://vulkan.lunarg.com/sdk/home
|
||||
3. Open the project folder with VS, select the root CMakeLists.txt
|
||||
4. Select A.Windows x64 Debug at the top, then compile and execute dl_test.exe
|
||||
|
||||
### Linux (Ubuntu)
|
||||
1. Download VS Code: https://code.visualstudio.com/#alt-downloads
|
||||
2. Install VS Code, Git, Vulkan SDK, GLFW, etc.
|
||||
|
||||
```
|
||||
// To improve download speed, please set up a domestic mirror in "Software & Updates" first
|
||||
sudo apt update
|
||||
//---------------------Install VS Code-----------------------
|
||||
//1. Download and install from official website
|
||||
sudo dpkg -i *.deb // Switch to the VS Code installation package directory to install
|
||||
//2. Search and install from store
|
||||
//---------------------Install CMake, Clang, etc.--------------------------
|
||||
sudo apt install cmake
|
||||
sudo apt install clang
|
||||
sudo apt install xorg-dev
|
||||
//---------------------Install Vulkan SDK-------------------
|
||||
wget -qO- https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo tee /etc/apt/trusted.gpg.d/lunarg.asc
|
||||
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-1.3.268-jammy.list https://packages.lunarg.com/vulkan/1.3.268/lunarg-vulkan-1.3.268-jammy.list
|
||||
sudo apt update
|
||||
sudo apt install vulkan-sdk
|
||||
```
|
||||
|
||||
3. Open the project folder, select the root CMakeLists.txt to generate
|
||||
4. Install VS Code related plugins, CMake, C++, etc.
|
||||
5. Select B.Linux Clang at the bottom to compile and execute dl_test
|
||||
|
||||
### Linux (CentOS)
|
||||
|
||||
```
|
||||
# Install clang
|
||||
sudo dnf install clang clang-tools-extra -y
|
||||
# Install cmake
|
||||
sudo dnf install cmake -y
|
||||
# Install curl
|
||||
sudo dnf install libcurl-devel -y
|
||||
# Clone repository
|
||||
cd /opt
|
||||
git clone https://gitee.com/lveyou/dl.git
|
||||
# Parse dl
|
||||
mkdir -p out
|
||||
cd out
|
||||
cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DODE_WITH_DEMOS=false -DDL_EASY=true ..
|
||||
# Compile
|
||||
make -j4
|
||||
|
||||
# Clone subproject
|
||||
git submodule update --init --recursive project/dl_chess_server/
|
||||
```
|
||||
|
||||
|
||||
### Android
|
||||
1. Install Android Studio
|
||||
2. Install Vulkan SDK: https://vulkan.lunarg.com/sdk/home
|
||||
3. Open the build/android directory with Android Studio to compile and execute
|
||||
|
||||
### MacOS
|
||||
1. Install CMake
|
||||
```bash
|
||||
# Install brew, skip if already installed
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
brew update
|
||||
brew install cmake
|
||||
```
|
||||
2. Install Vulkan SDK: https://vulkan.lunarg.com/sdk/home
|
||||
3. Compile, execute in the dl root directory
|
||||
```
|
||||
mkdir -p out
|
||||
cd out
|
||||
cmake ..
|
||||
make -j4
|
||||
```
|
||||
|
||||
## Usage Instructions
|
||||
|
||||
Compile dl_test to view test programs, or directly download the preview release version
|
||||
|
||||
## Discussion Group
|
||||
|
||||
QQ Group: 512001256
|
||||
@@ -1,2 +1,189 @@
|
||||
# dl
|
||||
# dl engine
|
||||
|
||||
## 语言 / Language
|
||||
- [中文](README.md)
|
||||
- [English](README.EN.md)
|
||||
|
||||
## 框架简介
|
||||
dl(drawing library)是以 C++ 语言为基础,集成各类 C/C++ 开源库组成的开发框架。
|
||||
|
||||
## 核心设计原则
|
||||
1. 使用最新的 C++ 标准
|
||||
2. 自身非商业化,免费
|
||||
3. 集成各类开源库,便于使用
|
||||
4. 适合开发各类原生应用,偏向于游戏引擎场景
|
||||
5. 接口统一性,跨平台兼容
|
||||
|
||||
#### 支持平台
|
||||
|
||||
| 平台 | Windows10 | Linux | Android | MacOS | IOS |
|
||||
|------|------------|--------------|--------|------|------|
|
||||
| 编译 | OK | OK | OK | OK | TODO |
|
||||
| 绘图 | OK | OK | OK | OK | TODO |
|
||||
| 文件 | OK | OK | OK | OK | TODO |
|
||||
| 音效 | OK | OK | OK | OK | TODO |
|
||||
| OPENSSL | OK | OK | OK | OK | TODO |
|
||||
| 输入 | OK | OK | 部分 | OK | TODO |
|
||||
| 网络 | OK | OK | OK | OK | TODO |
|
||||
|
||||
## 目录结构
|
||||
```text
|
||||
├── build/ # 构建相关文件和脚本
|
||||
├── dl/ # 核心引擎代码
|
||||
│ ├── base/ # 基础数据结构和工具
|
||||
│ ├── io/ # 输入输出功能
|
||||
│ ├── math/ # 数学库
|
||||
│ ├── memory/ # 内存管理
|
||||
│ ├── misc/ # 杂项功能
|
||||
│ ├── render/ # 渲染系统
|
||||
│ ├── script/ # 脚本支持
|
||||
│ ├── system/ # 系统功能
|
||||
│ ├── tool/ # 工具类
|
||||
│ ├── ui/ # UI系统
|
||||
│ └── vk/ # Vulkan渲染
|
||||
├── document/ # 文档
|
||||
├── project/ # 项目示例和测试
|
||||
├── redist/ # 运行库
|
||||
├── res/ # 必要资源文件
|
||||
├── shader/ # 着色器代码
|
||||
└── third/ # 第三方库
|
||||
```
|
||||
## 注意事项
|
||||
:heavy_exclamation_mark: `拉取仓库时,请勿勾选拉取子模块`
|
||||
|
||||
:heavy_exclamation_mark: `暂无发布版本,非商业化,欢迎加入`
|
||||
|
||||
## 第三方库列表
|
||||
| 功能分类 | 库名 | 说明 |
|
||||
| :------------- | :------------ | :------------------------------------- |
|
||||
| 📜 脚本相关 | angelscript | 类C++语法的强类型脚本语言(不再使用) |
|
||||
| 📜 脚本相关 | lua | lua脚本语言 |
|
||||
| 📜 脚本相关 | LuaBridge3 | lua绑定库 |
|
||||
| 🌐 网络通信 | asio | 网络库,将来或许会进标准库 |
|
||||
| 🌐 网络通信 | curl | 通信协议库(配合OpenSSL可支持https) |
|
||||
| 🌐 网络通信 | openssl | 加密库 |
|
||||
| 🎵 音频处理 | flac | flac音频格式库 |
|
||||
| 🎵 音频处理 | ogg | ogg音频格式库 |
|
||||
| 🎵 音频处理 | openal-soft | OpenAL音频库 |
|
||||
| 🎵 音频处理 | vorbis | ogg格式相关库 |
|
||||
| 🎵 音频处理 | minimp3 | mp3格式库 |
|
||||
| 🎵 音频处理 | midifile | midi库(暂未使用) |
|
||||
| 🎵 音频处理 | rtmidi | midi库 |
|
||||
| 🎨 图形/图像 | freetype | 字体解析库 |
|
||||
| 🎨 图形/图像 | libwebp | webp格式库 |
|
||||
| 🎨 图形/图像 | lunasvg | svg格式库 |
|
||||
| 🎨 图形/图像 | stb_image | 常用图像格式解析库 |
|
||||
| 🎨 图形/图像 | tinygltf | gltf格式库 |
|
||||
| 🎨 图形/图像 | tinyobjloader | obj格式解析库 |
|
||||
| 🚜 物理引擎 | box2d | 2D刚体物理引擎(暂未集成,后续计划) |
|
||||
| 🚜 物理引擎 | JoltPhysics | 3D物理引擎 |
|
||||
| 📊 数据解析 | json | json解析库 |
|
||||
| 📊 数据解析 | libiconv | 字符编码转换库 |
|
||||
| 📊 数据解析 | OpenXLSX | xlsx格式解析库 |
|
||||
| 📊 数据解析 | tinyxml2 | xml格式解析库 |
|
||||
| 📊 数据解析 | uchardet | 字符集检测(暂未使用) |
|
||||
| 🗜️ 压缩库 | lz4 | lz4压缩算法库 |
|
||||
| 🗜️ 压缩库 | zlib | 压缩格式库 |
|
||||
| 🛠️ 开发调试 | CrashRpt | 崩溃采集工具(只支持windows) |
|
||||
| 🛠️ 开发调试 | googletest | 单元测试库 |
|
||||
| 🛠️ 开发调试 | infoware | 硬件信息获取 |
|
||||
| 🛠️ 开发调试 | mimalloc | 内存分配器 |
|
||||
| 🛠️ 开发调试 | vld | 内存泄露检测(只支持windows) |
|
||||
| 🔧 通用工具 | fmt | format库,与std::format类似 |
|
||||
| 🔧 通用工具 | glfw | 窗口库 |
|
||||
| 🔧 通用工具 | qrcodegen | 二维码生成库 |
|
||||
| 🔧 通用工具 | simde | simd流指令库 |
|
||||
| 🔧 通用工具 | sqlite | sqlite库 |
|
||||
| 🔧 通用工具 | wcwidth | 字符宽度检测 |
|
||||
| 🔧 通用工具 | cpp-subprocess | 子进程库 |
|
||||
| 🔧 通用工具 | ktx | ktx纹理压缩格式库 |
|
||||
| 🔧 通用工具 | magic_enum | 枚举静态反射 |
|
||||
| 📋 未使用/规划 | BigNumber | 大数类(暂未使用) |
|
||||
|
||||
## 安装教程
|
||||
|
||||
### Windows
|
||||
1. 安装 vs2022+(包含C++环境、cmake工具)
|
||||
2. 安装 vulkan-sdk:https://vulkan.lunarg.com/sdk/home
|
||||
3. 使用 vs打开项目文件夹,选中根目录CMakeLists.txt
|
||||
4. 上方选中 A.Windows x64 Debug,然后选择dl_test.exe编译执行
|
||||
|
||||
### Linux(Ubuntu)
|
||||
1. 下载 vscode:https://code.visualstudio.com/#alt-downloads
|
||||
2. 安装 vscode、git、vulkan-sdk、glfw等环境
|
||||
|
||||
```
|
||||
// 为了提高下载速度,请先在“软件和更新”中设置国内镜像
|
||||
sudo apt update
|
||||
//---------------------安装 vscode-----------------------
|
||||
//1.官网下载安装
|
||||
sudo dpkg -i *.deb // 切换到vscode安装包目录安装
|
||||
//2.商店搜索安装
|
||||
//---------------------安装 cmake、clang等--------------------------
|
||||
sudo apt install cmake
|
||||
sudo apt install clang
|
||||
sudo apt install xorg-dev
|
||||
//---------------------安装 vulkan-sdk-------------------
|
||||
wget -qO- https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo tee /etc/apt/trusted.gpg.d/lunarg.asc
|
||||
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-1.3.268-jammy.list https://packages.lunarg.com/vulkan/1.3.268/lunarg-vulkan-1.3.268-jammy.list
|
||||
sudo apt update
|
||||
sudo apt install vulkan-sdk
|
||||
```
|
||||
|
||||
3. 打开 项目文件夹,选中根目录CMakeLists.txt生成
|
||||
4. 安装 vscode相关插件,cmake、C++等
|
||||
5. 下方选中 B.Linux Clang 编译执行dl_test
|
||||
|
||||
### Linux(CentOS)
|
||||
|
||||
```
|
||||
# 安装clang
|
||||
sudo dnf install clang clang-tools-extra -y
|
||||
# 安装cmake
|
||||
sudo dnf install cmake -y
|
||||
# 安装curl
|
||||
sudo dnf install libcurl-devel -y
|
||||
# 拉取仓库
|
||||
cd /opt
|
||||
git clone https://gitee.com/lveyou/dl.git
|
||||
# 解析dl
|
||||
mkdir -p out
|
||||
cd out
|
||||
cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DODE_WITH_DEMOS=false -DDL_EASY=true ..
|
||||
# 编译
|
||||
make -j4
|
||||
|
||||
# 拉取子项目
|
||||
git submodule update --init --recursive project/dl_chess_server/
|
||||
```
|
||||
|
||||
|
||||
### Android
|
||||
1. 安装 Android Studio
|
||||
2. 安装 vulkan-sdk:https://vulkan.lunarg.com/sdk/home
|
||||
3. 使用 Android Studio打开build/android目录编译执行
|
||||
|
||||
### MacOS
|
||||
1. 安装cmake
|
||||
```bash
|
||||
# 安装 brew,已安装跳过
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
brew update
|
||||
brew install cmake
|
||||
```
|
||||
2. 安装 vulkan-sdk:https://vulkan.lunarg.com/sdk/home
|
||||
3. 编译,在dl根目录执行
|
||||
```
|
||||
mdkir -p out
|
||||
cd out
|
||||
cmake ..
|
||||
make -j4
|
||||
```
|
||||
|
||||
## 使用说明
|
||||
|
||||
编译dl_test查看测试程序,也可直接下载发行版预览
|
||||
|
||||
## 讨论群
|
||||
|
||||
QQ群:512001256
|
||||
@@ -0,0 +1,16 @@
|
||||
import openpyxl, sys, os
|
||||
path = sys.argv[1] if len(sys.argv) > 1 else r"d:/dl/project/hs/文档/设计.xlsx"
|
||||
wb = openpyxl.load_workbook(path, data_only=True)
|
||||
print("SHEETS:", wb.sheetnames)
|
||||
for sn in wb.sheetnames:
|
||||
ws = wb[sn]
|
||||
print("###", sn, f"{ws.max_row}x{ws.max_column}")
|
||||
for r in range(1, ws.max_row + 1):
|
||||
vals = []
|
||||
for c in range(1, ws.max_column + 1):
|
||||
v = ws.cell(r, c).value
|
||||
if v is not None:
|
||||
s = str(v).replace("\n", "\\n")
|
||||
vals.append(f"{openpyxl.utils.get_column_letter(c)}{r}:{s}")
|
||||
if vals:
|
||||
print(" " + " | ".join(vals))
|
||||
@@ -0,0 +1,28 @@
|
||||
sudo prime-select nvidia
|
||||
|
||||
|
||||
# 1. 安装推荐的开源内核模块版本
|
||||
sudo apt install nvidia-driver-595-open
|
||||
|
||||
# 2. 安装完成后重启
|
||||
sudo reboot
|
||||
|
||||
|
||||
# 1. 确认驱动加载
|
||||
lsmod | grep nvidia
|
||||
|
||||
# 2. 确认 nvidia-smi 可用
|
||||
nvidia-smi
|
||||
|
||||
# 3. 确认 OpenGL 渲染器(闭源驱动专用)
|
||||
glxinfo | grep "OpenGL renderer"
|
||||
# 应该显示 NVIDIA Corporation 和 RTX 4070
|
||||
|
||||
|
||||
prime-select query
|
||||
|
||||
独显启动程序
|
||||
DRI_PRIME=1 ./dl_test
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
@@ -0,0 +1 @@
|
||||
/build
|
||||
@@ -0,0 +1,106 @@
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
}
|
||||
object Config {
|
||||
// 包名
|
||||
const val DL_APPLICATION_ID = "com.dl.dl_test"
|
||||
// 目标项目名字
|
||||
const val DL_PROJECT_NAME = "dl_test"
|
||||
// 实际显示的应用名字
|
||||
const val DL_APP_NAME = "dl_test"
|
||||
}
|
||||
|
||||
android {
|
||||
signingConfigs {
|
||||
create("release") {
|
||||
storeFile = file("../../../build/android/key")
|
||||
storePassword = "123456"
|
||||
keyPassword = "123456"
|
||||
keyAlias = "dl"
|
||||
}
|
||||
}
|
||||
namespace = Config.DL_APPLICATION_ID
|
||||
compileSdk = 36
|
||||
|
||||
defaultConfig {
|
||||
applicationId = Config.DL_APPLICATION_ID
|
||||
minSdk = 29
|
||||
targetSdk = 36
|
||||
versionCode = 1
|
||||
versionName = "1.0"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
ndk {
|
||||
// v7现在 libwebp 编不过
|
||||
abiFilters.clear()
|
||||
abiFilters.add("arm64-v8a")
|
||||
abiFilters.add("x86_64")
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug{
|
||||
buildConfigField("String", "DL_PROJECT_NAME", "\"${Config.DL_PROJECT_NAME}\"")
|
||||
resValue("string", "DL_PROJECT_NAME", Config.DL_PROJECT_NAME)
|
||||
resValue("string", "DL_APP_NAME", Config.DL_APP_NAME)
|
||||
}
|
||||
release {
|
||||
buildConfigField("String", "DL_PROJECT_NAME", "\"${Config.DL_PROJECT_NAME}\"")
|
||||
resValue("string", "DL_PROJECT_NAME", Config.DL_PROJECT_NAME)
|
||||
resValue("string", "DL_APP_NAME", Config.DL_APP_NAME)
|
||||
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
signingConfig = signingConfigs.getByName("release")
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
}
|
||||
buildFeatures {
|
||||
prefab = true
|
||||
buildConfig = true
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path = file("../../../CMakeLists.txt")
|
||||
version = "3.31.6"
|
||||
}
|
||||
}
|
||||
sourceSets {
|
||||
getByName("main"){
|
||||
assets.srcDirs("../../../project/${Config.DL_PROJECT_NAME}/res")
|
||||
}
|
||||
}
|
||||
|
||||
// Native 库专属规则
|
||||
packaging {
|
||||
jniLibs {
|
||||
excludes += "**"
|
||||
pickFirsts += "**/lib${Config.DL_PROJECT_NAME}.so"
|
||||
}
|
||||
}
|
||||
ndkVersion = "29.0.14206865"
|
||||
buildToolsVersion = "35.0.0"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation(libs.androidx.core.ktx)
|
||||
implementation(libs.androidx.appcompat)
|
||||
implementation(libs.material)
|
||||
implementation(libs.androidx.games.activity)
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
androidTestImplementation(libs.androidx.espresso.core)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.dl.project
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.dl.dl_test", appContext.packageName)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<!-- Declare that this app uses Vulkan -->
|
||||
<!-- <uses-feature android:name="android.hardware.vulkan.version" android:version="0x400003" android:required="true" />-->
|
||||
<!-- <uses-feature android:name="android.hardware.vulkan.level" android:version="0" android:required="true" />-->
|
||||
|
||||
|
||||
<!-- 基础联网权限 -->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/DL_APP_NAME"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.dl">
|
||||
<activity
|
||||
android:name="com.dl.project.MainActivity"
|
||||
android:configChanges="keyboardHidden|orientation"
|
||||
android:screenOrientation="landscape"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.app.lib_name"
|
||||
android:value="@string/DL_PROJECT_NAME" />
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,4 @@
|
||||
#include "AndroidOut.h"
|
||||
|
||||
AndroidOut androidOut("AO");
|
||||
std::ostream aout(&androidOut);
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef ANDROIDGLINVESTIGATIONS_ANDROIDOUT_H
|
||||
#define ANDROIDGLINVESTIGATIONS_ANDROIDOUT_H
|
||||
|
||||
#include <android/log.h>
|
||||
#include <sstream>
|
||||
|
||||
/*!
|
||||
* Use this to log strings out to logcat. Note that you should use std::endl to commit the line
|
||||
*
|
||||
* ex:
|
||||
* aout << "Hello World" << std::endl;
|
||||
*/
|
||||
extern std::ostream aout;
|
||||
|
||||
/*!
|
||||
* Use this class to create an output stream that writes to logcat. By default, a global one is
|
||||
* defined as @a aout
|
||||
*/
|
||||
class AndroidOut: public std::stringbuf {
|
||||
public:
|
||||
/*!
|
||||
* Creates a new output stream for logcat
|
||||
* @param kLogTag the log tag to output
|
||||
*/
|
||||
inline AndroidOut(const char* kLogTag) : logTag_(kLogTag){}
|
||||
|
||||
protected:
|
||||
virtual int sync() override {
|
||||
__android_log_print(ANDROID_LOG_DEBUG, logTag_, "%s", str().c_str());
|
||||
str("");
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
const char* logTag_;
|
||||
};
|
||||
|
||||
#endif //ANDROIDGLINVESTIGATIONS_ANDROIDOUT_H
|
||||
@@ -0,0 +1,32 @@
|
||||
# For more information about using CMake with Android Studio, read the
|
||||
# documentation: https://d.android.com/studio/projects/add-native-code.html
|
||||
|
||||
cmake_minimum_required(VERSION 3.22.1)
|
||||
|
||||
project("dl_test")
|
||||
|
||||
# Creates your game shared library. The name must be the same as the
|
||||
# one used for loading in your Kotlin/Java or AndroidManifest.txt files.
|
||||
add_library(dl_test SHARED
|
||||
main.cpp
|
||||
AndroidOut.cpp
|
||||
Renderer.cpp
|
||||
Shader.cpp
|
||||
TextureAsset.cpp
|
||||
Utility.cpp)
|
||||
|
||||
# Searches for a package provided by the game activity dependency
|
||||
find_package(game-activity REQUIRED CONFIG)
|
||||
|
||||
# Configure libraries CMake uses to link your target library.
|
||||
target_link_libraries(dl_test
|
||||
# The game activity
|
||||
game-activity::game-activity
|
||||
|
||||
# EGL and other dependent libraries required for drawing
|
||||
# and interacting with Android system
|
||||
EGL
|
||||
GLESv3
|
||||
jnigraphics
|
||||
android
|
||||
log)
|
||||
@@ -0,0 +1,66 @@
|
||||
#ifndef ANDROIDGLINVESTIGATIONS_MODEL_H
|
||||
#define ANDROIDGLINVESTIGATIONS_MODEL_H
|
||||
|
||||
#include <vector>
|
||||
#include "TextureAsset.h"
|
||||
|
||||
union Vector3 {
|
||||
struct {
|
||||
float x, y, z;
|
||||
};
|
||||
float idx[3];
|
||||
};
|
||||
|
||||
union Vector2 {
|
||||
struct {
|
||||
float x, y;
|
||||
};
|
||||
struct {
|
||||
float u, v;
|
||||
};
|
||||
float idx[2];
|
||||
};
|
||||
|
||||
struct Vertex {
|
||||
constexpr Vertex(const Vector3 &inPosition, const Vector2 &inUV) : position(inPosition),
|
||||
uv(inUV) {}
|
||||
|
||||
Vector3 position;
|
||||
Vector2 uv;
|
||||
};
|
||||
|
||||
typedef uint16_t Index;
|
||||
|
||||
class Model {
|
||||
public:
|
||||
inline Model(
|
||||
std::vector<Vertex> vertices,
|
||||
std::vector<Index> indices,
|
||||
std::shared_ptr<TextureAsset> spTexture)
|
||||
: vertices_(std::move(vertices)),
|
||||
indices_(std::move(indices)),
|
||||
spTexture_(std::move(spTexture)) {}
|
||||
|
||||
inline const Vertex *getVertexData() const {
|
||||
return vertices_.data();
|
||||
}
|
||||
|
||||
inline const size_t getIndexCount() const {
|
||||
return indices_.size();
|
||||
}
|
||||
|
||||
inline const Index *getIndexData() const {
|
||||
return indices_.data();
|
||||
}
|
||||
|
||||
inline const TextureAsset &getTexture() const {
|
||||
return *spTexture_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Vertex> vertices_;
|
||||
std::vector<Index> indices_;
|
||||
std::shared_ptr<TextureAsset> spTexture_;
|
||||
};
|
||||
|
||||
#endif //ANDROIDGLINVESTIGATIONS_MODEL_H
|
||||
@@ -0,0 +1,378 @@
|
||||
#include "Renderer.h"
|
||||
|
||||
#include <game-activity/native_app_glue/android_native_app_glue.h>
|
||||
#include <GLES3/gl3.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <android/imagedecoder.h>
|
||||
|
||||
#include "AndroidOut.h"
|
||||
#include "Shader.h"
|
||||
#include "Utility.h"
|
||||
#include "TextureAsset.h"
|
||||
|
||||
//! executes glGetString and outputs the result to logcat
|
||||
#define PRINT_GL_STRING(s) {aout << #s": "<< glGetString(s) << std::endl;}
|
||||
|
||||
/*!
|
||||
* @brief if glGetString returns a space separated list of elements, prints each one on a new line
|
||||
*
|
||||
* This works by creating an istringstream of the input c-style string. Then that is used to create
|
||||
* a vector -- each element of the vector is a new element in the input string. Finally a foreach
|
||||
* loop consumes this and outputs it to logcat using @a aout
|
||||
*/
|
||||
#define PRINT_GL_STRING_AS_LIST(s) { \
|
||||
std::istringstream extensionStream((const char *) glGetString(s));\
|
||||
std::vector<std::string> extensionList(\
|
||||
std::istream_iterator<std::string>{extensionStream},\
|
||||
std::istream_iterator<std::string>());\
|
||||
aout << #s":\n";\
|
||||
for (auto& extension: extensionList) {\
|
||||
aout << extension << "\n";\
|
||||
}\
|
||||
aout << std::endl;\
|
||||
}
|
||||
|
||||
//! Color for cornflower blue. Can be sent directly to glClearColor
|
||||
#define CORNFLOWER_BLUE 100 / 255.f, 149 / 255.f, 237 / 255.f, 1
|
||||
|
||||
// Vertex shader, you'd typically load this from assets
|
||||
static const char *vertex = R"vertex(#version 300 es
|
||||
in vec3 inPosition;
|
||||
in vec2 inUV;
|
||||
|
||||
out vec2 fragUV;
|
||||
|
||||
uniform mat4 uProjection;
|
||||
|
||||
void main() {
|
||||
fragUV = inUV;
|
||||
gl_Position = uProjection * vec4(inPosition, 1.0);
|
||||
}
|
||||
)vertex";
|
||||
|
||||
// Fragment shader, you'd typically load this from assets
|
||||
static const char *fragment = R"fragment(#version 300 es
|
||||
precision mediump float;
|
||||
|
||||
in vec2 fragUV;
|
||||
|
||||
uniform sampler2D uTexture;
|
||||
|
||||
out vec4 outColor;
|
||||
|
||||
void main() {
|
||||
outColor = texture(uTexture, fragUV);
|
||||
}
|
||||
)fragment";
|
||||
|
||||
/*!
|
||||
* Half the height of the projection matrix. This gives you a renderable area of height 4 ranging
|
||||
* from -2 to 2
|
||||
*/
|
||||
static constexpr float kProjectionHalfHeight = 2.f;
|
||||
|
||||
/*!
|
||||
* The near plane distance for the projection matrix. Since this is an orthographic projection
|
||||
* matrix, it's convenient to have negative values for sorting (and avoiding z-fighting at 0).
|
||||
*/
|
||||
static constexpr float kProjectionNearPlane = -1.f;
|
||||
|
||||
/*!
|
||||
* The far plane distance for the projection matrix. Since this is an orthographic porjection
|
||||
* matrix, it's convenient to have the far plane equidistant from 0 as the near plane.
|
||||
*/
|
||||
static constexpr float kProjectionFarPlane = 1.f;
|
||||
|
||||
Renderer::~Renderer() {
|
||||
if (display_ != EGL_NO_DISPLAY) {
|
||||
eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
if (context_ != EGL_NO_CONTEXT) {
|
||||
eglDestroyContext(display_, context_);
|
||||
context_ = EGL_NO_CONTEXT;
|
||||
}
|
||||
if (surface_ != EGL_NO_SURFACE) {
|
||||
eglDestroySurface(display_, surface_);
|
||||
surface_ = EGL_NO_SURFACE;
|
||||
}
|
||||
eglTerminate(display_);
|
||||
display_ = EGL_NO_DISPLAY;
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::render() {
|
||||
// Check to see if the surface has changed size. This is _necessary_ to do every frame when
|
||||
// using immersive mode as you'll get no other notification that your renderable area has
|
||||
// changed.
|
||||
updateRenderArea();
|
||||
|
||||
// When the renderable area changes, the projection matrix has to also be updated. This is true
|
||||
// even if you change from the sample orthographic projection matrix as your aspect ratio has
|
||||
// likely changed.
|
||||
if (shaderNeedsNewProjectionMatrix_) {
|
||||
// a placeholder projection matrix allocated on the stack. Column-major memory layout
|
||||
float projectionMatrix[16] = {0};
|
||||
|
||||
// build an orthographic projection matrix for 2d rendering
|
||||
Utility::buildOrthographicMatrix(
|
||||
projectionMatrix,
|
||||
kProjectionHalfHeight,
|
||||
float(width_) / height_,
|
||||
kProjectionNearPlane,
|
||||
kProjectionFarPlane);
|
||||
|
||||
// send the matrix to the shader
|
||||
// Note: the shader must be active for this to work. Since we only have one shader for this
|
||||
// demo, we can assume that it's active.
|
||||
shader_->setProjectionMatrix(projectionMatrix);
|
||||
|
||||
// make sure the matrix isn't generated every frame
|
||||
shaderNeedsNewProjectionMatrix_ = false;
|
||||
}
|
||||
|
||||
// clear the color buffer
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Render all the models. There's no depth testing in this sample so they're accepted in the
|
||||
// order provided. But the sample EGL setup requests a 24 bit depth buffer so you could
|
||||
// configure it at the end of initRenderer
|
||||
if (!models_.empty()) {
|
||||
for (const auto &model: models_) {
|
||||
shader_->drawModel(model);
|
||||
}
|
||||
}
|
||||
|
||||
// Present the rendered image. This is an implicit glFlush.
|
||||
auto swapResult = eglSwapBuffers(display_, surface_);
|
||||
assert(swapResult == EGL_TRUE);
|
||||
}
|
||||
|
||||
void Renderer::initRenderer() {
|
||||
// Choose your render attributes
|
||||
constexpr EGLint attribs[] = {
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_DEPTH_SIZE, 24,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
// The default display is probably what you want on Android
|
||||
auto display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
eglInitialize(display, nullptr, nullptr);
|
||||
|
||||
// figure out how many configs there are
|
||||
EGLint numConfigs;
|
||||
eglChooseConfig(display, attribs, nullptr, 0, &numConfigs);
|
||||
|
||||
// get the list of configurations
|
||||
std::unique_ptr<EGLConfig[]> supportedConfigs(new EGLConfig[numConfigs]);
|
||||
eglChooseConfig(display, attribs, supportedConfigs.get(), numConfigs, &numConfigs);
|
||||
|
||||
// Find a config we like.
|
||||
// Could likely just grab the first if we don't care about anything else in the config.
|
||||
// Otherwise hook in your own heuristic
|
||||
auto config = *std::find_if(
|
||||
supportedConfigs.get(),
|
||||
supportedConfigs.get() + numConfigs,
|
||||
[&display](const EGLConfig &config) {
|
||||
EGLint red, green, blue, depth;
|
||||
if (eglGetConfigAttrib(display, config, EGL_RED_SIZE, &red)
|
||||
&& eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &green)
|
||||
&& eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blue)
|
||||
&& eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depth)) {
|
||||
|
||||
aout << "Found config with " << red << ", " << green << ", " << blue << ", "
|
||||
<< depth << std::endl;
|
||||
return red == 8 && green == 8 && blue == 8 && depth == 24;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
aout << "Found " << numConfigs << " configs" << std::endl;
|
||||
aout << "Chose " << config << std::endl;
|
||||
|
||||
// create the proper window surface
|
||||
EGLint format;
|
||||
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
|
||||
EGLSurface surface = eglCreateWindowSurface(display, config, app_->window, nullptr);
|
||||
|
||||
// Create a GLES 3 context
|
||||
EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
|
||||
EGLContext context = eglCreateContext(display, config, nullptr, contextAttribs);
|
||||
|
||||
// get some window metrics
|
||||
auto madeCurrent = eglMakeCurrent(display, surface, surface, context);
|
||||
assert(madeCurrent);
|
||||
|
||||
display_ = display;
|
||||
surface_ = surface;
|
||||
context_ = context;
|
||||
|
||||
// make width and height invalid so it gets updated the first frame in @a updateRenderArea()
|
||||
width_ = -1;
|
||||
height_ = -1;
|
||||
|
||||
PRINT_GL_STRING(GL_VENDOR);
|
||||
PRINT_GL_STRING(GL_RENDERER);
|
||||
PRINT_GL_STRING(GL_VERSION);
|
||||
PRINT_GL_STRING_AS_LIST(GL_EXTENSIONS);
|
||||
|
||||
shader_ = std::unique_ptr<Shader>(
|
||||
Shader::loadShader(vertex, fragment, "inPosition", "inUV", "uProjection"));
|
||||
assert(shader_);
|
||||
|
||||
// Note: there's only one shader in this demo, so I'll activate it here. For a more complex game
|
||||
// you'll want to track the active shader and activate/deactivate it as necessary
|
||||
shader_->activate();
|
||||
|
||||
// setup any other gl related global states
|
||||
glClearColor(CORNFLOWER_BLUE);
|
||||
|
||||
// enable alpha globally for now, you probably don't want to do this in a game
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// get some demo models into memory
|
||||
createModels();
|
||||
}
|
||||
|
||||
void Renderer::updateRenderArea() {
|
||||
EGLint width;
|
||||
eglQuerySurface(display_, surface_, EGL_WIDTH, &width);
|
||||
|
||||
EGLint height;
|
||||
eglQuerySurface(display_, surface_, EGL_HEIGHT, &height);
|
||||
|
||||
if (width != width_ || height != height_) {
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
glViewport(0, 0, width, height);
|
||||
|
||||
// make sure that we lazily recreate the projection matrix before we render
|
||||
shaderNeedsNewProjectionMatrix_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create any demo models we want for this demo.
|
||||
*/
|
||||
void Renderer::createModels() {
|
||||
/*
|
||||
* This is a square:
|
||||
* 0 --- 1
|
||||
* | \ |
|
||||
* | \ |
|
||||
* | \ |
|
||||
* 3 --- 2
|
||||
*/
|
||||
std::vector<Vertex> vertices = {
|
||||
Vertex(Vector3{1, 1, 0}, Vector2{0, 0}), // 0
|
||||
Vertex(Vector3{-1, 1, 0}, Vector2{1, 0}), // 1
|
||||
Vertex(Vector3{-1, -1, 0}, Vector2{1, 1}), // 2
|
||||
Vertex(Vector3{1, -1, 0}, Vector2{0, 1}) // 3
|
||||
};
|
||||
std::vector<Index> indices = {
|
||||
0, 1, 2, 0, 2, 3
|
||||
};
|
||||
|
||||
// loads an image and assigns it to the square.
|
||||
//
|
||||
// Note: there is no texture management in this sample, so if you reuse an image be careful not
|
||||
// to load it repeatedly. Since you get a shared_ptr you can safely reuse it in many models.
|
||||
auto assetManager = app_->activity->assetManager;
|
||||
auto spAndroidRobotTexture = TextureAsset::loadAsset(assetManager, "android_robot.png");
|
||||
|
||||
// Create a model and put it in the back of the render list.
|
||||
models_.emplace_back(vertices, indices, spAndroidRobotTexture);
|
||||
}
|
||||
|
||||
void Renderer::handleInput() {
|
||||
// handle all queued inputs
|
||||
auto *inputBuffer = android_app_swap_input_buffers(app_);
|
||||
if (!inputBuffer) {
|
||||
// no inputs yet.
|
||||
return;
|
||||
}
|
||||
|
||||
// handle motion events (motionEventsCounts can be 0).
|
||||
for (auto i = 0; i < inputBuffer->motionEventsCount; i++) {
|
||||
auto &motionEvent = inputBuffer->motionEvents[i];
|
||||
auto action = motionEvent.action;
|
||||
|
||||
// Find the pointer index, mask and bitshift to turn it into a readable value.
|
||||
auto pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
|
||||
>> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
||||
aout << "Pointer(s): ";
|
||||
|
||||
// get the x and y position of this event if it is not ACTION_MOVE.
|
||||
auto &pointer = motionEvent.pointers[pointerIndex];
|
||||
auto x = GameActivityPointerAxes_getX(&pointer);
|
||||
auto y = GameActivityPointerAxes_getY(&pointer);
|
||||
|
||||
// determine the action type and process the event accordingly.
|
||||
switch (action & AMOTION_EVENT_ACTION_MASK) {
|
||||
case AMOTION_EVENT_ACTION_DOWN:
|
||||
case AMOTION_EVENT_ACTION_POINTER_DOWN:
|
||||
aout << "(" << pointer.id << ", " << x << ", " << y << ") "
|
||||
<< "Pointer Down";
|
||||
break;
|
||||
|
||||
case AMOTION_EVENT_ACTION_CANCEL:
|
||||
// treat the CANCEL as an UP event: doing nothing in the app, except
|
||||
// removing the pointer from the cache if pointers are locally saved.
|
||||
// code pass through on purpose.
|
||||
case AMOTION_EVENT_ACTION_UP:
|
||||
case AMOTION_EVENT_ACTION_POINTER_UP:
|
||||
aout << "(" << pointer.id << ", " << x << ", " << y << ") "
|
||||
<< "Pointer Up";
|
||||
break;
|
||||
|
||||
case AMOTION_EVENT_ACTION_MOVE:
|
||||
// There is no pointer index for ACTION_MOVE, only a snapshot of
|
||||
// all active pointers; app needs to cache previous active pointers
|
||||
// to figure out which ones are actually moved.
|
||||
for (auto index = 0; index < motionEvent.pointerCount; index++) {
|
||||
pointer = motionEvent.pointers[index];
|
||||
x = GameActivityPointerAxes_getX(&pointer);
|
||||
y = GameActivityPointerAxes_getY(&pointer);
|
||||
aout << "(" << pointer.id << ", " << x << ", " << y << ")";
|
||||
|
||||
if (index != (motionEvent.pointerCount - 1)) aout << ",";
|
||||
aout << " ";
|
||||
}
|
||||
aout << "Pointer Move";
|
||||
break;
|
||||
default:
|
||||
aout << "Unknown MotionEvent Action: " << action;
|
||||
}
|
||||
aout << std::endl;
|
||||
}
|
||||
// clear the motion input count in this buffer for main thread to re-use.
|
||||
android_app_clear_motion_events(inputBuffer);
|
||||
|
||||
// handle input key events.
|
||||
for (auto i = 0; i < inputBuffer->keyEventsCount; i++) {
|
||||
auto &keyEvent = inputBuffer->keyEvents[i];
|
||||
aout << "Key: " << keyEvent.keyCode <<" ";
|
||||
switch (keyEvent.action) {
|
||||
case AKEY_EVENT_ACTION_DOWN:
|
||||
aout << "Key Down";
|
||||
break;
|
||||
case AKEY_EVENT_ACTION_UP:
|
||||
aout << "Key Up";
|
||||
break;
|
||||
case AKEY_EVENT_ACTION_MULTIPLE:
|
||||
// Deprecated since Android API level 29.
|
||||
aout << "Multiple Key Actions";
|
||||
break;
|
||||
default:
|
||||
aout << "Unknown KeyEvent Action: " << keyEvent.action;
|
||||
}
|
||||
aout << std::endl;
|
||||
}
|
||||
// clear the key input count too.
|
||||
android_app_clear_key_events(inputBuffer);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
#ifndef ANDROIDGLINVESTIGATIONS_RENDERER_H
|
||||
#define ANDROIDGLINVESTIGATIONS_RENDERER_H
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <memory>
|
||||
|
||||
#include "Model.h"
|
||||
#include "Shader.h"
|
||||
|
||||
struct android_app;
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
/*!
|
||||
* @param pApp the android_app this Renderer belongs to, needed to configure GL
|
||||
*/
|
||||
inline Renderer(android_app *pApp) :
|
||||
app_(pApp),
|
||||
display_(EGL_NO_DISPLAY),
|
||||
surface_(EGL_NO_SURFACE),
|
||||
context_(EGL_NO_CONTEXT),
|
||||
width_(0),
|
||||
height_(0),
|
||||
shaderNeedsNewProjectionMatrix_(true) {
|
||||
initRenderer();
|
||||
}
|
||||
|
||||
virtual ~Renderer();
|
||||
|
||||
/*!
|
||||
* Handles input from the android_app.
|
||||
*
|
||||
* Note: this will clear the input queue
|
||||
*/
|
||||
void handleInput();
|
||||
|
||||
/*!
|
||||
* Renders all the models in the renderer
|
||||
*/
|
||||
void render();
|
||||
|
||||
private:
|
||||
/*!
|
||||
* Performs necessary OpenGL initialization. Customize this if you want to change your EGL
|
||||
* context or application-wide settings.
|
||||
*/
|
||||
void initRenderer();
|
||||
|
||||
/*!
|
||||
* @brief we have to check every frame to see if the framebuffer has changed in size. If it has,
|
||||
* update the viewport accordingly
|
||||
*/
|
||||
void updateRenderArea();
|
||||
|
||||
/*!
|
||||
* Creates the models for this sample. You'd likely load a scene configuration from a file or
|
||||
* use some other setup logic in your full game.
|
||||
*/
|
||||
void createModels();
|
||||
|
||||
android_app *app_;
|
||||
EGLDisplay display_;
|
||||
EGLSurface surface_;
|
||||
EGLContext context_;
|
||||
EGLint width_;
|
||||
EGLint height_;
|
||||
|
||||
bool shaderNeedsNewProjectionMatrix_;
|
||||
|
||||
std::unique_ptr<Shader> shader_;
|
||||
std::vector<Model> models_;
|
||||
};
|
||||
|
||||
#endif //ANDROIDGLINVESTIGATIONS_RENDERER_H
|
||||
@@ -0,0 +1,154 @@
|
||||
#include "Shader.h"
|
||||
|
||||
#include "AndroidOut.h"
|
||||
#include "Model.h"
|
||||
#include "Utility.h"
|
||||
|
||||
Shader *Shader::loadShader(
|
||||
const std::string &vertexSource,
|
||||
const std::string &fragmentSource,
|
||||
const std::string &positionAttributeName,
|
||||
const std::string &uvAttributeName,
|
||||
const std::string &projectionMatrixUniformName) {
|
||||
Shader *shader = nullptr;
|
||||
|
||||
GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vertexSource);
|
||||
if (!vertexShader) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentSource);
|
||||
if (!fragmentShader) {
|
||||
glDeleteShader(vertexShader);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GLuint program = glCreateProgram();
|
||||
if (program) {
|
||||
glAttachShader(program, vertexShader);
|
||||
glAttachShader(program, fragmentShader);
|
||||
|
||||
glLinkProgram(program);
|
||||
GLint linkStatus = GL_FALSE;
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
|
||||
if (linkStatus != GL_TRUE) {
|
||||
GLint logLength = 0;
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
|
||||
|
||||
// If we fail to link the shader program, log the result for debugging
|
||||
if (logLength) {
|
||||
GLchar *log = new GLchar[logLength];
|
||||
glGetProgramInfoLog(program, logLength, nullptr, log);
|
||||
aout << "Failed to link program with:\n" << log << std::endl;
|
||||
delete[] log;
|
||||
}
|
||||
|
||||
glDeleteProgram(program);
|
||||
} else {
|
||||
// Get the attribute and uniform locations by name. You may also choose to hardcode
|
||||
// indices with layout= in your shader, but it is not done in this sample
|
||||
GLint positionAttribute = glGetAttribLocation(program, positionAttributeName.c_str());
|
||||
GLint uvAttribute = glGetAttribLocation(program, uvAttributeName.c_str());
|
||||
GLint projectionMatrixUniform = glGetUniformLocation(
|
||||
program,
|
||||
projectionMatrixUniformName.c_str());
|
||||
|
||||
// Only create a new shader if all the attributes are found.
|
||||
if (positionAttribute != -1
|
||||
&& uvAttribute != -1
|
||||
&& projectionMatrixUniform != -1) {
|
||||
|
||||
shader = new Shader(
|
||||
program,
|
||||
positionAttribute,
|
||||
uvAttribute,
|
||||
projectionMatrixUniform);
|
||||
} else {
|
||||
glDeleteProgram(program);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The shaders are no longer needed once the program is linked. Release their memory.
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
GLuint Shader::loadShader(GLenum shaderType, const std::string &shaderSource) {
|
||||
Utility::assertGlError();
|
||||
GLuint shader = glCreateShader(shaderType);
|
||||
if (shader) {
|
||||
auto *shaderRawString = (GLchar *) shaderSource.c_str();
|
||||
GLint shaderLength = shaderSource.length();
|
||||
glShaderSource(shader, 1, &shaderRawString, &shaderLength);
|
||||
glCompileShader(shader);
|
||||
|
||||
GLint shaderCompiled = 0;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &shaderCompiled);
|
||||
|
||||
// If the shader doesn't compile, log the result to the terminal for debugging
|
||||
if (!shaderCompiled) {
|
||||
GLint infoLength = 0;
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLength);
|
||||
|
||||
if (infoLength) {
|
||||
auto *infoLog = new GLchar[infoLength];
|
||||
glGetShaderInfoLog(shader, infoLength, nullptr, infoLog);
|
||||
aout << "Failed to compile with:\n" << infoLog << std::endl;
|
||||
delete[] infoLog;
|
||||
}
|
||||
|
||||
glDeleteShader(shader);
|
||||
shader = 0;
|
||||
}
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
void Shader::activate() const {
|
||||
glUseProgram(program_);
|
||||
}
|
||||
|
||||
void Shader::deactivate() const {
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
void Shader::drawModel(const Model &model) const {
|
||||
// The position attribute is 3 floats
|
||||
glVertexAttribPointer(
|
||||
position_, // attrib
|
||||
3, // elements
|
||||
GL_FLOAT, // of type float
|
||||
GL_FALSE, // don't normalize
|
||||
sizeof(Vertex), // stride is Vertex bytes
|
||||
model.getVertexData() // pull from the start of the vertex data
|
||||
);
|
||||
glEnableVertexAttribArray(position_);
|
||||
|
||||
// The uv attribute is 2 floats
|
||||
glVertexAttribPointer(
|
||||
uv_, // attrib
|
||||
2, // elements
|
||||
GL_FLOAT, // of type float
|
||||
GL_FALSE, // don't normalize
|
||||
sizeof(Vertex), // stride is Vertex bytes
|
||||
((uint8_t *) model.getVertexData()) + sizeof(Vector3) // offset Vector3 from the start
|
||||
);
|
||||
glEnableVertexAttribArray(uv_);
|
||||
|
||||
// Setup the texture
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, model.getTexture().getTextureID());
|
||||
|
||||
// Draw as indexed triangles
|
||||
glDrawElements(GL_TRIANGLES, model.getIndexCount(), GL_UNSIGNED_SHORT, model.getIndexData());
|
||||
|
||||
glDisableVertexAttribArray(uv_);
|
||||
glDisableVertexAttribArray(position_);
|
||||
}
|
||||
|
||||
void Shader::setProjectionMatrix(float *projectionMatrix) const {
|
||||
glUniformMatrix4fv(projectionMatrix_, 1, false, projectionMatrix);
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#ifndef ANDROIDGLINVESTIGATIONS_SHADER_H
|
||||
#define ANDROIDGLINVESTIGATIONS_SHADER_H
|
||||
|
||||
#include <string>
|
||||
#include <GLES3/gl3.h>
|
||||
|
||||
class Model;
|
||||
|
||||
/*!
|
||||
* A class representing a simple shader program. It consists of vertex and fragment components. The
|
||||
* input attributes are a position (as a Vector3) and a uv (as a Vector2). It also takes a uniform
|
||||
* to be used as the entire model/view/projection matrix. The shader expects a single texture for
|
||||
* fragment shading, and does no other lighting calculations (thus no uniforms for lights or normal
|
||||
* attributes).
|
||||
*/
|
||||
class Shader {
|
||||
public:
|
||||
/*!
|
||||
* Loads a shader given the full sourcecode and names for necessary attributes and uniforms to
|
||||
* link to. Returns a valid shader on success or null on failure. Shader resources are
|
||||
* automatically cleaned up on destruction.
|
||||
*
|
||||
* @param vertexSource The full source code for your vertex program
|
||||
* @param fragmentSource The full source code of your fragment program
|
||||
* @param positionAttributeName The name of the position attribute in your vertex program
|
||||
* @param uvAttributeName The name of the uv coordinate attribute in your vertex program
|
||||
* @param projectionMatrixUniformName The name of your model/view/projection matrix uniform
|
||||
* @return a valid Shader on success, otherwise null.
|
||||
*/
|
||||
static Shader *loadShader(
|
||||
const std::string &vertexSource,
|
||||
const std::string &fragmentSource,
|
||||
const std::string &positionAttributeName,
|
||||
const std::string &uvAttributeName,
|
||||
const std::string &projectionMatrixUniformName);
|
||||
|
||||
inline ~Shader() {
|
||||
if (program_) {
|
||||
glDeleteProgram(program_);
|
||||
program_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Prepares the shader for use, call this before executing any draw commands
|
||||
*/
|
||||
void activate() const;
|
||||
|
||||
/*!
|
||||
* Cleans up the shader after use, call this after executing any draw commands
|
||||
*/
|
||||
void deactivate() const;
|
||||
|
||||
/*!
|
||||
* Renders a single model
|
||||
* @param model a model to render
|
||||
*/
|
||||
void drawModel(const Model &model) const;
|
||||
|
||||
/*!
|
||||
* Sets the model/view/projection matrix in the shader.
|
||||
* @param projectionMatrix sixteen floats, column major, defining an OpenGL projection matrix.
|
||||
*/
|
||||
void setProjectionMatrix(float *projectionMatrix) const;
|
||||
|
||||
private:
|
||||
/*!
|
||||
* Helper function to load a shader of a given type
|
||||
* @param shaderType The OpenGL shader type. Should either be GL_VERTEX_SHADER or GL_FRAGMENT_SHADER
|
||||
* @param shaderSource The full source of the shader
|
||||
* @return the id of the shader, as returned by glCreateShader, or 0 in the case of an error
|
||||
*/
|
||||
static GLuint loadShader(GLenum shaderType, const std::string &shaderSource);
|
||||
|
||||
/*!
|
||||
* Constructs a new instance of a shader. Use @a loadShader
|
||||
* @param program the GL program id of the shader
|
||||
* @param position the attribute location of the position
|
||||
* @param uv the attribute location of the uv coordinates
|
||||
* @param projectionMatrix the uniform location of the projection matrix
|
||||
*/
|
||||
constexpr Shader(
|
||||
GLuint program,
|
||||
GLint position,
|
||||
GLint uv,
|
||||
GLint projectionMatrix)
|
||||
: program_(program),
|
||||
position_(position),
|
||||
uv_(uv),
|
||||
projectionMatrix_(projectionMatrix) {}
|
||||
|
||||
GLuint program_;
|
||||
GLint position_;
|
||||
GLint uv_;
|
||||
GLint projectionMatrix_;
|
||||
};
|
||||
|
||||
#endif //ANDROIDGLINVESTIGATIONS_SHADER_H
|
||||
@@ -0,0 +1,80 @@
|
||||
#include <android/imagedecoder.h>
|
||||
#include "TextureAsset.h"
|
||||
#include "AndroidOut.h"
|
||||
#include "Utility.h"
|
||||
|
||||
std::shared_ptr<TextureAsset>
|
||||
TextureAsset::loadAsset(AAssetManager *assetManager, const std::string &assetPath) {
|
||||
// Get the image from asset manager
|
||||
auto pAndroidRobotPng = AAssetManager_open(
|
||||
assetManager,
|
||||
assetPath.c_str(),
|
||||
AASSET_MODE_BUFFER);
|
||||
|
||||
// Make a decoder to turn it into a texture
|
||||
AImageDecoder *pAndroidDecoder = nullptr;
|
||||
auto result = AImageDecoder_createFromAAsset(pAndroidRobotPng, &pAndroidDecoder);
|
||||
assert(result == ANDROID_IMAGE_DECODER_SUCCESS);
|
||||
|
||||
// make sure we get 8 bits per channel out. RGBA order.
|
||||
AImageDecoder_setAndroidBitmapFormat(pAndroidDecoder, ANDROID_BITMAP_FORMAT_RGBA_8888);
|
||||
|
||||
// Get the image header, to help set everything up
|
||||
const AImageDecoderHeaderInfo *pAndroidHeader = nullptr;
|
||||
pAndroidHeader = AImageDecoder_getHeaderInfo(pAndroidDecoder);
|
||||
|
||||
// important metrics for sending to GL
|
||||
auto width = AImageDecoderHeaderInfo_getWidth(pAndroidHeader);
|
||||
auto height = AImageDecoderHeaderInfo_getHeight(pAndroidHeader);
|
||||
auto stride = AImageDecoder_getMinimumStride(pAndroidDecoder);
|
||||
|
||||
// Get the bitmap data of the image
|
||||
auto upAndroidImageData = std::make_unique<std::vector<uint8_t>>(height * stride);
|
||||
auto decodeResult = AImageDecoder_decodeImage(
|
||||
pAndroidDecoder,
|
||||
upAndroidImageData->data(),
|
||||
stride,
|
||||
upAndroidImageData->size());
|
||||
assert(decodeResult == ANDROID_IMAGE_DECODER_SUCCESS);
|
||||
|
||||
// Get an opengl texture
|
||||
GLuint textureId;
|
||||
glGenTextures(1, &textureId);
|
||||
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||
|
||||
// Clamp to the edge, you'll get odd results alpha blending if you don't
|
||||
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_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
// Load the texture into VRAM
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D, // target
|
||||
0, // mip level
|
||||
GL_RGBA, // internal format, often advisable to use BGR
|
||||
width, // width of the texture
|
||||
height, // height of the texture
|
||||
0, // border (always 0)
|
||||
GL_RGBA, // format
|
||||
GL_UNSIGNED_BYTE, // type
|
||||
upAndroidImageData->data() // Data to upload
|
||||
);
|
||||
|
||||
// generate mip levels. Not really needed for 2D, but good to do
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
// cleanup helpers
|
||||
AImageDecoder_delete(pAndroidDecoder);
|
||||
AAsset_close(pAndroidRobotPng);
|
||||
|
||||
// Create a shared pointer so it can be cleaned up easily/automatically
|
||||
return std::shared_ptr<TextureAsset>(new TextureAsset(textureId));
|
||||
}
|
||||
|
||||
TextureAsset::~TextureAsset() {
|
||||
// return texture resources
|
||||
glDeleteTextures(1, &textureID_);
|
||||
textureID_ = 0;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef ANDROIDGLINVESTIGATIONS_TEXTUREASSET_H
|
||||
#define ANDROIDGLINVESTIGATIONS_TEXTUREASSET_H
|
||||
|
||||
#include <memory>
|
||||
#include <android/asset_manager.h>
|
||||
#include <GLES3/gl3.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class TextureAsset {
|
||||
public:
|
||||
/*!
|
||||
* Loads a texture asset from the assets/ directory
|
||||
* @param assetManager Asset manager to use
|
||||
* @param assetPath The path to the asset
|
||||
* @return a shared pointer to a texture asset, resources will be reclaimed when it's cleaned up
|
||||
*/
|
||||
static std::shared_ptr<TextureAsset>
|
||||
loadAsset(AAssetManager *assetManager, const std::string &assetPath);
|
||||
|
||||
~TextureAsset();
|
||||
|
||||
/*!
|
||||
* @return the texture id for use with OpenGL
|
||||
*/
|
||||
constexpr GLuint getTextureID() const { return textureID_; }
|
||||
|
||||
private:
|
||||
inline TextureAsset(GLuint textureId) : textureID_(textureId) {}
|
||||
|
||||
GLuint textureID_;
|
||||
};
|
||||
|
||||
#endif //ANDROIDGLINVESTIGATIONS_TEXTUREASSET_H
|
||||
@@ -0,0 +1,87 @@
|
||||
#include "Utility.h"
|
||||
#include "AndroidOut.h"
|
||||
|
||||
#include <GLES3/gl3.h>
|
||||
|
||||
#define CHECK_ERROR(e) case e: aout << "GL Error: "#e << std::endl; break;
|
||||
|
||||
bool Utility::checkAndLogGlError(bool alwaysLog) {
|
||||
GLenum error = glGetError();
|
||||
if (error == GL_NO_ERROR) {
|
||||
if (alwaysLog) {
|
||||
aout << "No GL error" << std::endl;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
switch (error) {
|
||||
CHECK_ERROR(GL_INVALID_ENUM);
|
||||
CHECK_ERROR(GL_INVALID_VALUE);
|
||||
CHECK_ERROR(GL_INVALID_OPERATION);
|
||||
CHECK_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
|
||||
CHECK_ERROR(GL_OUT_OF_MEMORY);
|
||||
default:
|
||||
aout << "Unknown GL error: " << error << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
float *
|
||||
Utility::buildOrthographicMatrix(float *outMatrix, float halfHeight, float aspect, float near,
|
||||
float far) {
|
||||
float halfWidth = halfHeight * aspect;
|
||||
|
||||
// column 1
|
||||
outMatrix[0] = 1.f / halfWidth;
|
||||
outMatrix[1] = 0.f;
|
||||
outMatrix[2] = 0.f;
|
||||
outMatrix[3] = 0.f;
|
||||
|
||||
// column 2
|
||||
outMatrix[4] = 0.f;
|
||||
outMatrix[5] = 1.f / halfHeight;
|
||||
outMatrix[6] = 0.f;
|
||||
outMatrix[7] = 0.f;
|
||||
|
||||
// column 3
|
||||
outMatrix[8] = 0.f;
|
||||
outMatrix[9] = 0.f;
|
||||
outMatrix[10] = -2.f / (far - near);
|
||||
outMatrix[11] = -(far + near) / (far - near);
|
||||
|
||||
// column 4
|
||||
outMatrix[12] = 0.f;
|
||||
outMatrix[13] = 0.f;
|
||||
outMatrix[14] = 0.f;
|
||||
outMatrix[15] = 1.f;
|
||||
|
||||
return outMatrix;
|
||||
}
|
||||
|
||||
float *Utility::buildIdentityMatrix(float *outMatrix) {
|
||||
// column 1
|
||||
outMatrix[0] = 1.f;
|
||||
outMatrix[1] = 0.f;
|
||||
outMatrix[2] = 0.f;
|
||||
outMatrix[3] = 0.f;
|
||||
|
||||
// column 2
|
||||
outMatrix[4] = 0.f;
|
||||
outMatrix[5] = 1.f;
|
||||
outMatrix[6] = 0.f;
|
||||
outMatrix[7] = 0.f;
|
||||
|
||||
// column 3
|
||||
outMatrix[8] = 0.f;
|
||||
outMatrix[9] = 0.f;
|
||||
outMatrix[10] = 1.f;
|
||||
outMatrix[11] = 0.f;
|
||||
|
||||
// column 4
|
||||
outMatrix[12] = 0.f;
|
||||
outMatrix[13] = 0.f;
|
||||
outMatrix[14] = 0.f;
|
||||
outMatrix[15] = 1.f;
|
||||
|
||||
return outMatrix;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef ANDROIDGLINVESTIGATIONS_UTILITY_H
|
||||
#define ANDROIDGLINVESTIGATIONS_UTILITY_H
|
||||
|
||||
#include <cassert>
|
||||
|
||||
class Utility {
|
||||
public:
|
||||
static bool checkAndLogGlError(bool alwaysLog = false);
|
||||
|
||||
static inline void assertGlError() { assert(checkAndLogGlError()); }
|
||||
|
||||
/**
|
||||
* Generates an orthographic projection matrix given the half height, aspect ratio, near, and far
|
||||
* planes
|
||||
*
|
||||
* @param outMatrix the matrix to write into
|
||||
* @param halfHeight half of the height of the screen
|
||||
* @param aspect the width of the screen divided by the height
|
||||
* @param near the distance of the near plane
|
||||
* @param far the distance of the far plane
|
||||
* @return the generated matrix, this will be the same as @a outMatrix so you can chain calls
|
||||
* together if needed
|
||||
*/
|
||||
static float *buildOrthographicMatrix(
|
||||
float *outMatrix,
|
||||
float halfHeight,
|
||||
float aspect,
|
||||
float near,
|
||||
float far);
|
||||
|
||||
static float *buildIdentityMatrix(float *outMatrix);
|
||||
};
|
||||
|
||||
#endif //ANDROIDGLINVESTIGATIONS_UTILITY_H
|
||||
@@ -0,0 +1,118 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "AndroidOut.h"
|
||||
#include "Renderer.h"
|
||||
|
||||
#include <game-activity/GameActivity.cpp>
|
||||
#include <game-text-input/gametextinput.cpp>
|
||||
|
||||
extern "C" {
|
||||
|
||||
#include <game-activity/native_app_glue/android_native_app_glue.c>
|
||||
|
||||
/*!
|
||||
* Handles commands sent to this Android application
|
||||
* @param pApp the app the commands are coming from
|
||||
* @param cmd the command to handle
|
||||
*/
|
||||
void handle_cmd(android_app *pApp, int32_t cmd) {
|
||||
switch (cmd) {
|
||||
case APP_CMD_INIT_WINDOW:
|
||||
// A new window is created, associate a renderer with it. You may replace this with a
|
||||
// "game" class if that suits your needs. Remember to change all instances of userData
|
||||
// if you change the class here as a reinterpret_cast is dangerous this in the
|
||||
// android_main function and the APP_CMD_TERM_WINDOW handler case.
|
||||
pApp->userData = new Renderer(pApp);
|
||||
break;
|
||||
case APP_CMD_TERM_WINDOW:
|
||||
// The window is being destroyed. Use this to clean up your userData to avoid leaking
|
||||
// resources.
|
||||
//
|
||||
// We have to check if userData is assigned just in case this comes in really quickly
|
||||
if (pApp->userData) {
|
||||
//
|
||||
auto *pRenderer = reinterpret_cast<Renderer *>(pApp->userData);
|
||||
pApp->userData = nullptr;
|
||||
delete pRenderer;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Enable the motion events you want to handle; not handled events are
|
||||
* passed back to OS for further processing. For this example case,
|
||||
* only pointer and joystick devices are enabled.
|
||||
*
|
||||
* @param motionEvent the newly arrived GameActivityMotionEvent.
|
||||
* @return true if the event is from a pointer or joystick device,
|
||||
* false for all other input devices.
|
||||
*/
|
||||
bool motion_event_filter_func(const GameActivityMotionEvent *motionEvent) {
|
||||
auto sourceClass = motionEvent->source & AINPUT_SOURCE_CLASS_MASK;
|
||||
return (sourceClass == AINPUT_SOURCE_CLASS_POINTER ||
|
||||
sourceClass == AINPUT_SOURCE_CLASS_JOYSTICK);
|
||||
}
|
||||
|
||||
/*!
|
||||
* This the main entry point for a native activity
|
||||
*/
|
||||
void android_main(struct android_app *pApp) {
|
||||
// Can be removed, useful to ensure your code is running
|
||||
aout << "Welcome to android_main" << std::endl;
|
||||
|
||||
// Register an event handler for Android events
|
||||
pApp->onAppCmd = handle_cmd;
|
||||
|
||||
// Set input event filters (set it to NULL if the app wants to process all inputs).
|
||||
// Note that for key inputs, this example uses the default default_key_filter()
|
||||
// implemented in android_native_app_glue.c.
|
||||
android_app_set_motion_event_filter(pApp, motion_event_filter_func);
|
||||
|
||||
// This sets up a typical game/event loop. It will run until the app is destroyed.
|
||||
do {
|
||||
// Process all pending events before running game logic.
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
// 0 is non-blocking.
|
||||
int timeout = 0;
|
||||
int events;
|
||||
android_poll_source *pSource;
|
||||
int result = ALooper_pollOnce(timeout, nullptr, &events,
|
||||
reinterpret_cast<void**>(&pSource));
|
||||
switch (result) {
|
||||
case ALOOPER_POLL_TIMEOUT:
|
||||
[[clang::fallthrough]];
|
||||
case ALOOPER_POLL_WAKE:
|
||||
// No events occurred before the timeout or explicit wake. Stop checking for events.
|
||||
done = true;
|
||||
break;
|
||||
case ALOOPER_EVENT_ERROR:
|
||||
aout << "ALooper_pollOnce returned an error" << std::endl;
|
||||
break;
|
||||
case ALOOPER_POLL_CALLBACK:
|
||||
break;
|
||||
default:
|
||||
if (pSource) {
|
||||
pSource->process(pApp, pSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if any user data is associated. This is assigned in handle_cmd
|
||||
if (pApp->userData) {
|
||||
// We know that our user data is a Renderer, so reinterpret cast it. If you change your
|
||||
// user data remember to change it here
|
||||
auto *pRenderer = reinterpret_cast<Renderer *>(pApp->userData);
|
||||
|
||||
// Process game input
|
||||
pRenderer->handleInput();
|
||||
|
||||
// Render a frame
|
||||
pRenderer->render();
|
||||
}
|
||||
} while (!pApp->destroyRequested);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
*FileName: AssetsCopyer.java
|
||||
*Author: xxx
|
||||
*Time: 2016年6月28日 下午3:31:49
|
||||
*
|
||||
/******************************************************************************************/
|
||||
package com.dl.project;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
public class AssetsCopyer {
|
||||
|
||||
private static final String TAG = "AssetsCopyer";
|
||||
|
||||
public static void releaseAssets(Context context, String assetsDir,
|
||||
String releaseDir) {
|
||||
|
||||
// Log.d(TAG, "context: " + context + ", " + assetsDir);
|
||||
if (TextUtils.isEmpty(releaseDir)) {
|
||||
return;
|
||||
} else if (releaseDir.endsWith("/")) {
|
||||
releaseDir = releaseDir.substring(0, releaseDir.length() - 1);
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(assetsDir) || assetsDir.equals("/")) {
|
||||
assetsDir = "";
|
||||
} else if (assetsDir.endsWith("/")) {
|
||||
assetsDir = assetsDir.substring(0, assetsDir.length() - 1);
|
||||
}
|
||||
|
||||
AssetManager assets = context.getAssets();
|
||||
try {
|
||||
String[] fileNames = assets.list(assetsDir);//只能获取到文件(夹)名,所以还得判断是文件夹还是文件
|
||||
if (fileNames.length > 0) {// is dir
|
||||
for (String name : fileNames) {
|
||||
if (!TextUtils.isEmpty(assetsDir)) {
|
||||
name = assetsDir + File.separator + name;//补全assets资源路径
|
||||
}
|
||||
// Log.i(, brian name= + name);
|
||||
String[] childNames = assets.list(name);//判断是文件还是文件夹
|
||||
if (!TextUtils.isEmpty(name) && childNames.length > 0) {
|
||||
checkFolderExists(releaseDir + File.separator + name);
|
||||
releaseAssets(context, name, releaseDir);//递归, 因为资源都是带着全路径,
|
||||
//所以不需要在递归是设置目标文件夹的路径
|
||||
} else {
|
||||
InputStream is = assets.open(name);
|
||||
// FileUtil.writeFile(releaseDir + File.separator + name, is);
|
||||
writeFile(releaseDir + File.separator + name, is);
|
||||
}
|
||||
}
|
||||
} else {// is file
|
||||
InputStream is = assets.open(assetsDir);
|
||||
// 写入文件前, 需要提前级联创建好路径, 下面有代码贴出
|
||||
// FileUtil.writeFile(releaseDir + File.separator + assetsDir, is);
|
||||
writeFile(releaseDir + File.separator + assetsDir, is);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean writeFile(String fileName, InputStream in) throws IOException
|
||||
{
|
||||
boolean bRet = true;
|
||||
try {
|
||||
OutputStream os = new FileOutputStream(fileName);
|
||||
byte[] buffer = new byte[4112];
|
||||
int read;
|
||||
while((read = in.read(buffer)) != -1)
|
||||
{
|
||||
os.write(buffer, 0, read);
|
||||
}
|
||||
in.close();
|
||||
in = null;
|
||||
os.flush();
|
||||
os.close();
|
||||
os = null;
|
||||
// Log.v(TAG, "copyed file: " + fileName);
|
||||
} catch (FileNotFoundException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
bRet = false;
|
||||
}
|
||||
return bRet;
|
||||
}
|
||||
|
||||
private static void checkFolderExists(String path)
|
||||
{
|
||||
File file = new File(path);
|
||||
if((file.exists() && !file.isDirectory()) || !file.exists())
|
||||
{
|
||||
file.mkdirs();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
package com.dl.project;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.res.Configuration;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.dl.dl_test.BuildConfig;
|
||||
import com.google.androidgamesdk.GameActivity;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class MainActivity extends GameActivity {
|
||||
static String TAG = BuildConfig.DL_PROJECT_NAME;
|
||||
static {
|
||||
System.loadLibrary(TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
// 声音可设置
|
||||
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||
// 文件系统
|
||||
initStoragePath();
|
||||
|
||||
// Keep the screen on while the app is running
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
Log.d(TAG, "onStart()被调用");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
Log.d(TAG, "onResume()被调用");
|
||||
DispatchOnResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
Log.d(TAG, "onPause()被调用");
|
||||
DispatchOnPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
Log.d(TAG, "onStop()被调用");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
Log.d(TAG, "onDestroy()被调用");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestart() {
|
||||
super.onRestart();
|
||||
Log.d(TAG, "onRestart()被调用");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
//
|
||||
super.onConfigurationChanged(newConfig);
|
||||
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
// 屏幕为横屏模式时的操作
|
||||
Log.d(TAG, "切换至横屏");
|
||||
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||
// 屏幕为竖屏模式时的操作
|
||||
Log.d(TAG, "切换至竖屏");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus)
|
||||
{
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
|
||||
if (hasFocus) {
|
||||
hideSystemUi();
|
||||
}
|
||||
}
|
||||
//---------------------------C++接口-----------------------------------
|
||||
// 设置文件夹路径
|
||||
native void SetStoragePath(String str_private, String str_storage, String str_public);
|
||||
// onPause事件
|
||||
native void DispatchOnPause();
|
||||
// onResume事件
|
||||
native void DispatchOnResume();
|
||||
|
||||
//---------------------------私有接口-----------------------------------
|
||||
private void hideSystemUi() {
|
||||
View decorView = getWindow().getDecorView();
|
||||
decorView.setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
);
|
||||
}
|
||||
|
||||
private void initStoragePath()
|
||||
{
|
||||
// 私有内部存储
|
||||
String str_private = getFilesDir().getAbsolutePath();
|
||||
// 私有外部存储
|
||||
String str_storage;
|
||||
File file = getExternalFilesDir("");
|
||||
if(file != null)
|
||||
str_storage = file.getAbsolutePath();
|
||||
else
|
||||
str_storage = "";
|
||||
// 公共文件夹
|
||||
String str_public;
|
||||
File file1 = Environment.getExternalStoragePublicDirectory("");
|
||||
if(file1 != null)
|
||||
str_public = file1.getAbsolutePath();
|
||||
else
|
||||
str_public = "";
|
||||
|
||||
SetStoragePath(str_private, str_storage, str_public);
|
||||
|
||||
// 由于AAssetManager无法递归遍历所有文件,只能由Java复制副本到外部存储的assets目录(自己定的名字)
|
||||
AssetsCopyer.releaseAssets(this, "", str_storage + "/assets");
|
||||
}
|
||||
public void MessageBox(String str_title, String str_info, String str_btn)
|
||||
{
|
||||
// 在 Activity 中调用
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(str_title) // 标题
|
||||
.setMessage(str_info) // 内容
|
||||
.setPositiveButton(str_btn, (dialog, which) -> {
|
||||
// 点击确定回调
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setCancelable(false) // 点击空白/返回键是否关闭
|
||||
.show();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
||||
@@ -0,0 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 982 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="purple_200">#FFBB86FC</color>
|
||||
<color name="purple_500">#FF6200EE</color>
|
||||
<color name="purple_700">#FF3700B3</color>
|
||||
<color name="teal_200">#FF03DAC5</color>
|
||||
<color name="teal_700">#FF018786</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
</resources>
|
||||
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<!-- <string name="app_name">AppName</string>-->
|
||||
</resources>
|
||||
@@ -0,0 +1,8 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.dl" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<!-- 全屏、占满刘海屏 -->
|
||||
<item name="android:windowFullscreen">true</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample backup rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/guide/topics/data/autobackup
|
||||
for details.
|
||||
Note: This file is ignored for devices older that API 31
|
||||
See https://developer.android.com/about/versions/12/backup-restore
|
||||
-->
|
||||
<full-backup-content>
|
||||
<!--
|
||||
<include domain="sharedpref" path="."/>
|
||||
<exclude domain="sharedpref" path="device.xml"/>
|
||||
-->
|
||||
</full-backup-content>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample data extraction rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
|
||||
for details.
|
||||
-->
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<!-- TODO: Use <include> and <exclude> to control what is backed up.
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
-->
|
||||
</cloud-backup>
|
||||
<!--
|
||||
<device-transfer>
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
</device-transfer>
|
||||
-->
|
||||
</data-extraction-rules>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.dl.project
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
alias(libs.plugins.android.application) apply false
|
||||
alias(libs.plugins.kotlin.android) apply false
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. For more details, visit
|
||||
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
|
||||
# org.gradle.parallel=true
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app's APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
# Kotlin code style for this project: "official" or "obsolete":
|
||||
kotlin.code.style=official
|
||||
# Enables namespacing of each library's R class so that its R class includes only the
|
||||
# resources declared in the library itself and none from the library's dependencies,
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
||||
@@ -0,0 +1,24 @@
|
||||
[versions]
|
||||
agp = "8.8.0"
|
||||
kotlin = "1.9.24"
|
||||
coreKtx = "1.10.1"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "1.1.5"
|
||||
espressoCore = "3.5.1"
|
||||
appcompat = "1.6.1"
|
||||
material = "1.10.0"
|
||||
gamesActivity = "1.2.2"
|
||||
|
||||
[libraries]
|
||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
||||
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
||||
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||
androidx-games-activity = { group = "androidx.games", name = "games-activity", version.ref = "gamesActivity" }
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#Mon Jan 20 00:48:23 CST 2025
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.10.2-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -0,0 +1,185 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
@@ -0,0 +1,89 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -0,0 +1,34 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
// 改为阿里云的镜像地址
|
||||
maven { setUrl("https://maven.aliyun.com/repository/central") }
|
||||
maven { setUrl("https://maven.aliyun.com/repository/jcenter") }
|
||||
maven { setUrl("https://maven.aliyun.com/repository/google") }
|
||||
maven { setUrl("https://maven.aliyun.com/repository/gradle-plugin") }
|
||||
maven { setUrl("https://maven.aliyun.com/repository/public") }
|
||||
maven { setUrl("https://jitpack.io") }
|
||||
maven { setUrl("https://maven.aliyun.com/nexus/content/groups/public/") }
|
||||
maven { setUrl("https://maven.aliyun.com/nexus/content/repositories/jcenter") }
|
||||
gradlePluginPortal()
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
// 改为阿里云的镜像地址
|
||||
maven { setUrl("https://maven.aliyun.com/repository/central") }
|
||||
maven { setUrl("https://maven.aliyun.com/repository/jcenter") }
|
||||
maven { setUrl("https://maven.aliyun.com/repository/google") }
|
||||
maven { setUrl("https://maven.aliyun.com/repository/gradle-plugin") }
|
||||
maven { setUrl("https://maven.aliyun.com/repository/public") }
|
||||
maven { setUrl("https://jitpack.io") }
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "dl"
|
||||
include(":app")
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package:mine -tag=:MESA
|
||||
@@ -0,0 +1,39 @@
|
||||
#if DL_PLATFORM == DL_PLATFORM_ANDROID
|
||||
if(str[0] != '/')
|
||||
{// 不是绝对路径,则读assets
|
||||
AAsset* asset = AAssetManager_open(
|
||||
g_android->_app->activity->assetManager,
|
||||
str.data(), AASSET_MODE_BUFFER);
|
||||
if (!asset)
|
||||
{
|
||||
log_err("AAssetManager_open失败:{}", str);
|
||||
return {};
|
||||
}
|
||||
|
||||
Buffer buf;
|
||||
auto size = AAsset_getLength(asset);
|
||||
buf.resize(size);
|
||||
|
||||
int size_read = AAsset_read(asset, buf.data(), size);
|
||||
AAsset_close(asset);
|
||||
|
||||
if (size_read < size)
|
||||
{
|
||||
log_err("AAsset_read失败:{}", str);
|
||||
return {};
|
||||
}
|
||||
|
||||
// 保存到外部存储
|
||||
std::string str_temp = PathStorage() + str;
|
||||
File::CreateFolder(File::GetFilePath(str_temp));
|
||||
std::ofstream ofs;
|
||||
ofs.open(str_temp);
|
||||
ofs.write((char*)buf.data(), buf.size());
|
||||
ofs.close();
|
||||
|
||||
log_info("安卓从assets创建文件:{} -> {}", path_name, str_temp);
|
||||
std::ifstream ret;
|
||||
ret.open(str_temp, is_binary ? (std::ifstream::binary | std::ifstream::in) : std::ifstream::in);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,226 @@
|
||||
// Demo1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
#include <cstdint>
|
||||
#include <stacktrace>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
void print(int x, int y, std::string str) {
|
||||
COORD p = { x, y };
|
||||
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), p);
|
||||
std::cout << str;
|
||||
}
|
||||
|
||||
// 2D环形遍历
|
||||
// 中心点是数学坐标(0, 0), 每环从右下(N, -N)开始逆时针遍历
|
||||
void RingSearch_Next(int& nX, int& nY)
|
||||
{
|
||||
// 开始
|
||||
if (nX == 0 && nY == 0)
|
||||
{
|
||||
nX = 1;
|
||||
nY = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// 下1环(右下)
|
||||
if (nY<0 && nX+nY== -1)
|
||||
{
|
||||
++nX; // 到右下
|
||||
|
||||
// 下1环
|
||||
++nX;
|
||||
--nY;
|
||||
return;
|
||||
}
|
||||
|
||||
// 右边线(向上)
|
||||
if (nY+nX>=0 && nY-nX<0)
|
||||
{
|
||||
++nY;
|
||||
return;
|
||||
}
|
||||
|
||||
// 上边线(向左)
|
||||
if (nY - nX >= 0 && nY + nX > 0)
|
||||
{
|
||||
--nX;
|
||||
return;
|
||||
}
|
||||
|
||||
// 左边线(向下)
|
||||
if (nY + nX <= 0 && nY - nX > 0)
|
||||
{
|
||||
--nY;
|
||||
return;
|
||||
}
|
||||
|
||||
// 下边线(向右)
|
||||
if (nY-nX<=0 && nY+nX<0)
|
||||
{
|
||||
++nX;
|
||||
return;
|
||||
}
|
||||
|
||||
// 无法到这里
|
||||
int x = 0;
|
||||
x++;
|
||||
}
|
||||
|
||||
|
||||
// 2D环形遍历
|
||||
// 中心点是数学坐标(0, 0), 每环从右下(N, -N)开始逆时针遍历
|
||||
// 根据序号直接计算点坐标
|
||||
void RingSearch_Index(int nIndex, int& nX, int& nY)
|
||||
{
|
||||
// (0, 0) 做为第0环, 且 nIndex=0
|
||||
if (nIndex <= 0)
|
||||
{
|
||||
nX = 0;
|
||||
nY = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// 次外层第K环, 共有 (2K+1)*(2K+1)个点
|
||||
|
||||
// 最外层
|
||||
int k = (sqrt(nIndex) + 1) / 2;
|
||||
|
||||
// 第k环点的序号
|
||||
int nIdx = nIndex - (2*k-1)*(2*k-1);
|
||||
|
||||
// 第k环每条边的点数
|
||||
int nL = 2 * k; // 只能包含一个端点
|
||||
|
||||
// 第几条边的第几个点
|
||||
int nD = nIdx / nL;
|
||||
int nIdx2 = nIdx % nL;
|
||||
|
||||
// (下面边的序号对应的边可以随意修改: 代表了不同的遍历方法)
|
||||
switch (nD)
|
||||
{
|
||||
case 0:
|
||||
// 第一条边(右)
|
||||
nX = k;
|
||||
nY = -k;
|
||||
|
||||
nY += nIdx2;
|
||||
break;
|
||||
case 1:
|
||||
// 第二条边(上)
|
||||
nX = k;
|
||||
nY = k;
|
||||
|
||||
nX -= nIdx2;
|
||||
break;
|
||||
case 2:
|
||||
// 第三条边(左)
|
||||
nX = -k;
|
||||
nY = k;
|
||||
|
||||
nY -= nIdx2;
|
||||
break;
|
||||
case 3:
|
||||
// 第四条边(下)
|
||||
nX = -k;
|
||||
nY = -k;
|
||||
|
||||
nX += nIdx2;
|
||||
break;
|
||||
default:
|
||||
// 出错
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 2D环形遍历
|
||||
// 中心点是数学坐标(0, 0), 每环从右下(N, -N)开始逆时针遍历
|
||||
// 根据点坐标计算序号(从0开始)
|
||||
int GetRingIndex(int nX, int nY)
|
||||
{
|
||||
if (nX == 0 && nY == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int k = max(abs(nX), abs(nY));
|
||||
|
||||
// 环内的数量
|
||||
int nN = (2 * k - 1) * (2 * k - 1);
|
||||
|
||||
// 边长
|
||||
int nL = 2 * k;
|
||||
|
||||
if (nX == k && nY != k)
|
||||
{
|
||||
// 第一边(右)
|
||||
nN += (k + nY);
|
||||
}
|
||||
else if (nY == k && nX != -k)
|
||||
{
|
||||
// 第二边(上)
|
||||
nN += 2*k;
|
||||
nN += (k - nX);
|
||||
}
|
||||
else if (nX == -k && nY != -k)
|
||||
{
|
||||
// 第三边(左)
|
||||
nN += 4 * k;
|
||||
nN += (k-nY);
|
||||
}
|
||||
else if(nY == -k && nX != k)
|
||||
{
|
||||
// 第四边(下)
|
||||
nN += 6 * k;
|
||||
nN += (k + nX);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 不会到这里
|
||||
}
|
||||
|
||||
return nN;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
int nX = 0, nY = 0;
|
||||
//std::cout << "0 : (" << nX << ", " << nY << ")" << std::endl;
|
||||
|
||||
int K = 5;
|
||||
for (int i = 1; i < (2*K+1)*(2*K+1); i++)
|
||||
{
|
||||
// 第一种算法
|
||||
RingSearch_Next(nX, nY);
|
||||
|
||||
// 第二种算法
|
||||
int nX2, nY2;
|
||||
RingSearch_Index(i, nX2, nY2);
|
||||
if (nX != nX2 || nY != nY2)
|
||||
{
|
||||
std::cout << "Error" << std::endl;
|
||||
}
|
||||
|
||||
// 反向计算序号
|
||||
int iii = GetRingIndex(nX, nY);
|
||||
if (i != iii)
|
||||
{
|
||||
std::cout << "Error" << std::endl;
|
||||
}
|
||||
|
||||
print((nX2 + 10) * 3, (nY2 + 10) * 3, std::to_string(i));
|
||||
//std::cout <<i << " : (" << nX << ", " << nY << ")" << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
set "PATH_RES=%1%"
|
||||
set "PATH_OUT=%2%"
|
||||
|
||||
set "PATH_RES=%PATH_RES:/=\%"
|
||||
set "PATH_OUT=%PATH_OUT:/=\%"
|
||||
|
||||
echo 进行资源软链接,失败请以管理员模式启动ide
|
||||
mklink /d %PATH_OUT% %PATH_RES%
|
||||
|
||||
::xcopy %PATH_RES% %PATH_OUT% /e /i /y
|
||||
@@ -0,0 +1,16 @@
|
||||
# 接收传入的两个参数:源资源路径、输出路径
|
||||
PATH_RES="$1"
|
||||
PATH_OUT="$2"
|
||||
|
||||
# 将路径中的 / 和 \ 统一为 Linux 标准的 /(兼容传入 Windows 风格路径的情况)
|
||||
PATH_RES=$(echo "$PATH_RES" | sed 's/\\/\//g')
|
||||
PATH_OUT=$(echo "$PATH_OUT" | sed 's/\\/\//g')
|
||||
|
||||
# 提示信息
|
||||
echo "进行资源软链接,若失败请检查权限"
|
||||
|
||||
# Linux 创建目录软链接(ln -s 源 目标,与 Windows mklink 顺序相反!)
|
||||
ln -s "$PATH_RES" "$PATH_OUT"
|
||||
|
||||
# 若需要替换为拷贝(注释掉上面的 ln 命令,启用下面的 cp 命令)
|
||||
# cp -rf "$PATH_RES"/* "$PATH_OUT"/ 2>/dev/null || cp -rf "$PATH_RES" "$PATH_OUT"
|
||||
@@ -0,0 +1,302 @@
|
||||
/**
|
||||
* @file dl_ui_msg_box.h
|
||||
* @brief 消息框
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 22-05-11
|
||||
*
|
||||
* @note 带有标题、内容、按钮、关闭按钮的弹窗
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifndef DL_DISABLE_RENDER
|
||||
#include "ui/dl_ui_button_sprite.h"
|
||||
#include "system/dl_system.h"
|
||||
|
||||
namespace dl::UI
|
||||
{
|
||||
//! 消息框最大按钮数量
|
||||
constexpr size_t NUM_MSG_BOX_BTN = 10;
|
||||
|
||||
//! UI消息框
|
||||
class MsgBox
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 构造
|
||||
* @param[in] bg 九图精灵作为背景
|
||||
* @param[in] txt_title 标题文本
|
||||
* @param[in] txt 内容文本
|
||||
* @param[in] btn 普通按钮
|
||||
* @param[in] btn_close 关闭按钮
|
||||
* @param[in] dx_btn 按钮(额外)间隔,艺术性调整
|
||||
*
|
||||
* @note 应该立即调用Set设置内容
|
||||
*/
|
||||
static MsgBox* Create(
|
||||
Background* bg,
|
||||
gcText txt_title,
|
||||
gcText txt,
|
||||
UI::ButtonSprite* btn,
|
||||
UI::ButtonSprite* btn_close,
|
||||
Float dx_btn = 0.0)
|
||||
{
|
||||
MsgBox* ret = new MsgBox;
|
||||
Coor* coor = Coor::Create();
|
||||
coor->SetPosition(toPosition(g_system->GetWindowSize() / 2u));
|
||||
bg->SetUI(true);
|
||||
|
||||
ret->_coor = coor;
|
||||
ret->_bg = bg;
|
||||
ret->_txtTitle = txt_title;
|
||||
ret->_txt = txt;
|
||||
ret->_btn = btn;
|
||||
ret->_btnClose = btn_close;
|
||||
ret->_dxBtn = dx_btn;
|
||||
|
||||
ret->_refresh_coor();
|
||||
ret->SetOrder(Z_DEFAULT_UI);
|
||||
return ret;
|
||||
}
|
||||
|
||||
MsgBox* Clone()
|
||||
{
|
||||
MsgBox* ret = new MsgBox(*this);
|
||||
ret->_coor = _coor->Clone();
|
||||
ret->_bg = _bg->Clone();
|
||||
ret->_btn = _btn->Clone();
|
||||
ret->_btnClose = _btnClose->Clone();
|
||||
|
||||
for (size_t i = 0; i < _allBtn.size(); ++i)
|
||||
{
|
||||
ret->_allBtn[i] = _allBtn[i]->Clone();
|
||||
}
|
||||
ret->_refresh_coor();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置内容
|
||||
* @param[in] title 标题
|
||||
* @param[in] info 内容
|
||||
* @param[in] btns 按钮内容
|
||||
*
|
||||
*/
|
||||
void Set(std::string_view title, std::string_view info, std::vector<std::string_view> all_btn)
|
||||
{
|
||||
_txtTitle->SetString(title);
|
||||
if(_bAddTab)
|
||||
_txt->SetString(std::string{ "\t" } + std::string{ info });
|
||||
else
|
||||
_txt->SetString(info);
|
||||
|
||||
//少了就新建按钮
|
||||
_numBtn = all_btn.size();
|
||||
if (_numBtn > _allBtn.size())
|
||||
{
|
||||
_allBtn.resize(_numBtn);
|
||||
for (UI::ButtonSprite*& btn : _allBtn)
|
||||
{
|
||||
if (!btn)
|
||||
{
|
||||
btn = _btn->Clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < _numBtn; ++i)
|
||||
{
|
||||
_allBtn[i]->SetString(all_btn[i]);
|
||||
}
|
||||
|
||||
//--------------------------------更新布局--------------------------------
|
||||
Float w_btn = _btn->GetSize()[0]; //按钮宽度
|
||||
Float h_btn = _btn->GetSize()[1];
|
||||
//整体宽度为 按钮宽度 + 间隔(多一个)
|
||||
Float w = w_btn * _numBtn + _dxBtn * (1 + _numBtn);
|
||||
|
||||
_txt->SetMaxW(w);//设置文本宽度
|
||||
|
||||
Float h_txt = _txt->GetSize()[1]; //文本高度
|
||||
Float h_title = _txtTitle->GetSize()[1];//标题高度
|
||||
//整体高度 标题 + 文本 + 按钮
|
||||
Float h = h_title + h_txt * 1 + h_btn * 1;
|
||||
_txt->SetCenter();
|
||||
Position size{ w, h };
|
||||
Position size_half{ size * 0.5f };
|
||||
_bg->SetSize(size);
|
||||
|
||||
//设置位置
|
||||
_bg->GetCoor()->SetPosition(toPosition(_bg->GetOffset()) - size_half);
|
||||
_txtTitle->SetPositionAlign(-size_half, Align::LC);
|
||||
_btnClose->GetCoor()->SetPosition({ size_half[0], -size_half[1] });
|
||||
|
||||
if (_numBtn > 0)
|
||||
{
|
||||
//偏移为 负的 按钮总宽度的一半(间隔少一个) + 半个按钮
|
||||
Float sx_btn = (w_btn * _numBtn + _dxBtn * (_numBtn - 1)) * -0.5_f + w_btn * 0.5_f;
|
||||
for (std::size_t i = 0; i < _numBtn; ++i)
|
||||
{
|
||||
_allBtn[i]->GetCoor()->SetPosition({ sx_btn + i * (w_btn + _dxBtn), size_half[1] });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief 设置内容,以语言文件配置的名称
|
||||
*
|
||||
*/
|
||||
void Set(std::string_view str)
|
||||
{
|
||||
std::string_view str_title = lang("msg_box", std::string{ str } + "_title");
|
||||
std::string_view str_info = lang("msg_box", std::string{ str } + "_info");
|
||||
std::vector<std::string_view> all_btn;
|
||||
for (std::size_t i = 0; i < NUM_MSG_BOX_BTN; ++i)
|
||||
{
|
||||
std::string str_name = fmt::format("{}_{}", str, i);
|
||||
auto str = g_lang->GetCheck("msg_box", str_name);
|
||||
if (!str.has_value())
|
||||
{
|
||||
break;
|
||||
}
|
||||
all_btn.push_back(str.value());
|
||||
}
|
||||
|
||||
Set(str_title, str_info, all_btn);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
_btnClose->Update();
|
||||
for (size_t i = 0; i < _numBtn; ++i)
|
||||
{
|
||||
_allBtn[i]->Update();
|
||||
}
|
||||
|
||||
if (_posPick)
|
||||
{
|
||||
if (g_input->KeyUp(MouseCode::LEFT))
|
||||
_posPick.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_input->KeyDown(MouseCode::LEFT) && IsPickupTitle())
|
||||
{
|
||||
_posPick = _coor->WorldToThis(toPosition(g_input->GetCursorPosition()));
|
||||
}
|
||||
}
|
||||
|
||||
//左键拖动
|
||||
if (_posPick)
|
||||
{
|
||||
Point pos = g_input->GetCursorPosition();
|
||||
_coor->SetPosition(toPosition(pos) - _posPick.value());
|
||||
}
|
||||
}
|
||||
|
||||
void Render()
|
||||
{
|
||||
_bg->Render();
|
||||
_txtTitle->Render();
|
||||
_txt->Render();
|
||||
}
|
||||
/**
|
||||
* @brief 返回点击按钮索引,返回-1代表没有点击
|
||||
*/
|
||||
size_t GetClick()
|
||||
{
|
||||
for (size_t i = 0; i < _numBtn; ++i)
|
||||
{
|
||||
if (_allBtn[i]->IsClick())
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/**
|
||||
* @brief 是否点击了关闭按钮
|
||||
*/
|
||||
bool IsClickClose()
|
||||
{
|
||||
return _btnClose->IsClick();
|
||||
}
|
||||
/**
|
||||
* @brief 是否选中标题栏
|
||||
*/
|
||||
bool IsPickupTitle()
|
||||
{
|
||||
if (_bg->IsPickup())
|
||||
{//按钮会屏蔽bg的IsPickup
|
||||
Position pos = _txtTitle->GetCoor()->WorldToThis(toPosition(g_input->GetCursorPosition()));
|
||||
if (pos[1] < _txtTitle->GetSize()[1])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetOrder(float order)
|
||||
{
|
||||
_txt->SetOrder(Math::OffsetOrder(order, 0, 0, -1));
|
||||
_txtTitle->SetOrder(Math::OffsetOrder(order, 0, 0, -1));
|
||||
_btnClose->SetOrder(Math::OffsetOrder(order, 0, 0, -1));
|
||||
_btn->SetOrder(Math::OffsetOrder(order, 0, 0, -1));
|
||||
for (auto& iter : _allBtn)
|
||||
{
|
||||
iter->SetOrder(Math::OffsetOrder(order, 0, 0, -1));
|
||||
}
|
||||
_bg->SetOrder(Math::OffsetOrder(order, 0, 0, 0));
|
||||
}
|
||||
|
||||
~MsgBox()
|
||||
{
|
||||
delete _coor;
|
||||
delete _bg;
|
||||
delete _btn;
|
||||
delete _btnClose;
|
||||
for (auto& iter : _allBtn)
|
||||
delete iter;
|
||||
}
|
||||
private:
|
||||
MsgBox():
|
||||
_coor{nullptr},
|
||||
_bg{nullptr},
|
||||
_btn{nullptr},
|
||||
_btnClose{nullptr},
|
||||
_numBtn{0},
|
||||
_bAddTab{true}
|
||||
{}
|
||||
Coor* _coor;
|
||||
|
||||
Background* _bg;
|
||||
gcText _txtTitle;
|
||||
gcText _txt;
|
||||
UI::ButtonSprite* _btn;
|
||||
UI::ButtonSprite* _btnClose;
|
||||
|
||||
//动态改变长度,多余的不会自动删除,所以需要标记使用数量
|
||||
std::vector<UI::ButtonSprite*> _allBtn;
|
||||
std::size_t _numBtn;
|
||||
|
||||
Float _dxBtn;
|
||||
|
||||
std::optional<Position> _posPick;//被拾取位置(差值,相加即可)(直到再抬起)
|
||||
bool _bAddTab;//添加段首缩进
|
||||
|
||||
void _refresh_coor()
|
||||
{
|
||||
_bg->GetCoor()->SetParent(_coor);
|
||||
_txtTitle->GetCoor()->SetParent(_coor);
|
||||
_txt->GetCoor()->SetParent(_coor);
|
||||
_btn->GetCoor()->SetParent(_coor);
|
||||
_btnClose->GetCoor()->SetParent(_coor);
|
||||
|
||||
for (size_t i = 0; i < _allBtn.size(); ++i)
|
||||
{
|
||||
_allBtn[i]->GetCoor()->SetParent(_coor);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,60 @@
|
||||
|
||||
if(true)
|
||||
{
|
||||
struct DataSubType
|
||||
{
|
||||
int _min = INT_MAX;
|
||||
int _max = 0;
|
||||
};
|
||||
struct DataType
|
||||
{
|
||||
std::string _name;
|
||||
std::map<std::string, DataSubType> _allSub;
|
||||
};
|
||||
struct Data
|
||||
{
|
||||
std::map<int, DataType> _data;
|
||||
};
|
||||
Data data;
|
||||
std::string str = File::GetString("F:/All/收藏/音效光碟/C/list.txt");
|
||||
std::vector<std::string> vec_str;
|
||||
split(str, '\n', vec_str);
|
||||
for (size_t i = 0; i + 3 < vec_str.size(); i += 3)
|
||||
{
|
||||
int id = String::toInt(vec_str[i]);
|
||||
int type = String::toInt(vec_str[i + 1]);
|
||||
std::string name = vec_str[i + 2];
|
||||
std::string_view type_sub = String::GetBeginUntilNumber(name);
|
||||
//log_info("{}, {}, {}, {}", type, type_sub, name, id);
|
||||
|
||||
DataType* group;
|
||||
if (type == -1)
|
||||
{
|
||||
group = &data._data[id];
|
||||
group->_name = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
group = &data._data[type];
|
||||
|
||||
DataSubType& sub = group->_allSub[std::string{ type_sub }];
|
||||
if (id < sub._min)
|
||||
sub._min = id;
|
||||
else if (id > sub._max)
|
||||
sub._max = id;
|
||||
}
|
||||
|
||||
}
|
||||
// export
|
||||
std::string str_out;
|
||||
for (auto& iter : data._data)
|
||||
{
|
||||
for (auto& iter1 : iter.second._allSub)
|
||||
{
|
||||
str_out += fmt::format("{},{},{}-{}\n",
|
||||
iter.second._name, iter1.first, iter1.second._min, iter1.second._max);
|
||||
}
|
||||
}
|
||||
|
||||
File::SaveString(str_out, "D:/1.txt");
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
@echo off
|
||||
|
||||
@rem 查找cmake安装位置
|
||||
vswhere.exe -latest -products * -requires Microsoft.VisualStudio.Component.VC.CMake.Project -find "**/CMake/bin/cmake.exe" >temp.txt
|
||||
set/p PATH_CMAKE=<temp.txt
|
||||
del temp.txt
|
||||
echo cmake位置:%PATH_CMAKE%
|
||||
|
||||
@rem 查找ninja安装位置
|
||||
vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.CMake.Project -find "**/CMake/Ninja/ninja.exe" >temp.txt
|
||||
set/p PATH_NINJA=<temp.txt
|
||||
del temp.txt
|
||||
echo Ninja位置:%PATH_NINJA%
|
||||
|
||||
@rem 查找vs安装位置
|
||||
vswhere.exe -latest -prerelease -property installationPath >temp.txt
|
||||
set/p PATH_VS_ROOT=<temp.txt
|
||||
del temp.txt
|
||||
|
||||
set PATH_VCVARS=%PATH_VS_ROOT%\VC\Auxiliary\Build\vcvarsall.bat
|
||||
echo vs编译脚本位置:%PATH_VCVARS%
|
||||
|
||||
:: 1. 获取VS安装路径
|
||||
for /f "usebackq tokens=*" %%i in (`vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do (
|
||||
set "VS_PATH=%%i"
|
||||
)
|
||||
|
||||
:: 2. 获取MSVC版本号
|
||||
for /f "usebackq tokens=*" %%v in (`dir /b "%VS_PATH%\VC\Tools\MSVC"`) do (
|
||||
set "MSVC_VER=%%v"
|
||||
)
|
||||
|
||||
:: 3. 拼接 cl.exe 路径(x64)
|
||||
set "CL_PATH=%VS_PATH%\VC\Tools\MSVC\%MSVC_VER%\bin\Hostx64\x64\cl.exe"
|
||||
|
||||
|
||||
pause
|
||||
|
||||
@REM 解析工程(cmake)
|
||||
%PATH_CMAKE% -G "Ninja" -DCMAKE_C_COMPILER:STRING="cl.exe" -DCMAKE_CXX_COMPILER:STRING=%CL_PATH% -DODE_WITH_DEMOS:BOOL="FALSE" -DCMAKE_BUILD_TYPE:STRING="Debug" -DCMAKE_INSTALL_PREFIX:PATH="D:/dl/out/install/x64-debug" -DCMAKE_MAKE_PROGRAM=%PATH_NINJA% "D:\dl"
|
||||
|
||||
|
||||
pause
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
#ifndef NDEBUG
|
||||
#pragma comment(lib, "dlx.lib")
|
||||
#pragma comment(lib, "libiconvStatic.lib")
|
||||
#pragma comment(lib, "fmtd.lib")
|
||||
#pragma comment(lib, "freetyped.lib")
|
||||
#pragma comment(lib, "lunasvg.lib")
|
||||
#pragma comment(lib, "lz4.lib")
|
||||
#pragma comment(lib, "libwebp.lib")
|
||||
#pragma comment(lib, "OpenXLSXd.lib")
|
||||
#pragma comment(lib, "zlibstaticd.lib")
|
||||
#pragma comment(lib, "infowared.lib")
|
||||
#pragma comment(lib, "angelscriptd.lib")
|
||||
#else
|
||||
#pragma comment(lib, "dlx.lib")
|
||||
#pragma comment(lib, "libiconvStatic.lib")
|
||||
#pragma comment(lib, "fmt.lib")
|
||||
#pragma comment(lib, "freetype.lib")
|
||||
#pragma comment(lib, "lunasvg.lib")
|
||||
#pragma comment(lib, "lz4.lib")
|
||||
#pragma comment(lib, "libwebp.lib")
|
||||
#pragma comment(lib, "OpenXLSX.lib")
|
||||
#pragma comment(lib, "zlibstatic.lib")
|
||||
#pragma comment(lib, "infoware.lib")
|
||||
#pragma comment(lib, "angelscript.lib")
|
||||
#endif
|
||||
|
||||
|
||||
#pragma comment(lib, "FLAC.lib")
|
||||
#pragma comment(lib, "glfw3.lib")
|
||||
#pragma comment(lib, "OpenAL32.lib")
|
||||
#pragma comment(lib, "FLAC.lib")
|
||||
#pragma comment(lib, "vorbis.lib")
|
||||
#pragma comment(lib, "vorbisfile.lib")
|
||||
#pragma comment(lib, "ogg.lib")
|
||||
#pragma comment(lib, "plutovg.lib")
|
||||
#pragma comment(lib, "lua.lib")
|
||||
#pragma comment(lib, "wcwidth.lib")
|
||||
#pragma comment(lib, "Jolt.lib")
|
||||
#pragma comment(lib, "ktx.lib")
|
||||
#pragma comment(lib, "tinygltf.lib")
|
||||
|
||||
#pragma comment(lib, "libcurl.lib")
|
||||
#pragma comment(lib, "libcrypto_static.lib")
|
||||
#pragma comment(lib, "libssl_static.lib")
|
||||
#pragma comment(lib, "vulkan-1.lib")
|
||||
|
||||
#pragma comment(lib, "Wldap32.lib")
|
||||
#pragma comment(lib, "Crypt32.lib")
|
||||
#pragma comment(lib, "version.lib")
|
||||
#pragma comment(lib, "wbemuuid.lib")
|
||||
@@ -0,0 +1,25 @@
|
||||
echo off
|
||||
|
||||
set PATH_SRC=..\..
|
||||
|
||||
rd .\dll /s /q
|
||||
rd .\include /s /q
|
||||
rd .\lib /s /q
|
||||
|
||||
set PATH_INSTALL=%PATH_SRC%\out\install
|
||||
xcopy %PATH_INSTALL%\x86-debug\include .\include\x86\debug /s /e /i /y
|
||||
xcopy %PATH_INSTALL%\x64-debug\include .\include\x64\debug /s /e /i /y
|
||||
xcopy %PATH_INSTALL%\x86-release\include .\include\x86\release /s /e /i /y
|
||||
xcopy %PATH_INSTALL%\x64-release\include .\include\x64\release /s /e /i /y
|
||||
|
||||
xcopy %PATH_INSTALL%\x86-debug\lib\*.lib .\lib\x86\debug /s /e /i /y
|
||||
xcopy %PATH_INSTALL%\x64-debug\lib\*.lib .\lib\x64\debug /s /e /i /y
|
||||
xcopy %PATH_INSTALL%\x86-release\lib\*.lib .\lib\x86\release /s /e /i /y
|
||||
xcopy %PATH_INSTALL%\x64-release\lib\*.lib .\lib\x64\release /s /e /i /y
|
||||
|
||||
set PATH_VLD=%PATH_SRC%\third\vld
|
||||
xcopy %PATH_VLD%\bin\Win32\ .\bin\x86\debug /s /e /i /y
|
||||
xcopy %PATH_VLD%\bin\Win64\ .\bin\x64\debug /s /e /i /y
|
||||
|
||||
|
||||
pause
|
||||
@@ -0,0 +1,18 @@
|
||||
1.由于msvc在26年5月份后的一次更新后,编译不识别头文件修改
|
||||
特此改为非源码集成dl的方式
|
||||
2.使用cmake的安装(install)后,执行此目录的“拷贝dl库”,便可和原生vs项目开发类似
|
||||
3.链接方法
|
||||
附加包含目录
|
||||
..\dl\build\library\include\x64\$(Configuration)\dl
|
||||
..\dl\build\library\include\x64\$(Configuration)
|
||||
附加库目录
|
||||
..\dl\build\library\lib\x64\$(Configuration);%(AdditionalLibraryDirectories)
|
||||
代码中加入link.txt内容
|
||||
4.其他注意事项
|
||||
设置调试目录
|
||||
设置命令行 /utf-8
|
||||
设置C++语言版本 >=20
|
||||
设置运行库为MT
|
||||
可能需要设置子系统为“窗口”
|
||||
拷贝vld、dl/res到资源目录
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
1.用AndroidStudio打开 android 即可编译安卓
|
||||
|
||||
2.backup备份文件,无用
|
||||
|
||||
3.library 使用预编译dl,使用vs开发
|
||||
@@ -0,0 +1,56 @@
|
||||
1.常见文件
|
||||
新建文件:touch 1.txt
|
||||
cmake设置多线程编译(0不会用满):Ctrl+, 然后设置 cmake.parallelJobs
|
||||
使用clangd进行智能提示:安装后,cmake添加
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
然后 将 compile_commands.json拷贝到项目根目录
|
||||
使用lldb调试:安装CodeLLDB插件,自动更新比较慢从github
|
||||
libreOffice:Office替代
|
||||
GIMP:图像编辑
|
||||
|
||||
|
||||
2.安装git
|
||||
sudo apt install git
|
||||
|
||||
3.拉取仓库
|
||||
git clone https://gitee.com/lveyou/dl.git
|
||||
|
||||
4.安装vscode
|
||||
安装中文插件
|
||||
安装cmake插件(CMake Tools)
|
||||
|
||||
5.安装cmake、clang等
|
||||
sudo apt install cmake
|
||||
sudo apt install clang
|
||||
# glfw
|
||||
sudo apt install libwayland-dev libxkbcommon-dev xorg-dev
|
||||
# curl
|
||||
sudo apt install libcurl4-openssl-dev
|
||||
# vulkan
|
||||
sudo apt install libvulkan-dev vulkan-tools
|
||||
# openal
|
||||
sudo apt install libopenal-dev
|
||||
|
||||
---------------------------------------------------------------------
|
||||
Wayland 和 X11 的依赖关系
|
||||
|
||||
默认情况下,Wayland 和 X11 后端均在 Linux 和其他类 Unix 系统(macOS 除外)上启用。要禁用其中一个或两个选项,请在生成构建文件时,在下一步设置 GLFW_BUILD_WAYLAND 或 GLFW_BUILD_X11 CMake 选项。
|
||||
|
||||
要为 Wayland 和 X11 编译 GLFW,需要安装 X11、Wayland 和 xkcommon 开发包。在某些系统上,还需要一些其他软件包。上述开发包中,没有一项是使用已编译的GLFW库来构建或运行程序的。
|
||||
|
||||
在 Debian 以及 Ubuntu 和 Linux Mint 等衍生产品上,你需要 libwayland-dev 而且 libxkbcommon-dev 用于 Wayland 和 the 的软件包 xorg-dev 用于 X11 的元包编译。这些将拉入所有其他依赖项。
|
||||
sudo apt install libwayland-dev libxkcommon-dev xorg-dev
|
||||
|
||||
在Fedora和Red Hat等衍生产品上,您需要 wayland-devel 而且 libxkbcommon-devel 用于 Wayland 和 the 的软件包 libXcursor-devel, libXi-devel, libXinerama-devel 而且 libXrandr-devel 用于 X11 编译的软件包。这些将拉入所有其他依赖项。
|
||||
sudo dnf install wayland-devel libxkbcommon-devel libXcursor-devel libXi-devel libXinerama-devel libXrandr-devel
|
||||
|
||||
在 FreeBSD 上,你需要 wayland, libxkbcommon 而且 evdev-proto 用于为 Wayland 编译的软件包。X11 头部安装在终端用户的 X11 包上,因此如果你的 X 服务器正在运行,则应该也具备这些头。如果不行,请安装 xorgproto 用于 X11 的编译包。
|
||||
pkg install wayland libxkbcommon evdev-proto xorgproto
|
||||
|
||||
在Cygwin Wayland上不支持,但您需要 libXcursor-devel, libXi-devel, libXinerama-devel, libXrandr-devel 而且 libXrender-devel 用于 X11 编译的软件包。这些可以在 GUI 安装程序的 Libs 部分找到,并会拉入所有其他依赖项。
|
||||
|
||||
拥有所需的依赖项后,请继续使用 CMake 生成构建文件。
|
||||
|
||||
---------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
cloc-2.04.exe ../dl
|
||||
cloc-2.04.exe ../project
|
||||
cloc-2.04.exe ../project/dl_unit_test
|
||||
cloc-2.04.exe ../third
|
||||
cloc-2.04.exe ../project/hs/src
|
||||
pause
|
||||
@@ -0,0 +1,267 @@
|
||||
cmake_minimum_required (VERSION 3.5)
|
||||
project ("dlx")
|
||||
#add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/source-charset:utf-8>")
|
||||
#add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/execution-charset:utf-8>")
|
||||
|
||||
# 设置处理
|
||||
if (DL_DISABLE_RENDER)
|
||||
add_compile_definitions(DL_DISABLE_RENDER)
|
||||
endif()
|
||||
if (DL_DISABLE_AUDIO)
|
||||
add_compile_definitions(DL_DISABLE_AUDIO)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
# 禁用windows min max宏(兼容性起见,还是不禁用)
|
||||
# add_definitions(-DNOMINMAX)
|
||||
# 关闭windows相关警告
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
# windows(这个设置已经不起用了,可能某些预编译的库用到了不兼容win7的系统函数)
|
||||
add_definitions(-D_WIN32_WINNT=0x0601)
|
||||
endif()
|
||||
|
||||
# dl源文件
|
||||
#FILE(GLOB_RECURSE SRC_LIST CONFIGURE_DEPENDS "*.cpp" "*.h")
|
||||
#aux_source_directory(${CMAKE_SOURCE_DIR}/dl SRC_LIST)
|
||||
#aux_source_directory(${CMAKE_SOURCE_DIR}/dl/base SRC_LIST)
|
||||
#aux_source_directory(${CMAKE_SOURCE_DIR}/dl/io SRC_LIST)
|
||||
#aux_source_directory(${CMAKE_SOURCE_DIR}/dl/math SRC_LIST)
|
||||
#aux_source_directory(${CMAKE_SOURCE_DIR}/dl/memory SRC_LIST)
|
||||
#aux_source_directory(${CMAKE_SOURCE_DIR}/dl/render SRC_LIST)
|
||||
#aux_source_directory(${CMAKE_SOURCE_DIR}/dl/vk SRC_LIST)
|
||||
#aux_source_directory(${CMAKE_SOURCE_DIR}/dl/ui SRC_LIST)
|
||||
#aux_source_directory(${CMAKE_SOURCE_DIR}/dl/misc SRC_LIST)
|
||||
#aux_source_directory(${CMAKE_SOURCE_DIR}/dl/script SRC_LIST)
|
||||
#aux_source_directory(${CMAKE_SOURCE_DIR}/dl/system SRC_LIST)
|
||||
#aux_source_directory(${CMAKE_SOURCE_DIR}/dl/tool SRC_LIST)
|
||||
|
||||
file(GLOB_RECURSE
|
||||
SRC_LIST
|
||||
${CMAKE_SOURCE_DIR}/dl/*.cpp
|
||||
${CMAKE_SOURCE_DIR}/dl/*.h
|
||||
)
|
||||
|
||||
# 第三方库源文件
|
||||
list(APPEND SRC_LIST ${CMAKE_SOURCE_DIR}/third/qrcodegen/qrcodegen.cpp)
|
||||
list(APPEND SRC_LIST ${CMAKE_SOURCE_DIR}/third/tinyxml2/tinyxml2.cpp)
|
||||
list(APPEND SRC_LIST ${CMAKE_SOURCE_DIR}/third/sqlite/sqlite3.c)
|
||||
|
||||
foreach(var ${SRC_LIST})
|
||||
message("${var}")
|
||||
endforeach()
|
||||
add_library (${PROJECT_NAME} ${SRC_LIST})
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "/EHsc")
|
||||
#target_compile_options(${PROJECT_NAME} PRIVATE "/Qvec-report:2")
|
||||
#target_compile_options(${PROJECT_NAME} PRIVATE "/arch:AVX")
|
||||
endif()
|
||||
|
||||
|
||||
# 自包含头文件
|
||||
include_directories(${CMAKE_SOURCE_DIR}/dl)
|
||||
# linux 无法识别上面的头文件目录
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
#set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 23)
|
||||
endif()
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
# vld
|
||||
include_directories(${CMAKE_SOURCE_DIR}/third/vld/include)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/third/vld/lib/${ARCH}/vld.lib)
|
||||
endif()
|
||||
|
||||
# lz4
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE lz4)
|
||||
# fmt
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE fmt)
|
||||
# json
|
||||
include_directories(${CMAKE_SOURCE_DIR}/third/json)
|
||||
# lunasvg
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE lunasvg)
|
||||
# libwebp
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE webp)
|
||||
# OpenXLSX
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE OpenXLSX::OpenXLSX)
|
||||
# tinyxml2
|
||||
include_directories(${CMAKE_SOURCE_DIR}/third/tinyxml2)
|
||||
# zlib
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE zlibstatic)
|
||||
|
||||
#---------------------------render----------------------------
|
||||
if (NOT DL_DISABLE_RENDER)
|
||||
# glfw
|
||||
if (NOT CMAKE_SYSTEM_NAME MATCHES "Android")
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE glfw)
|
||||
endif()
|
||||
|
||||
# vulkan
|
||||
if (DL_VULKAN_DIR MATCHES "AUTO")
|
||||
find_package(Vulkan REQUIRED)
|
||||
include_directories(${Vulkan_INCLUDE_DIRS})
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${Vulkan_LIBRARIES})
|
||||
else()
|
||||
if(CMAKE_CL_64)
|
||||
include_directories(${DL_VULKAN_DIR}/Include)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${DL_VULKAN_DIR}/Lib/vulkan-1.lib)
|
||||
else()
|
||||
include_directories(${DL_VULKAN_DIR}/Include)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${DL_VULKAN_DIR}/Lib32/vulkan-1.lib)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
# stb_image
|
||||
include_directories(${CMAKE_SOURCE_DIR}/third/stb_image)
|
||||
# qrcodegen
|
||||
include_directories(${CMAKE_SOURCE_DIR}/third/qrcodegen)
|
||||
# iconv
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/third/libiconv/include)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/third/libiconv/lib/${ARCH}/libiconvStatic.lib)
|
||||
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Android")
|
||||
#include_directories(${CMAKE_SOURCE_DIR}/third/libiconv/include)
|
||||
#target_link_libraries(${PROJECT_NAME} PRIVATE Libiconv)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
# 查找 iconv 库(兼容系统/新版)
|
||||
find_library(ICONV_LIBRARY NAMES iconv libiconv)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${ICONV_LIBRARY})
|
||||
endif()
|
||||
|
||||
if (NOT DL_DISABLE_RENDER)
|
||||
# freetype
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE freetype)
|
||||
# tinygltf
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE tinygltf)
|
||||
endif()
|
||||
|
||||
#---------------------------audio----------------------------
|
||||
if (NOT DL_DISABLE_AUDIO)
|
||||
# ogg
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ogg)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE vorbis)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE vorbisfile)
|
||||
# flac
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE FLAC++)
|
||||
# mp3
|
||||
include_directories(${CMAKE_SOURCE_DIR}/third/minimp3)
|
||||
# openal
|
||||
if (NOT CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE OpenAL)
|
||||
else()
|
||||
find_package(OpenAL REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE openal)
|
||||
endif()
|
||||
endif()
|
||||
#rtmidi
|
||||
if (NOT CMAKE_SYSTEM_NAME MATCHES "Android")
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE rtmidi)
|
||||
endif()
|
||||
|
||||
# angelscript
|
||||
include_directories(${CMAKE_SOURCE_DIR}/third/angelscript/add_on)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE angelscript)
|
||||
# lua
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE lua)
|
||||
# LuaBridge3
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE LuaBridge)
|
||||
# infoware
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
#OR CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE infoware)
|
||||
endif()
|
||||
# wcwidth
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE wcwidth)
|
||||
# simde
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE simde)
|
||||
# magic enmu
|
||||
include_directories(${CMAKE_SOURCE_DIR}/third/magic_enum/include)
|
||||
# cpp-subprocess
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE cpp-subprocess::subprocess)
|
||||
# ktx
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ktx)
|
||||
# JoltPhysics
|
||||
include_directories(${CMAKE_SOURCE_DIR}/third/JoltPhysics)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Jolt)
|
||||
# mimalloc
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE mimalloc-static)
|
||||
endif()
|
||||
# openssl
|
||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||
# curl
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE libcurl)
|
||||
# asio
|
||||
include_directories(${CMAKE_SOURCE_DIR}/third/asio/include)
|
||||
# sqlite
|
||||
include_directories(${CMAKE_SOURCE_DIR}/third/sqlite)
|
||||
|
||||
# tinyobjloader
|
||||
include_directories(${CMAKE_SOURCE_DIR}/third/tinyobjloader)
|
||||
# tinygltf
|
||||
#include_directories(${CMAKE_SOURCE_DIR}/third/tinygltf)
|
||||
|
||||
# 安卓必要库
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Android")
|
||||
find_package(game-activity REQUIRED CONFIG)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC log android
|
||||
game-activity::game-activity_static)
|
||||
# 解决 UnsatisfiedLinkError 问题
|
||||
set(CMAKE_SHARED_LINKER_FLAGS
|
||||
"${CMAKE_SHARED_LINKER_FLAGS} -u \
|
||||
Java_com_google_androidgamesdk_GameActivity_initializeNativeCode")
|
||||
endif()
|
||||
|
||||
# 创建软链接到项目根目录
|
||||
if(NOT MSVC)
|
||||
add_custom_command(
|
||||
TARGET ${PROJECT_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
${CMAKE_BINARY_DIR}/compile_commands.json
|
||||
${CMAKE_SOURCE_DIR}/compile_commands.json
|
||||
COMMENT "创建软链接:`compile_commands.json"
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
# 安装(方便修改,可以直接使用头文件)
|
||||
install(DIRECTORY "./"
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/include/dl/
|
||||
FILES_MATCHING PATTERN "*.h")
|
||||
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/third/json/json.hpp DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/third/tinyxml2/tinyxml2.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/third/asio/include/
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/include
|
||||
FILES_MATCHING PATTERN "*.hpp" PATTERN "*.ipp")
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/third/magic_enum/include/ DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
|
||||
|
||||
# CrashRpt
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Windows" AND
|
||||
CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/third/CrashRpt/include/ DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/third/CrashRpt/${ARCH}/CrashRpt1403.lib DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/third/CrashRpt/${ARCH}/CrashRpt1403.dll DESTINATION ${CMAKE_INSTALL_PREFIX}/bin/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/third/CrashRpt/${ARCH}/CrashSender1403.exe DESTINATION ${CMAKE_INSTALL_PREFIX}/bin/)
|
||||
endif()
|
||||
|
||||
# vulkan
|
||||
install(FILES ${Vulkan_LIBRARIES} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/)
|
||||
|
||||
# copy
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/third/vld/lib/${ARCH}/vld.lib DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/third/libiconv/lib/${ARCH}/libiconvStatic.lib DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/../third/glfw/src/glfw3.lib DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/)
|
||||
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/third/openssl/${ARCH}/${RT}/libcrypto_static.lib DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/third/openssl/${ARCH}/${RT}/libssl_static.lib DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/)
|
||||
|
||||
|
||||
install(TARGETS dlx
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
|
||||
@@ -0,0 +1,362 @@
|
||||
/**
|
||||
* @file dl_array.h
|
||||
* @brief 类似std::array,增加xyzw、wh等成员访问
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 26-01-22
|
||||
*
|
||||
* @note 效率与std::array相当
|
||||
* std::array与原生数组不能简单互转
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
#if 1
|
||||
namespace dl
|
||||
{
|
||||
//#define DL_ALIGN16
|
||||
//#define DL_ALIGN16 alignas(16)
|
||||
|
||||
//! Array
|
||||
template<typename T, size_t N>
|
||||
class Array
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
T _data[N];
|
||||
Array() = default;
|
||||
|
||||
constexpr Array(std::initializer_list<T> data)
|
||||
{
|
||||
size_t i = 0;
|
||||
for (auto iter : data)
|
||||
{
|
||||
_data[i] = iter;
|
||||
++i;
|
||||
if (i >= N)
|
||||
return;
|
||||
}
|
||||
for (; i < N; ++i)
|
||||
_data[i] = {};
|
||||
}
|
||||
constexpr T& operator[](size_t i)
|
||||
{
|
||||
assert(i < N);
|
||||
return _data[i];
|
||||
}
|
||||
constexpr const T& operator[](size_t i) const
|
||||
{
|
||||
assert(i < N);
|
||||
return _data[i];
|
||||
}
|
||||
constexpr T& at(size_t i)
|
||||
{
|
||||
if (i >= N)
|
||||
throw std::out_of_range("dl::Array::at outrange");
|
||||
return _data[i];
|
||||
}
|
||||
constexpr const T& at(size_t i) const
|
||||
{
|
||||
if (i >= N)
|
||||
throw std::out_of_range("dl::Array::at outrange");
|
||||
return _data[i];
|
||||
}
|
||||
|
||||
T* begin() { return &_data[0]; }
|
||||
T* end() { return &_data[N]; }
|
||||
const T* begin() const { return &_data[0]; }
|
||||
const T* end() const { return &_data[N]; }
|
||||
bool empty() const { return false; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
requires std::is_trivial_v<T>
|
||||
class Array<T, 2>
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
T x;
|
||||
T y;
|
||||
};
|
||||
struct
|
||||
{
|
||||
T w;
|
||||
T h;
|
||||
};
|
||||
struct
|
||||
{
|
||||
T col;
|
||||
T row;
|
||||
};
|
||||
T _data[2];
|
||||
};
|
||||
Array() = default;
|
||||
|
||||
constexpr Array(std::initializer_list<T> data)
|
||||
{
|
||||
size_t N_LIST = std::size(data);
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
_data[i] = i < N_LIST ? *(data.begin() + i) : T{};
|
||||
}
|
||||
constexpr const T& Get(size_t i) const
|
||||
{
|
||||
assert(i < 2);
|
||||
return _data[i];
|
||||
}
|
||||
constexpr T& operator[](size_t i)
|
||||
{
|
||||
assert(i < 2);
|
||||
return _data[i];
|
||||
}
|
||||
constexpr const T& operator[](size_t i) const
|
||||
{
|
||||
assert(i < 2);
|
||||
return _data[i];
|
||||
}
|
||||
constexpr T& at(size_t i)
|
||||
{
|
||||
assert(i < 2);
|
||||
if (i < 2)
|
||||
return _data[i];
|
||||
else
|
||||
throw std::out_of_range("dl::Array::at outrange");
|
||||
}
|
||||
constexpr const T& at(size_t i) const
|
||||
{
|
||||
assert(i < 2);
|
||||
if (i < 2)
|
||||
return _data[i];
|
||||
else
|
||||
throw std::out_of_range("dl::Array::at outrange");
|
||||
}
|
||||
|
||||
T* begin() { return &x; }
|
||||
T* end() { return &x + 2; }
|
||||
const T* begin() const { return &x; }
|
||||
const T* end() const { return &x + 2; }
|
||||
bool empty() const { return false; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
requires std::is_trivial_v<T>
|
||||
class Array<T, 3>
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
T x;
|
||||
T y;
|
||||
T z;
|
||||
};
|
||||
struct
|
||||
{
|
||||
T col;
|
||||
T row;
|
||||
T dep;
|
||||
};
|
||||
T _data[3];
|
||||
};
|
||||
Array() = default;
|
||||
|
||||
constexpr Array(std::initializer_list<T> data)
|
||||
{
|
||||
size_t N_LIST = std::size(data);
|
||||
for (size_t i = 0; i < 3; ++i)
|
||||
_data[i] = i < N_LIST ? *(data.begin() + i) : T{};
|
||||
}
|
||||
constexpr const T& Get(size_t i) const
|
||||
{
|
||||
assert(i < 3);
|
||||
return _data[i];
|
||||
}
|
||||
constexpr T& operator[](size_t i)
|
||||
{
|
||||
assert(i < 3);
|
||||
return _data[i];
|
||||
}
|
||||
constexpr const T& operator[](size_t i) const
|
||||
{
|
||||
assert(i < 3);
|
||||
return _data[i];
|
||||
}
|
||||
constexpr T& at(size_t i)
|
||||
{
|
||||
assert(i < 3);
|
||||
if (i < 3)
|
||||
return _data[i];
|
||||
else
|
||||
throw std::out_of_range("dl::Array::at outrange");
|
||||
}
|
||||
constexpr const T& at(size_t i) const
|
||||
{
|
||||
assert(i < 3);
|
||||
if (i < 3)
|
||||
return _data[i];
|
||||
else
|
||||
throw std::out_of_range("dl::Array::at outrange");
|
||||
}
|
||||
|
||||
T* begin() { return &x; }
|
||||
T* end() { return &x + 3; }
|
||||
const T* begin() const { return &x; }
|
||||
const T* end() const { return &x + 3; }
|
||||
bool empty() const { return false; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
requires std::is_trivial_v<T>
|
||||
class Array<T, 4>
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
T x;
|
||||
T y;
|
||||
T z;
|
||||
T w;
|
||||
};
|
||||
struct
|
||||
{
|
||||
T lt;
|
||||
T rt;
|
||||
T rb;
|
||||
T lb;
|
||||
};
|
||||
struct
|
||||
{
|
||||
T r;
|
||||
T g;
|
||||
T b;
|
||||
T a;
|
||||
};
|
||||
struct
|
||||
{
|
||||
T left;
|
||||
T top;
|
||||
T right;
|
||||
T bottom;
|
||||
};
|
||||
T _data[4];
|
||||
};
|
||||
Array() = default;
|
||||
|
||||
constexpr Array(std::initializer_list<T> data)
|
||||
{
|
||||
size_t N_LIST = std::size(data);
|
||||
for (size_t i = 0; i < 4; ++i)
|
||||
_data[i] = i < N_LIST ? *(data.begin() + i) : T{};
|
||||
}
|
||||
constexpr const T& Get(size_t i) const
|
||||
{
|
||||
assert(i < 4);
|
||||
return _data[i];
|
||||
}
|
||||
constexpr T Sum(size_t i, size_t j) const
|
||||
{
|
||||
assert(i < 4);
|
||||
assert(j < 4);
|
||||
return _data[i] + _data[j];
|
||||
}
|
||||
constexpr T& operator[](size_t i)
|
||||
{
|
||||
assert(i < 4);
|
||||
return _data[i];
|
||||
}
|
||||
constexpr const T& operator[](size_t i) const
|
||||
{
|
||||
assert(i < 4);
|
||||
return _data[i];
|
||||
}
|
||||
constexpr T& at(size_t i)
|
||||
{
|
||||
assert(i < 4);
|
||||
if (i < 4)
|
||||
return _data[i];
|
||||
else
|
||||
throw std::out_of_range("dl::Array::at outrange");
|
||||
}
|
||||
constexpr const T& at(size_t i) const
|
||||
{
|
||||
assert(i < 4);
|
||||
if (i < 4)
|
||||
return _data[i];
|
||||
else
|
||||
throw std::out_of_range("dl::Array::at outrange");
|
||||
}
|
||||
|
||||
T* begin() { return &x; }
|
||||
T* end() { return &x + 4; }
|
||||
const T* begin() const { return &x; }
|
||||
const T* end() const { return &x + 4; }
|
||||
bool empty() const { return false; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class Array<T, 0>
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
T _data[1];
|
||||
Array() = default;
|
||||
|
||||
constexpr Array(std::initializer_list<T> data)
|
||||
{
|
||||
}
|
||||
constexpr T& operator[](size_t i)
|
||||
{
|
||||
return *begin();
|
||||
}
|
||||
constexpr const T& operator[](size_t i) const
|
||||
{
|
||||
return *begin();
|
||||
}
|
||||
constexpr T& at(size_t i)
|
||||
{
|
||||
throw std::out_of_range("dl::Array::at outrange");
|
||||
}
|
||||
constexpr const T& at(size_t i) const
|
||||
{
|
||||
throw std::out_of_range("dl::Array::at outrange");
|
||||
}
|
||||
|
||||
T* begin() { return nullptr; }
|
||||
T* end() { return nullptr; }
|
||||
const T* begin() const { return nullptr; }
|
||||
const T* end() const { return nullptr; }
|
||||
bool empty() const { return true; }
|
||||
};
|
||||
|
||||
template<typename T, size_t N>
|
||||
constexpr bool operator==(const Array<T, N>& a, const Array<T, N>& b)
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
{
|
||||
if (a[i] != b[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#else
|
||||
template<typename T, size_t N>
|
||||
using Array = std::array<T, N>;
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* @file dl_array2.h
|
||||
* @brief 2维array
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 23-07-09
|
||||
*
|
||||
* @note 提供行指针,避免乘法计算
|
||||
* @note 设计为深拷贝,与std::array一致
|
||||
* @note std::array<std::array<T, W>, H>这种写法,下标访问时会使用imul,所以使用行指针
|
||||
* @note 以上废弃,实际测试,原生写法速度最快
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
||||
namespace dl
|
||||
{
|
||||
//! 二维array
|
||||
template<typename T, size_t W, size_t H>
|
||||
class Array2
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 返回第j行
|
||||
*/
|
||||
T* operator[](std::size_t j)
|
||||
{
|
||||
assert(j < H);
|
||||
return &_data[j * W];
|
||||
}
|
||||
/**
|
||||
* @brief 返回第j行
|
||||
*/
|
||||
const T* operator[](std::size_t j) const
|
||||
{
|
||||
assert(j < H);
|
||||
return &_data[j * W];
|
||||
}
|
||||
|
||||
const T& Get(size_t j, size_t i) const
|
||||
{
|
||||
assert(j < H);
|
||||
assert(i < W);
|
||||
return _data[j * W + i];
|
||||
}
|
||||
T& GetRef(size_t j, size_t i)
|
||||
{
|
||||
assert(j < H);
|
||||
assert(i < W);
|
||||
return _data[j * W + i];
|
||||
}
|
||||
|
||||
bool CheckRange(size_t j, size_t i) const
|
||||
{
|
||||
return j < H && i < W;
|
||||
}
|
||||
bool CheckRange(const SizeT& xy) const
|
||||
{
|
||||
return CheckRange(xy.y, xy.x);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 填充值
|
||||
*/
|
||||
void Fill(const T& v)
|
||||
{
|
||||
for (auto& iter : _data)
|
||||
iter = v;
|
||||
}
|
||||
|
||||
std::byte* GetBuffer()
|
||||
{
|
||||
return (std::byte*)_data.data();
|
||||
}
|
||||
|
||||
T* GetData()
|
||||
{
|
||||
return _data.data();
|
||||
}
|
||||
|
||||
unsigned GetWidth()
|
||||
{
|
||||
return (unsigned)W;
|
||||
}
|
||||
|
||||
unsigned GetHeight()
|
||||
{
|
||||
return (unsigned)H;
|
||||
}
|
||||
|
||||
Size GetSize()
|
||||
{
|
||||
return { (unsigned)W, (unsigned)H };
|
||||
}
|
||||
|
||||
size_t GetSizeByte()
|
||||
{
|
||||
return _data.size() * sizeof(T);
|
||||
}
|
||||
|
||||
auto begin()
|
||||
{
|
||||
return _data.begin();
|
||||
}
|
||||
auto end()
|
||||
{
|
||||
return _data.end();
|
||||
}
|
||||
private:
|
||||
std::array<T, W * H> _data;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @file dl_array_enum.h
|
||||
* @brief array使用枚举类作为索引的封装
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 22-06-27
|
||||
*
|
||||
* @note malloc不会调用构造函数
|
||||
* @note 访问尾后指针是合法的
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace dl
|
||||
{
|
||||
//! 枚举类数组
|
||||
template<typename V, auto N>
|
||||
class ArrayEnum
|
||||
{
|
||||
public:
|
||||
using E = decltype(N);
|
||||
/**
|
||||
* @brief 返回位置元素,debug版本检查越界
|
||||
*/
|
||||
V& operator[](E e)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
assert(CheckRange(e));
|
||||
#endif
|
||||
return _data[(size_t)e];
|
||||
}
|
||||
|
||||
V& operator[](size_t index)
|
||||
{
|
||||
return operator[](E(index));
|
||||
}
|
||||
|
||||
//! 越界检查
|
||||
bool CheckRange(E e)
|
||||
{
|
||||
return (size_t)e < (size_t)N;
|
||||
}
|
||||
|
||||
size_t size() { return (size_t)N; }
|
||||
|
||||
V* begin() { return _data; }
|
||||
V* end() { return _data + (size_t)N; }
|
||||
|
||||
private:
|
||||
V _data[(size_t)N];
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
/**
|
||||
* @file dl_array_simd.h
|
||||
* @brief 向量化容器
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 26-02-05
|
||||
*
|
||||
* @note 基于simde库
|
||||
* @note 经测试,N较小时没有性能没有明显提升,且增加代码复杂度,还要求内存对齐(所以有特定需求才使用)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base/dl_array.h"
|
||||
#include "base/dl_type_op.h"
|
||||
|
||||
#if (DL_CPU_ARCH == DL_CPU_ARCH_AMD64 || DL_CPU_ARCH == DL_CPU_ARCH_X86)
|
||||
#include <simde/x86/sse.h>
|
||||
#else
|
||||
namespace dl
|
||||
{
|
||||
using simde__m128 = Array<float, 4>;
|
||||
|
||||
inline simde__m128 simde_mm_load_ps(float arr[4])
|
||||
{
|
||||
simde__m128 ret;
|
||||
ret[0] = arr[0];
|
||||
ret[1] = arr[1];
|
||||
ret[2] = arr[2];
|
||||
ret[3] = arr[3];
|
||||
return ret;
|
||||
}
|
||||
inline simde__m128 simde_mm_set1_ps(float a)
|
||||
{
|
||||
simde__m128 ret;
|
||||
ret[0] = a;
|
||||
ret[1] = a;
|
||||
ret[2] = a;
|
||||
ret[3] = a;
|
||||
return ret;
|
||||
}
|
||||
inline void simde_mm_store_ps(simde__m128& ret, const simde__m128& a)
|
||||
{
|
||||
ret = a;
|
||||
}
|
||||
|
||||
inline simde__m128 simde_mm_add_ps(const simde__m128& a, const simde__m128& b)
|
||||
{
|
||||
return a + b;
|
||||
}
|
||||
inline simde__m128 simde_mm_sub_ps(const simde__m128& a, const simde__m128& b)
|
||||
{
|
||||
return a - b;
|
||||
}
|
||||
inline simde__m128 simde_mm_mul_ps(const simde__m128& a, const simde__m128& b)
|
||||
{
|
||||
return a * b;
|
||||
}
|
||||
inline simde__m128 simde_mm_div_ps(const simde__m128& a, const simde__m128& b)
|
||||
{
|
||||
return a / b;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace dl
|
||||
{
|
||||
template<typename T, size_t N>
|
||||
requires std::is_arithmetic_v<T>
|
||||
class alignas(16) ArrayS2;
|
||||
|
||||
template<size_t N>
|
||||
ArrayS2<float, N> simd_m128u_op(simde__m128(*op)(simde__m128, simde__m128),
|
||||
const ArrayS2<float, N>& a, const Array<float, 2>& b)
|
||||
{
|
||||
ArrayS2<float, N> ret;
|
||||
if constexpr (N == 4)
|
||||
{
|
||||
simde__m128 vec_ax = simde_mm_load_ps(a.x);
|
||||
simde__m128 vec_bx = simde_mm_set1_ps(b.x);
|
||||
vec_ax = op(vec_ax, vec_bx);
|
||||
simde_mm_store_ps(ret.x, vec_ax);
|
||||
|
||||
simde__m128 vec_ay = simde_mm_load_ps(a.y);
|
||||
simde__m128 vec_by = simde_mm_set1_ps(b.y);
|
||||
vec_ay = op(vec_ay, vec_by);
|
||||
simde_mm_store_ps(ret.y, vec_ay);
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(N == 4);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
namespace dl
|
||||
{
|
||||
template<typename T, size_t N>
|
||||
requires std::is_arithmetic_v<T>
|
||||
class alignas(16) ArrayS2
|
||||
{
|
||||
public:
|
||||
union
|
||||
{
|
||||
T _data[N * 2];
|
||||
struct
|
||||
{
|
||||
T x[N];
|
||||
T y[N];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
ArrayS2() = default;
|
||||
|
||||
// slow
|
||||
constexpr Array<T, 2> Get(size_t i) const
|
||||
{
|
||||
return { x[i], y[i] };
|
||||
}
|
||||
constexpr Array<T, 2> Sum(size_t i, size_t j) const
|
||||
{
|
||||
Array<T, 2> ret;
|
||||
ret[0] = x[i] + x[j];
|
||||
ret[1] = y[i] + y[j];
|
||||
return ret;
|
||||
}
|
||||
/*constexpr const Array<T, 2> operator[](size_t i) const
|
||||
{
|
||||
return { x[i], y[i] };
|
||||
}*/
|
||||
|
||||
constexpr ArrayS2(std::initializer_list<Array<T, 2>> data)
|
||||
{
|
||||
size_t N_LIST = std::size(data);
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
x[i] = i < N_LIST ? data.x : T{};
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
y[i] = i < N_LIST ? data.y : T{};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr ArrayS2<T, N>& operator+=(ArrayS2<T, N>& a, const Array<T, 2>& b)
|
||||
{
|
||||
if constexpr (N == 4)
|
||||
a = a + b;
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
{
|
||||
a.x[i] += b[0];
|
||||
a.y[i] += b[1];
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
template<typename T, std::size_t N>
|
||||
constexpr ArrayS2<T, N> operator+(const ArrayS2<T, N>& a, const Array<T, 2>& b)
|
||||
{
|
||||
if constexpr (N == 4)
|
||||
return simd_m128u_op(simde_mm_add_ps, a, b);
|
||||
else
|
||||
{
|
||||
ArrayS2<T, N> ret = a;
|
||||
ret += b;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr ArrayS2<T, N>& operator-=(ArrayS2<T, N>& a, const Array<T, 2>& b)
|
||||
{
|
||||
if constexpr (N == 4)
|
||||
a = a - b;
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
{
|
||||
a.x[i] -= b[0];
|
||||
a.y[i] -= b[1];
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
template<typename T, std::size_t N>
|
||||
constexpr ArrayS2<T, N> operator-(const ArrayS2<T, N>& a, const Array<T, 2>& b)
|
||||
{
|
||||
if constexpr (N == 4)
|
||||
return simd_m128u_op(simde_mm_sub_ps, a, b);
|
||||
else
|
||||
{
|
||||
ArrayS2<T, N> ret = a;
|
||||
ret -= b;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr ArrayS2<T, N>& operator*=(ArrayS2<T, N>& a, const Array<T, 2>& b)
|
||||
{
|
||||
if constexpr (N == 4)
|
||||
a = a * b;
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
{
|
||||
a.x[i] *= b[0];
|
||||
a.y[i] *= b[1];
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
template<typename T, std::size_t N>
|
||||
constexpr ArrayS2<T, N> operator*(const ArrayS2<T, N>& a, const Array<T, 2>& b)
|
||||
{
|
||||
if constexpr (N == 4)
|
||||
return simd_m128u_op(simde_mm_mul_ps, a, b);
|
||||
else
|
||||
{
|
||||
ArrayS2<T, N> ret = a;
|
||||
ret *= b;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
constexpr ArrayS2<T, N>& operator/=(ArrayS2<T, N>& a, const Array<T, 2>& b)
|
||||
{
|
||||
if constexpr (N == 4)
|
||||
a = a / b;
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
{
|
||||
a.x[i] /= b[0];
|
||||
a.y[i] /= b[1];
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
template<typename T, std::size_t N>
|
||||
constexpr ArrayS2<T, N> operator/(const ArrayS2<T, N>& a, const Array<T, 2>& b)
|
||||
{
|
||||
if constexpr (N == 4)
|
||||
return simd_m128u_op(simde_mm_div_ps, a, b);
|
||||
else
|
||||
{
|
||||
ArrayS2<T, N> ret = a;
|
||||
ret /= b;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<size_t M = 1, typename T, size_t N>
|
||||
constexpr ArrayS2<T, N - M> toShorter(const ArrayS2<T, N>& a)
|
||||
{
|
||||
static_assert(M <= N);
|
||||
ArrayS2<T, N - M> ret;
|
||||
for (size_t i = 0; i < N - M; ++i)
|
||||
{
|
||||
ret.x[i] = a.x[i];
|
||||
ret.y[i] = a.y[i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,403 @@
|
||||
/**
|
||||
* @file dl_color.h
|
||||
* @brief 颜色
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 21-08-12
|
||||
*
|
||||
* @note 基于float类型,4个通道,顺序为 rgba,缩写col
|
||||
* @note 从书写的角度,32位色RGBA表示0xRRGGBBAA。
|
||||
* @note 大写A表示0-255,小写a表示0-1.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "math/dl_random.h"
|
||||
#include "math/dl_math.h"
|
||||
#include "base/dl_range_every.h"
|
||||
#include "dl_type.h"
|
||||
|
||||
namespace dl
|
||||
{
|
||||
|
||||
using Color3F = std::array<float, 3>;
|
||||
|
||||
/**
|
||||
* @brief 创建随机颜色
|
||||
* @param[in] a 指定透明度
|
||||
*/
|
||||
inline Color createColorRandom(float a = 1.0f)
|
||||
{
|
||||
Color ret;
|
||||
ret[0] = Random::Float(0_f, 1_f);
|
||||
ret[1] = Random::Float(0_f, 1_f);
|
||||
ret[2] = Random::Float(0_f, 1_f);
|
||||
ret[3] = a;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 创建指定透明度颜色
|
||||
* @param[in] col 纯色部分
|
||||
* @param[in] a 指定透明度
|
||||
*/
|
||||
constexpr Color createColor(const Color& col, float a = 1.0f)
|
||||
{
|
||||
return { col[0], col[1], col[2], a };
|
||||
}
|
||||
constexpr Color createColor(const Position3& col, float a = 1.0f)
|
||||
{
|
||||
return { col[0], col[1], col[2], a };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 创建指定透明度颜色
|
||||
* @param[in] col 纯色部分
|
||||
* @param[in] a 指定透明度
|
||||
*/
|
||||
constexpr Color createColor(const Color3F& rgb, float a = 1.0f)
|
||||
{
|
||||
return { rgb[0], rgb[1], rgb[2], a };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 创建颜色
|
||||
* @param[in] uint32_t 颜色值
|
||||
*/
|
||||
constexpr Color createColor(uint32_t dw_rgba)
|
||||
{
|
||||
//RGBA -> rgba
|
||||
return {
|
||||
(dw_rgba >> 24 & 255) / 255.0f,
|
||||
(dw_rgba >> 16 & 255) / 255.0f,
|
||||
(dw_rgba >> 8 & 255) / 255.0f,
|
||||
(dw_rgba >> 0 & 255) / 255.0f };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 创建颜色
|
||||
*/
|
||||
constexpr Color createColor(uint8_t R, uint8_t G, uint8_t B, uint8_t A)
|
||||
{
|
||||
return { R / 255.0f, G / 255.0f, B / 255.0f, A / 255.0f };
|
||||
}
|
||||
/**
|
||||
* @brief 通道数组转为 转为uint32_t颜色
|
||||
* 例如 00, 11, 22, 33 -> 0x00112233
|
||||
*/
|
||||
constexpr uint32_t AssembleColor(std::array<uint8_t, 4> arr_col)
|
||||
{
|
||||
return ((uint32_t)arr_col[0] << 24)
|
||||
| ((uint32_t)arr_col[1] << 16)
|
||||
| ((uint32_t)arr_col[2] << 8)
|
||||
| ((uint32_t)arr_col[3] << 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取颜色分量,从左到右
|
||||
*/
|
||||
constexpr std::array<uint8_t, 4> GetColorChannel(uint32_t dw_col)
|
||||
{
|
||||
return {
|
||||
(uint8_t)(dw_col >> 24),
|
||||
(uint8_t)(dw_col >> 16 & 255),
|
||||
(uint8_t)(dw_col >> 8 & 255),
|
||||
(uint8_t)(dw_col >> 0 & 255) };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief alpha混合
|
||||
*/
|
||||
constexpr void BlendColorAlpha(Color& bg, const Color& fg)
|
||||
{
|
||||
// 公式:
|
||||
// 输出颜色 = 前景色 × 前景透明度 + 背景色 ×(1 - 前景透明度)
|
||||
bg.r = fg.r * fg.a + bg.r * (1.0f - fg.a);
|
||||
bg.g = fg.g * fg.a + bg.g * (1.0f - fg.a);
|
||||
bg.b = fg.b * fg.a + bg.b * (1.0f - fg.a);
|
||||
bg.a = fg.a + bg.a * (1.0f - fg.a);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 限制颜色值 到[0, 1]
|
||||
*/
|
||||
inline void colorSaturate(Color& col)
|
||||
{
|
||||
Every::Saturate(col);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 反色,不包含透明通道
|
||||
*/
|
||||
inline void colorInverse(Color& col)
|
||||
{
|
||||
col = { 1.0f - col[0], 1.0f - col[1], 1.0f - col[2], col[3] };
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline Color colorInverse(const Color& col)
|
||||
{
|
||||
Color ret = col;
|
||||
colorInverse(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 不透明(a通道为1)
|
||||
*/
|
||||
inline bool isColorOpaque(const Color& col)
|
||||
{
|
||||
return col[3] == 1.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 32位颜色获取所有通道,按书写顺序拆分
|
||||
* 例如 0x00112233 -> 00, 11, 22, 33
|
||||
*/
|
||||
constexpr std::array<uint8_t, 4> getColorChannel(uint32_t dw_col)
|
||||
{
|
||||
return {
|
||||
(uint8_t)(dw_col >> 24 & 255),
|
||||
(uint8_t)(dw_col >> 16 & 255),
|
||||
(uint8_t)(dw_col >> 8 & 255),
|
||||
(uint8_t)(dw_col >> 0 & 255) };
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 颜色插值
|
||||
*/
|
||||
inline Color colorLerp(float cur)
|
||||
{
|
||||
cur *= 6.0f;
|
||||
Color col;
|
||||
if (cur < 1.0f)
|
||||
col = { 1.0f, 0.0f, cur, 1.0f };
|
||||
else if (cur < 2.0f)
|
||||
col = { 2.0f - cur, 0.0f, 1.0f, 1.0f };
|
||||
else if (cur < 3.0f)
|
||||
col = { 0.0f, cur - 2.0f, 1.0f, 1.0f };
|
||||
else if (cur < 4.0f)
|
||||
col = { 0.0f, 1.0f, 4.0f - cur, 1.0f };
|
||||
else if (cur < 5.0f)
|
||||
col = { cur - 4.0f, 1.0f, 0.0f, 1.0f };
|
||||
else
|
||||
col = { 1.0f, 6.0f - cur, 0.0f, 1.0f };
|
||||
return col;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从HSV颜色模型创建颜色
|
||||
* @param[in] h 色相 (0-360)
|
||||
* @param[in] s 饱和度 (0-1)
|
||||
* @param[in] v 亮度 (0-1)
|
||||
* @param[in] a 透明度 (0-1)
|
||||
*/
|
||||
inline Color createColorHSV(float h, float s, float v, float a = 1.0f)
|
||||
{
|
||||
float r, g, b;
|
||||
|
||||
int i = static_cast<int>(h / 60.0f) % 6;
|
||||
float f = h / 60.0f - i;
|
||||
float p = v * (1.0f - s);
|
||||
float q = v * (1.0f - f * s);
|
||||
float t = v * (1.0f - (1.0f - f) * s);
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
r = v; g = t; b = p;
|
||||
break;
|
||||
case 1:
|
||||
r = q; g = v; b = p;
|
||||
break;
|
||||
case 2:
|
||||
r = p; g = v; b = t;
|
||||
break;
|
||||
case 3:
|
||||
r = p; g = q; b = v;
|
||||
break;
|
||||
case 4:
|
||||
r = t; g = p; b = v;
|
||||
break;
|
||||
default:
|
||||
r = v; g = p; b = q;
|
||||
break;
|
||||
}
|
||||
|
||||
return { r, g, b, a };
|
||||
}
|
||||
|
||||
inline Color operator""_c(unsigned long long x)
|
||||
{
|
||||
return createColor((uint32_t)x);
|
||||
}
|
||||
|
||||
//! RGBA专用
|
||||
namespace RGBA
|
||||
{
|
||||
/**
|
||||
* @brief 颜色转为uint32_t颜色
|
||||
*/
|
||||
constexpr uint32_t Create(const Color& col)
|
||||
{
|
||||
return (uint32_t(col[0] * 255) << 24)//r
|
||||
| (uint32_t(col[1] * 255) << 16)//g
|
||||
| (uint32_t(col[2] * 255) << 8)//b
|
||||
| (uint32_t(col[3] * 255) << 0);//a
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 组合uint32_t颜色
|
||||
*/
|
||||
constexpr uint32_t Create(uint32_t r, uint32_t g, uint32_t b, uint32_t a)
|
||||
{
|
||||
return (r << 24) | (g << 16) | (b << 8) | (a << 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief uint32_t颜色获取A通道
|
||||
*/
|
||||
constexpr uint32_t GetA(uint32_t dw_col)
|
||||
{
|
||||
return dw_col & 0x000000ff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 转为ABGR颜色
|
||||
*/
|
||||
inline uint32_t ToABGR(uint32_t dw_col)
|
||||
{
|
||||
return Math::ByteReverse(dw_col);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! ABGR专用(请优先使用RGBA,除非你知道你在做什么)
|
||||
namespace ABGR
|
||||
{
|
||||
/**
|
||||
* @brief 颜色转为uint32_t颜色
|
||||
*/
|
||||
constexpr uint32_t Create(const Color& col)
|
||||
{
|
||||
return (uint32_t(col[0] * 255) << 0)//r
|
||||
| (uint32_t(col[1] * 255) << 8)//g
|
||||
| (uint32_t(col[2] * 255) << 16)//b
|
||||
| (uint32_t(col[3] * 255) << 24);//a
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 创建颜色
|
||||
* @param[in] uint32_t ABGR
|
||||
*/
|
||||
constexpr Color CreateColor(uint32_t dw)
|
||||
{
|
||||
// ABGR -> rgba
|
||||
return {
|
||||
(dw >> 0 & 255) / 255.0f,
|
||||
(dw >> 8 & 255) / 255.0f,
|
||||
(dw >> 16 & 255) / 255.0f,
|
||||
(dw >> 24 & 255) / 255.0f };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ABGR颜色获取A通道
|
||||
*/
|
||||
constexpr uint8_t GetA(uint32_t dw_col)
|
||||
{
|
||||
return (dw_col & 0xff000000) >> 24;
|
||||
}
|
||||
}
|
||||
|
||||
//! BGRA专用(请优先使用RGBA,除非你知道你在做什么)
|
||||
namespace BGRA
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief 转为ABGR颜色
|
||||
*/
|
||||
constexpr uint32_t ToABGR(uint32_t dw_col)
|
||||
{
|
||||
return ((dw_col & 0x000000ff) << 24)
|
||||
| (dw_col >> 8);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//! ARGB专用(请优先使用RGBA,除非你知道你在做什么)
|
||||
namespace ARGB
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief 转为ABGR颜色
|
||||
*/
|
||||
constexpr uint32_t ToABGR(uint32_t dw_col)
|
||||
{
|
||||
return (dw_col & 0xff00ff00)
|
||||
| ((dw_col & 0x00ff0000) >> 16)
|
||||
| ((dw_col & 0x000000ff) << 16);
|
||||
}
|
||||
|
||||
}
|
||||
//! 颜色预定义
|
||||
namespace ColorDef
|
||||
{
|
||||
constexpr Color NONE = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
|
||||
constexpr Color WHITE = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
constexpr Color BLACK = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
constexpr Color RED = { 1.0f, 0.0f, 0.0f, 1.0f };
|
||||
constexpr Color GREEN = { 0.0f, 1.0f, 0.0f, 1.0f };
|
||||
constexpr Color BLUE = { 0.0f, 0.0f, 1.0f, 1.0f };
|
||||
constexpr Color YELLOW = { 1.0f, 1.0f, 0.0f, 1.0f };
|
||||
constexpr Color PURPLE = { 1.0f, 0.0f, 1.0f, 1.0f };
|
||||
constexpr Color CYAN = { 0.0f, 1.0f, 1.0f, 1.0f };
|
||||
|
||||
constexpr Color ORANGE = { 1.0f, 0.5f, 0.0f, 1.0f };
|
||||
|
||||
constexpr Color GREEN_DARK = { 0.0f, 100.0f / 255.0f, 0.0f, 1.0f };
|
||||
|
||||
|
||||
|
||||
constexpr Color DISABLE = { 0.298f, 0.298f, 0.298f, 1.0f };
|
||||
constexpr Color TEXT_BG = { 0.0f, 0.0f, 0.0f, 0.5f }; //!< 文本背景,半透明黑色
|
||||
|
||||
constexpr Color FACTOR_GRAY = { 0.299f, 0.587f, 0.114f, 1.0f };//!< 转灰色因子(并不能转成真的灰色,可使用 Sprite::Blend::GRAY)
|
||||
|
||||
constexpr Color GRAY = { 0.5f, 0.5f, 0.5f, 1.0f };
|
||||
constexpr Color GRAY_LIGHT = { 0.75f, 0.75f, 0.75f, 1.0f };
|
||||
constexpr Color GRAY_DARK = { 0.25f, 0.25f, 0.25f, 1.0f };
|
||||
|
||||
constexpr Color CLEAR_SCREEN = { 0.0f, 0.2f, 0.4f, 1.0f };//!< 清屏颜色
|
||||
|
||||
//https://www.color.org/chardata/rgb/BT709.xalter
|
||||
constexpr Color AXIS_X = { 0.64f, 0.30f, 0.15f, 1.0f };
|
||||
constexpr Color AXIS_Y = { 0.33f, 0.60f, 0.06f, 1.0f };
|
||||
constexpr Color AXIS_Z = { 0.03f, 0.10f, 0.79f, 1.0f };
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 创建颜色
|
||||
* @param[in] str 十六进制RGBA
|
||||
* @retval 传入空、或失败返回白色
|
||||
*/
|
||||
inline Color createColor(std::string_view str)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(str.empty())
|
||||
return ColorDef::WHITE;
|
||||
uint32_t dw = (uint32_t)std::stoul(std::string{ str }, nullptr, 16);
|
||||
return createColor(dw);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
return ColorDef::WHITE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @file dl_concept.h
|
||||
* @brief 用于模板限定,更好的报错信息
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 21-08-12
|
||||
*
|
||||
* @note 标准库为小写下划线命名,我们使用大写开头
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "system/dl_platform.h"
|
||||
|
||||
#include <type_traits>
|
||||
#include <concepts>
|
||||
|
||||
namespace dl
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
concept PopFrontAble = requires(T x) { x.pop_front(); };
|
||||
|
||||
template<typename T>
|
||||
concept IsUnsigned = std::is_unsigned<T>::value;
|
||||
|
||||
template<typename T>
|
||||
concept IsSigned = std::is_signed<T>::value;
|
||||
|
||||
template<typename T>
|
||||
concept IsInteger = std::is_integral<T>::value;
|
||||
|
||||
template<typename T>
|
||||
concept IsReal = std::is_floating_point<T>::value;
|
||||
|
||||
//标准布局
|
||||
template<typename T>
|
||||
concept IsStandardLayout = std::is_standard_layout<T>::value;
|
||||
|
||||
//平凡类型,比is_standard_layout严格
|
||||
template<typename T>
|
||||
concept IsTrivial = std::is_trivial<T>::value;
|
||||
|
||||
//标准布局 与 平凡类型 的组合
|
||||
template<typename T>
|
||||
concept IsPod = std::is_trivial_v<T> && std::is_standard_layout_v<T>;
|
||||
|
||||
template<typename T>
|
||||
concept IsNotPod = !std::is_trivial_v<T> || !std::is_standard_layout_v<T>;
|
||||
|
||||
//! 平凡可复制 唯一可以使用std::memcpy和fstream::write/read的类型
|
||||
template<typename T>
|
||||
concept IsCopyable = std::is_trivially_copyable<T>::value;
|
||||
|
||||
//! 是内置数据类型
|
||||
template<typename T>
|
||||
concept IsBase = std::is_fundamental<T>::value;
|
||||
|
||||
//! 是指针类型
|
||||
template<typename T>
|
||||
concept IsPointer = std::is_pointer<T>::value;
|
||||
|
||||
//! 是枚举类型
|
||||
template<typename T>
|
||||
concept IsEnum = std::is_enum<T>::value;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* @file dl_discrete_range.h
|
||||
* @brief 离散范围
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 24-05-10
|
||||
*
|
||||
* @note 闭区间 [100, 200] [233, 500] [600, 1000)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace dl
|
||||
{
|
||||
//! 离散范围表示
|
||||
template<typename T>
|
||||
class DiscreteRange
|
||||
{
|
||||
using Range = std::array<T, 2>;
|
||||
public:
|
||||
void Add(const T& v)
|
||||
{
|
||||
auto iter = _data.begin();
|
||||
while (iter != _data.end())
|
||||
{
|
||||
Range& r = *iter;
|
||||
if (v < r[0])
|
||||
{// 小于区间左侧,必定不在所有区间内
|
||||
if (v + 1 == r[0])
|
||||
{// 刚好在边上
|
||||
--r[0];
|
||||
// 左移后不会连接到上一个区间,因为上一个区间已经判断
|
||||
return;
|
||||
}
|
||||
// 添加新区间
|
||||
break;
|
||||
}
|
||||
if (v > r[1])
|
||||
{// 大于区间右侧,必定不在当前区间内
|
||||
if (v == r[1] + 1)
|
||||
{// 刚好在边上
|
||||
auto iter_next = std::next(iter);
|
||||
if (iter_next != _data.end() && (*iter_next)[0] == v + 1)
|
||||
{
|
||||
// 右移后会连接到下一个区间
|
||||
r[1] = (*iter_next)[1];
|
||||
_data.erase(iter_next);
|
||||
}
|
||||
else
|
||||
++r[1];
|
||||
return;
|
||||
}
|
||||
++iter;
|
||||
continue;
|
||||
}
|
||||
// 剩下条件在范围内
|
||||
return;
|
||||
}
|
||||
_data.insert(iter, { v, v });
|
||||
}
|
||||
|
||||
std::string ToString()
|
||||
{
|
||||
std::string ret;
|
||||
for (auto& iter : _data)
|
||||
{
|
||||
ret += fmt::format("[{}] ", to_string(iter));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::optional<Range> GetTotalRange()
|
||||
{
|
||||
if (_data.empty())
|
||||
return {};
|
||||
if (_data.size() == 1)
|
||||
return _data.front();
|
||||
return Range{ _data.front()[0], _data.back()[1] };
|
||||
}
|
||||
private:
|
||||
std::list<Range> _data;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* @file dl_list_mt.h
|
||||
* @brief 多线程队列
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 26-03-04
|
||||
*
|
||||
* @note
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "base/dl_type_def.h"
|
||||
|
||||
namespace dl
|
||||
{
|
||||
//! 多线程队列
|
||||
template<typename T>
|
||||
class ListMultiThread
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 取第一个,顺序通过 SetQueueMode 指定,默认FIFO
|
||||
* @retval 成功返回true,并弹出
|
||||
*/
|
||||
bool PopFront(T& a)
|
||||
{
|
||||
_mutex.lock();
|
||||
if (_list.empty())
|
||||
{
|
||||
_mutex.unlock();
|
||||
return false;
|
||||
}
|
||||
a = _list.front();
|
||||
_list.pop_front();
|
||||
_mutex.unlock();
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @brief 添加
|
||||
*/
|
||||
void Add(const T& buf)
|
||||
{
|
||||
_mutex.lock();
|
||||
_list.push_back(buf);
|
||||
_mutex.unlock();
|
||||
}
|
||||
/**
|
||||
* @brief 添加
|
||||
*/
|
||||
void Add(T&& buf)
|
||||
{
|
||||
_mutex.lock();
|
||||
_list.push_back(buf);
|
||||
_mutex.unlock();
|
||||
}
|
||||
/**
|
||||
* @brief 当前数量
|
||||
*/
|
||||
size_t GetSize()
|
||||
{
|
||||
std::lock_guard guard{ _mutex };
|
||||
return _list.size();
|
||||
}
|
||||
/**
|
||||
* @brief 空
|
||||
*/
|
||||
bool IsEmpty()
|
||||
{
|
||||
std::lock_guard guard{ _mutex };
|
||||
return _list.empty();
|
||||
}
|
||||
/**
|
||||
* @brief 清除
|
||||
*/
|
||||
void Clear()
|
||||
{
|
||||
_mutex.lock();
|
||||
_list.clear();
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
void SetQueueMode(QueueMode mode)
|
||||
{
|
||||
_mode = mode;
|
||||
}
|
||||
|
||||
ListMultiThread(QueueMode mode = QueueMode::FIFO) :
|
||||
_mode{ mode }
|
||||
{}
|
||||
private:
|
||||
std::mutex _mutex;// 队列锁
|
||||
std::list<T> _list;// 队列
|
||||
QueueMode _mode;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* @file dl_list_mt_cache.h
|
||||
* @brief 多线程队列(带缓冲)
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 26-03-04
|
||||
*
|
||||
* @note 适用于一个线程(主要线程)添加任务,多个线程处理
|
||||
* 主要线程 调用Move将缓冲的任务立即刷新,否则任务可能不会执行
|
||||
* 例如,主线程Add增加任务,帧末尾调用Move,其他线程处理任务。参考 dl_thread_task.h
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "base/dl_type_def.h"
|
||||
|
||||
namespace dl
|
||||
{
|
||||
//! 多线程队列(带缓冲)
|
||||
template<typename T>
|
||||
class ListMultiThreadCache
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 取第一个,顺序通过 SetQueueMode 指定,默认FIFO
|
||||
* @note 线程B调用(处理线程)
|
||||
* @retval 成功返回true,并弹出
|
||||
*/
|
||||
bool PopFront(T& a)
|
||||
{
|
||||
_mutex.lock();
|
||||
if (_list.empty())
|
||||
{
|
||||
_mutex.unlock();
|
||||
return false;
|
||||
}
|
||||
a = _list.front();
|
||||
_list.pop_front();
|
||||
_mutex.unlock();
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @brief 添加
|
||||
* @note 线程A调用
|
||||
*/
|
||||
void Add(const T& buf)
|
||||
{
|
||||
if (_mutex.try_lock())
|
||||
{
|
||||
_list.splice(_list.begin(), _listTemp);
|
||||
_list.push_back(buf);
|
||||
_mutex.unlock();
|
||||
return;
|
||||
}
|
||||
_listTemp.push_back(buf);
|
||||
}
|
||||
/**
|
||||
* @brief 添加
|
||||
* @note 线程A调用
|
||||
*/
|
||||
void Add(T&& buf)
|
||||
{
|
||||
if (_mutex.try_lock())
|
||||
{
|
||||
_list.splice(_list.begin(), _listTemp);
|
||||
_list.push_back(buf);
|
||||
_mutex.unlock();
|
||||
return;
|
||||
}
|
||||
_listTemp.push_back(buf);
|
||||
}
|
||||
/**
|
||||
* @brief 结束添加时调用,或立即刷新
|
||||
* @note 线程A调用
|
||||
*/
|
||||
void Move()
|
||||
{
|
||||
if (_listTemp.empty())
|
||||
return;
|
||||
_mutex.lock();
|
||||
_list.splice(_list.begin(), _listTemp);
|
||||
_mutex.unlock();
|
||||
}
|
||||
/**
|
||||
* @brief 添加
|
||||
* @note 线程A调用
|
||||
*/
|
||||
size_t GetSize()
|
||||
{
|
||||
std::lock_guard guard{ _mutex };
|
||||
return _list.size() + _listTemp.size();
|
||||
}
|
||||
/**
|
||||
* @brief 所有任务完成
|
||||
* @note 线程A调用
|
||||
*/
|
||||
bool IsEmpty()
|
||||
{
|
||||
std::lock_guard guard{ _mutex };
|
||||
return _list.empty() && _listTemp.empty();
|
||||
}
|
||||
/**
|
||||
* @brief 添加
|
||||
* @note 线程A调用
|
||||
*/
|
||||
void Clear()
|
||||
{
|
||||
_mutex.lock();
|
||||
_list.clear();
|
||||
_mutex.unlock();
|
||||
_listTemp.clear();
|
||||
}
|
||||
|
||||
void SetQueueMode(QueueMode mode)
|
||||
{
|
||||
_mode = mode;
|
||||
}
|
||||
|
||||
ListMultiThreadCache(QueueMode mode = QueueMode::FIFO) :
|
||||
_mode{ mode }
|
||||
{}
|
||||
private:
|
||||
std::mutex _mutex;// 队列锁
|
||||
std::list<T> _list;// 先入先出队列
|
||||
std::list<T> _listTemp;// 主线程缓冲
|
||||
QueueMode _mode;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* @file dl_object_pool.h
|
||||
* @brief 对象池
|
||||
*
|
||||
|
||||
* @version 1.1
|
||||
* @author lveyou
|
||||
* @date 26-05-08
|
||||
*
|
||||
* @note 对象自动进行析构和构造调用
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
|
||||
namespace dl
|
||||
{
|
||||
|
||||
//! 对象池
|
||||
template<typename T>
|
||||
class ObjectPool
|
||||
{
|
||||
public:
|
||||
// 申请一个空闲元素(O(1))
|
||||
size_t GetFree()
|
||||
{
|
||||
// 1. 优先用空闲列表
|
||||
if (!_freeIndex.empty())
|
||||
{
|
||||
size_t idx = _freeIndex.top();
|
||||
_freeIndex.pop();
|
||||
return idx;
|
||||
}
|
||||
|
||||
// 2. 无空闲 → 扩容(最多触发一次)
|
||||
_data.emplace_back();
|
||||
return _data.size() - 1;
|
||||
}
|
||||
|
||||
// 释放元素(O(1))
|
||||
void Release(size_t index)
|
||||
{
|
||||
if (index < _data.size())
|
||||
{
|
||||
_freeIndex.push(index);
|
||||
}
|
||||
}
|
||||
|
||||
// 访问元素
|
||||
T& operator[](size_t index)
|
||||
{
|
||||
return _data[index];
|
||||
}
|
||||
|
||||
// 获取全部数据
|
||||
std::vector<T>& data()
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<T> _data; // 真实资源
|
||||
std::stack<size_t> _freeIndex; // 空闲索引栈
|
||||
};
|
||||
|
||||
|
||||
//! 对象池
|
||||
template<typename T>
|
||||
class ObjectPoolEx
|
||||
{
|
||||
public:
|
||||
ObjectPoolEx()
|
||||
{
|
||||
/*slots.resize(capacity);
|
||||
freeList.reserve(capacity);
|
||||
liveList.reserve(capacity);
|
||||
for (uint32_t i = 0; i < capacity; ++i)
|
||||
{
|
||||
freeList.push_back(capacity - 1 - i);
|
||||
slots[i].isActive = false;
|
||||
}*/
|
||||
}
|
||||
|
||||
T* acquire()
|
||||
{
|
||||
if (freeList.empty())
|
||||
_extend();
|
||||
|
||||
uint32_t idx = freeList.back();
|
||||
freeList.pop_back();
|
||||
|
||||
slots[idx].isActive = true;
|
||||
slots[idx].liveIndex = liveList.size();
|
||||
liveList.push_back(idx);
|
||||
|
||||
return &slots[idx].data;
|
||||
}
|
||||
|
||||
void release(T* ptr) {
|
||||
uint32_t idx = static_cast<uint32_t>(ptr - &slots[0].data);
|
||||
if (!slots[idx].isActive) return;
|
||||
|
||||
// O(1) 从 liveList 移除
|
||||
uint32_t lastIdx = liveList.back();
|
||||
uint32_t removePos = slots[idx].liveIndex;
|
||||
|
||||
liveList[removePos] = lastIdx;
|
||||
slots[lastIdx].liveIndex = removePos;
|
||||
liveList.pop_back();
|
||||
|
||||
slots[idx].isActive = false;
|
||||
freeList.push_back(idx);
|
||||
}
|
||||
|
||||
size_t aliveCount() const
|
||||
{
|
||||
return liveList.size();
|
||||
}
|
||||
|
||||
private:
|
||||
struct Slot
|
||||
{
|
||||
T data;
|
||||
uint32_t liveIndex;
|
||||
bool isActive;
|
||||
};
|
||||
|
||||
std::vector<Slot> slots;
|
||||
std::vector<uint32_t> freeList;
|
||||
std::vector<uint32_t> liveList;
|
||||
|
||||
void _extend()
|
||||
{
|
||||
Slot slot;
|
||||
slot.isActive = false;
|
||||
slots.push_back(slot);
|
||||
freeList.push_back(slots.size() - 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @file dl_range_accumulate.h
|
||||
* @brief 范围累积
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 23-07-16
|
||||
*
|
||||
* @note 对容器做累积操作,返回一个值
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
//! 所有元素操作,返回一个值
|
||||
namespace dl::Accumulate
|
||||
{
|
||||
//因为减 和 除是逆操作,其值互反,所以这儿不实现
|
||||
//标准库的accumulate需要传入初值,这里简化了
|
||||
|
||||
//! 求和sum
|
||||
template<typename C>
|
||||
constexpr auto Add(const C& container)
|
||||
{
|
||||
using V = std::decay_t<decltype(container)>;
|
||||
using T = typename V::value_type;
|
||||
if (container.empty())
|
||||
return T{};
|
||||
T ret = *container.begin();
|
||||
for (auto iter = container.begin() + 1; iter != container.end(); ++iter)
|
||||
ret += *iter;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//! 求积product
|
||||
template<typename C>
|
||||
constexpr auto Mul(const C& container)
|
||||
{
|
||||
using V = std::decay_t<decltype(container)>;
|
||||
using T = typename V::value_type;
|
||||
if (container.empty())
|
||||
return T{};
|
||||
T ret = *container.begin();
|
||||
for (auto iter = container.begin() + 1; iter != container.end(); ++iter)
|
||||
ret *= *iter;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* @file dl_range_any.h
|
||||
* @brief 范围操作 任一满足条件
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 23-06-22
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "dl_concept.h"
|
||||
|
||||
//! 对容器任意元素的判断
|
||||
namespace dl::Any
|
||||
{
|
||||
/**
|
||||
* @brief 判断容器任意元素等于某值
|
||||
* @param[in] container 操作的容器
|
||||
* @param[in] v 要比较的值
|
||||
*/
|
||||
template<typename C, typename V>
|
||||
bool Equal(const C& container, const V& v)
|
||||
{
|
||||
for (auto& iter : container)
|
||||
{
|
||||
if (iter == v)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<typename C>
|
||||
bool Zero(const C& container)
|
||||
{
|
||||
return Equal(container, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 判断容器任意元素满足条件
|
||||
* @param[in] container 操作的容器
|
||||
* @param[in] func 条件
|
||||
*/
|
||||
template<typename C, typename F>
|
||||
bool Yes(const C& container, F func)
|
||||
{
|
||||
for (auto& iter : container)
|
||||
{
|
||||
if (func(iter))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 判断容器任意元素小于某值
|
||||
* @param[in] container 操作的容器
|
||||
* @param[in] v 要比较的值
|
||||
*/
|
||||
template<typename C, typename V>
|
||||
bool Less(const C& container, const V& v)
|
||||
{
|
||||
for (auto& iter : container)
|
||||
{
|
||||
if (iter < v)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
/**
|
||||
* @file dl_range_each.h
|
||||
* @brief 范围操作
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 23-06-22
|
||||
*
|
||||
* @note 对容器每个元素单独的操作(多对多的关系)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "dl_concept.h"
|
||||
#include "base/dl_array.h"
|
||||
|
||||
//! 多对多遍历操作
|
||||
namespace dl::Each
|
||||
{
|
||||
/**
|
||||
* @brief 取两者最小值为新元素
|
||||
* @note 类型长度一致,所以用array
|
||||
*/
|
||||
template<typename T, size_t N>
|
||||
Array<T, N> Min(const Array<T, N>& a, const Array<T, N>& b)
|
||||
{
|
||||
Array<T, N> ret;
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
{
|
||||
ret[i] = (std::min)(a[i], b[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 取两者最大值为新元素
|
||||
* @note 类型长度一致,所以用array
|
||||
*/
|
||||
template<typename T, size_t N>
|
||||
Array<T, N> Max(const Array<T, N>& a, const Array<T, N>& b)
|
||||
{
|
||||
Array<T, N> ret;
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
{
|
||||
ret[i] = (std::max)(a[i], b[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @brief 限制元素到 前闭后开区间(过大自动减1)
|
||||
* @note 不能是浮点型,闭区间请用Clamp
|
||||
*/
|
||||
template<IsInteger T, size_t N>
|
||||
void Limit(Array<T, N>& a, const Array<T, N>& min, const Array<T, N>& max)
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
{
|
||||
if (a[i] < min[i])
|
||||
a[i] = min[i];
|
||||
else if (a[i] >= max[i])
|
||||
a[i] = max[i] - 1;
|
||||
}
|
||||
}
|
||||
|
||||
template<IsInteger T, size_t N>
|
||||
[[nodiscard]]
|
||||
Array<T, N> Limit(const Array<T, N>& a, const Array<T, N>& min, const Array<T, N>& max)
|
||||
{
|
||||
Array<T, N> ret = a;
|
||||
Limit(ret, min, max);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 每个元素都小于返回真
|
||||
* @note 类型长度一致,所以用array
|
||||
*/
|
||||
template<typename T, size_t N>
|
||||
constexpr bool Less(const Array<T, N>& a, const Array<T, N>& b)
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
{
|
||||
if (!(a[i] < b[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @brief 线性插值
|
||||
* @param[in] a 容器a
|
||||
* @param[in] b 容器b
|
||||
* @param[in] t 系数
|
||||
*/
|
||||
template<IsReal T, size_t N>
|
||||
Array<T, N> Lerp(const Array<T, N>& a, const Array<T, N>& b, T t)
|
||||
{
|
||||
Array<T, N> ret;
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
{
|
||||
ret[i] = std::lerp(a[i], b[i], t);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 传入2个容器,对每个元素进行线性插值
|
||||
* @param[in] a 容器a
|
||||
* @param[in] b 容器b
|
||||
* @param[in] t 系数
|
||||
* @param[in] func 对结果的操作(比如round)
|
||||
*/
|
||||
template<typename T, size_t N, IsReal R>
|
||||
Array<T, N> Lerp(const Array<T, N>& a, const Array<T, N>& b, R t, R(*func)(R))
|
||||
{
|
||||
Array<T, N> ret;
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
{
|
||||
ret[i] = (T)func(std::lerp((R)a[i], (R)b[i], t));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 浮点数求模
|
||||
*/
|
||||
template<typename T, size_t N>
|
||||
Array<T, N> FMod(const Array<T, N>& a, const Array<T, N>& b)
|
||||
{
|
||||
Array<T, N> ret;
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
{
|
||||
ret[i] = std::fmod(a[i], b[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 判断两个容器 每个元素都满足条件
|
||||
* @param[in] container0 操作的容器
|
||||
* @param[in] container1 操作的容器
|
||||
* @param[in] func 条件
|
||||
*/
|
||||
template<typename C0, typename C1, typename F>
|
||||
bool Yes(const C0& container0, const C1& container1, F func)
|
||||
{
|
||||
if (container0.size() != container1.size())
|
||||
return false;
|
||||
auto iter0 = container0.begin();
|
||||
auto iter1 = container1.begin();
|
||||
while (iter0 != container0.end())
|
||||
{
|
||||
if (!func(*iter0, *iter1))
|
||||
return false;
|
||||
++iter0;
|
||||
++iter1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 克隆容器到另一个
|
||||
* @param[in] tar 目标容器
|
||||
* @param[in] src 源容器
|
||||
* @note tar会调整至src大小
|
||||
*/
|
||||
template<typename C0, typename C1>
|
||||
void Clone(C1& tar, const C0& src)
|
||||
{
|
||||
tar.resize(src.size());
|
||||
auto iter0 = src.begin();
|
||||
auto iter1 = tar.begin();
|
||||
while (iter0 != src.end())
|
||||
{
|
||||
*iter1++ = *iter0++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 复制容器
|
||||
* @param[in] tar 目标容器
|
||||
* @param[in] src 源容器
|
||||
* @note tar不会修改大小
|
||||
*/
|
||||
template<typename C0, typename C1>
|
||||
void Copy(C1& tar, const C0& src)
|
||||
{
|
||||
std::size_t num = (std::min)(tar.size(), src.size());
|
||||
auto iter0 = src.begin();
|
||||
auto iter1 = tar.begin();
|
||||
while (num--)
|
||||
{
|
||||
*iter1++ = *iter0++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @file dl_range_each_any.h
|
||||
* @brief 范围操作
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 26-03-19
|
||||
*
|
||||
* @note 对容器每个元素单独的操作(多对多的关系,任意满足)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "dl_concept.h"
|
||||
#include "base/dl_array.h"
|
||||
|
||||
//! 多对多遍历操作
|
||||
namespace dl::EachAny
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief 任意元素小于返回真
|
||||
*/
|
||||
template<typename T, size_t N>
|
||||
constexpr bool Less(const Array<T, N>& a, const Array<T, N>& b)
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
{
|
||||
if (a[i] < b[i])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* @file dl_range_erase.h
|
||||
* @brief 范围移除
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 23-07-15
|
||||
*
|
||||
* @note 从容器移除元素
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base/dl_range_any.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
//! 移除算法
|
||||
namespace dl::Erase
|
||||
{
|
||||
/**
|
||||
* @brief 从容器container中移除 最后 匹配到的a元素 之前(包含a)的所有元素,如果没有匹配到,则什么都不做。
|
||||
* @param container 操作的容器
|
||||
* @param[in] a 要匹配的元素
|
||||
* @remarks {"data/image/cat.png", '/'} -> "cat.png"
|
||||
*/
|
||||
template<typename T, typename V>
|
||||
bool HeadFromLast(T& container, const V& a)
|
||||
{
|
||||
auto iter = find(container.rbegin(), container.rend(), a);
|
||||
if (iter == container.rend())
|
||||
return false;
|
||||
container.erase(container.begin(), iter.base());
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @brief 从容器container中移除 最后 匹配到的a元素 之后(不包含a)的所有元素,如果没有匹配到,则什么都不做。
|
||||
* @param container 操作的容器
|
||||
* @param[in] a 要匹配的元素
|
||||
* @retval 成功移除返回true
|
||||
* @remarks {"data/image/cat.png", '.'} -> "data/image/cat."
|
||||
*/
|
||||
template<typename T, typename V>
|
||||
bool TailFromLast(T& container, const V& a)
|
||||
{
|
||||
auto iter = find(container.rbegin(), container.rend(), a);
|
||||
if (iter == container.rend())
|
||||
return false;
|
||||
container.erase(iter.base(), container.end());
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @brief 从容器container中移除 最开始 匹配到的a元素 之后(包含a)的所有元素,如果没有匹配到,则什么都不做。
|
||||
* @param container 操作的容器
|
||||
* @param[in] a 要匹配的元素
|
||||
* @remarks {"data/image/cat.png", '.'} -> "data/image/cat"
|
||||
*/
|
||||
template<typename T, typename V>
|
||||
bool TailFromFirst(T& container, const V& a)
|
||||
{
|
||||
auto iter = find(container.begin(), container.end(), a);
|
||||
if (iter == container.end())
|
||||
return false;
|
||||
container.erase(iter, container.end());
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @brief 从容器container中移除 最开始 匹配到的子容器a 之后(不包含a)的所有元素,如果没有匹配到,则什么都不做。
|
||||
* @param container 操作的容器
|
||||
* @param[in] a 要匹配的元素
|
||||
* @remarks {"data/image/cat.png", '.'} -> "data/image/cat."
|
||||
*/
|
||||
template<typename T>
|
||||
void TailFromFirstSub(T& container, const T& sub)
|
||||
{
|
||||
auto iter_cur = container.begin();
|
||||
auto iter_acur = sub.begin();
|
||||
auto iter_delete = iter_cur;
|
||||
bool isSuccess = false;
|
||||
for (iter_cur; iter_cur != container.end();)
|
||||
{
|
||||
while (*iter_cur == *iter_acur)
|
||||
{
|
||||
iter_cur++;
|
||||
iter_acur++;
|
||||
if (iter_acur == sub.end())
|
||||
{
|
||||
isSuccess = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isSuccess)
|
||||
break;
|
||||
iter_cur++;
|
||||
iter_acur = sub.begin();
|
||||
iter_delete = iter_cur;
|
||||
}
|
||||
if (isSuccess)
|
||||
container.erase(iter_delete, container.end());
|
||||
}
|
||||
/**
|
||||
* @brief 从容器a中移除 存在于容器b的元素
|
||||
*/
|
||||
template<typename T>
|
||||
void Match(T& a, const T& b)
|
||||
{
|
||||
for (auto iter = a.begin(); iter != a.end();)
|
||||
{
|
||||
if (Any::Equal(b, *iter))
|
||||
iter = a.erase(iter);
|
||||
else
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief 从容器a中移除 存在于容器b的元素
|
||||
*/
|
||||
template<typename T>
|
||||
T Match(const T& a, const T& b)
|
||||
{
|
||||
T ret;
|
||||
for (auto& iter : a)
|
||||
{
|
||||
if (!Any::Equal(b, iter))
|
||||
ret.push_back(b);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 移除子串,第一个
|
||||
* @retval 成功返回true
|
||||
*/
|
||||
template<typename T>
|
||||
bool HeadSub(T& a, const T& b)
|
||||
{
|
||||
auto iter0 = std::search(a.begin(), a.end(), b.begin(), b.end());
|
||||
if (iter0 == a.end())
|
||||
return false;
|
||||
auto iter1 = iter0;
|
||||
std::advance(iter1, b.size());
|
||||
a.erase(iter0, iter1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 移除子串,所有
|
||||
* @retval 返回移除数量
|
||||
*/
|
||||
template<typename T>
|
||||
size_t AllSub(T& a, const T& b)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (HeadSub(a, b))
|
||||
{
|
||||
++i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 移除第一个找到的值
|
||||
* @param[in] container 操作的容器
|
||||
* @param[in] v 比较的值
|
||||
*/
|
||||
template<typename C, typename V>
|
||||
bool First(C& container, const V& v)
|
||||
{
|
||||
for (auto iter = container.begin(); iter != container.end(); ++iter)
|
||||
{
|
||||
if (*iter == v)
|
||||
{
|
||||
container.erase(iter);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
/**
|
||||
* @file dl_range_every.h
|
||||
* @brief 范围操作
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 23-06-22
|
||||
*
|
||||
* @note 所有元素执行同一操作
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include "math/dl_algorithm.h"
|
||||
//! 多对一操作
|
||||
namespace dl::Every
|
||||
{
|
||||
/**
|
||||
* @brief 加
|
||||
*/
|
||||
template<typename C, typename T>
|
||||
void Add(C& c, const T& v)
|
||||
{
|
||||
for (auto& iter : c)
|
||||
iter += v;
|
||||
}
|
||||
template<typename C, typename T>
|
||||
[[nodiscard]]
|
||||
C Add(const C& c, const T& v)
|
||||
{
|
||||
C ret = c;
|
||||
Add(ret, v);
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @brief 减
|
||||
*/
|
||||
template<typename C, typename T>
|
||||
void Sub(C& c, const T& v)
|
||||
{
|
||||
for (auto& iter : c)
|
||||
iter -= v;
|
||||
}
|
||||
template<typename C, typename T>
|
||||
[[nodiscard]]
|
||||
C Sub(const C& c, const T& v)
|
||||
{
|
||||
C ret = c;
|
||||
Sub(ret, v);
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @brief 乘
|
||||
*/
|
||||
template<typename C, typename T>
|
||||
void Mul(C& c, const T& v)
|
||||
{
|
||||
for (auto& iter : c)
|
||||
iter *= v;
|
||||
}
|
||||
template<typename C, typename T>
|
||||
[[nodiscard]]
|
||||
C Mul(const C& c, const T& v)
|
||||
{
|
||||
C ret = c;
|
||||
Mul(ret, v);
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @brief 四舍五入
|
||||
*/
|
||||
template<typename C>
|
||||
void Round(C& c)
|
||||
{
|
||||
for (auto& iter : c)
|
||||
iter = std::round(iter);
|
||||
}
|
||||
template<typename C>
|
||||
[[nodiscard]]
|
||||
C Round(const C& c)
|
||||
{
|
||||
C ret = c;
|
||||
Round(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 取下界
|
||||
*/
|
||||
template<typename C>
|
||||
void Floor(C& c)
|
||||
{
|
||||
for (auto& iter : c)
|
||||
iter = std::floor(iter);
|
||||
}
|
||||
template<typename C>
|
||||
[[nodiscard]]
|
||||
C Floor(const C& c)
|
||||
{
|
||||
C ret = c;
|
||||
Floor(ret);
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @brief 取上界
|
||||
*/
|
||||
template<typename C>
|
||||
void Ceil(C& c)
|
||||
{
|
||||
for (auto& iter : c)
|
||||
iter = std::ceil(iter);
|
||||
}
|
||||
template<typename C>
|
||||
[[nodiscard]]
|
||||
C Ceil(const C& c)
|
||||
{
|
||||
C ret = c;
|
||||
Ceil(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 取[min, max]
|
||||
*/
|
||||
template<typename C, typename T>
|
||||
constexpr void Clamp(C& c, const T& v_min, const T& v_max)
|
||||
{
|
||||
for (auto& iter : c)
|
||||
iter = std::clamp(iter, v_min, v_max);
|
||||
}
|
||||
template<typename C, typename T>
|
||||
[[nodiscard]]
|
||||
constexpr C Clamp(const C& c, const T& v_min, const T& v_max)
|
||||
{
|
||||
C ret = c;
|
||||
Clamp(ret, v_min, v_max);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 取[min, +∞)
|
||||
*/
|
||||
template<typename C, typename T>
|
||||
constexpr void ClampFloor(C& c, const T& v_min)
|
||||
{
|
||||
for (auto& iter : c)
|
||||
{
|
||||
if (iter < v_min)
|
||||
iter = v_min;
|
||||
}
|
||||
}
|
||||
template<typename C, typename T>
|
||||
[[nodiscard]]
|
||||
constexpr C ClampFloor(const C& c, const T& v_min)
|
||||
{
|
||||
C ret = c;
|
||||
ClampFloor(ret, v_min);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 取[0, 1]
|
||||
*/
|
||||
template<typename C>
|
||||
void Saturate(C& c)
|
||||
{
|
||||
for (auto& iter : c)
|
||||
iter = saturate(iter);
|
||||
}
|
||||
template<typename C>
|
||||
[[nodiscard]]
|
||||
C Saturate(const C& c)
|
||||
{
|
||||
C ret = c;
|
||||
Saturate(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 取绝对值
|
||||
*/
|
||||
template<typename C>
|
||||
void Abs(C& c)
|
||||
{
|
||||
for (auto& iter : c)
|
||||
iter = std::abs(iter);
|
||||
}
|
||||
template<typename C>
|
||||
[[nodiscard]]
|
||||
C Abs(const C& c)
|
||||
{
|
||||
C ret = c;
|
||||
Abs(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 判断容器所有元素都等于某值
|
||||
* @param[in] c 操作的容器
|
||||
* @param[in] v 要比较的值
|
||||
*/
|
||||
template<typename C, typename V>
|
||||
bool Equal(const C& c, const V& v)
|
||||
{
|
||||
for (auto& iter : c)
|
||||
{
|
||||
if (iter != v)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 判断容器所有元素都 不等于某值
|
||||
* @param[in] container 操作的容器
|
||||
* @param[in] v 要比较的值
|
||||
*/
|
||||
template<typename C, typename V>
|
||||
bool NotEqual(const C& container, const V& v)
|
||||
{
|
||||
for (auto& iter : container)
|
||||
{
|
||||
if (iter == v)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename C>
|
||||
bool Zero(const C& c)
|
||||
{
|
||||
return Equal(c, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 移除容器所有元素都等于某值
|
||||
* @param[in] container 操作的容器
|
||||
* @param[in] v 要比较的值
|
||||
*/
|
||||
template<typename C, typename V>
|
||||
void Erase(C& container, const V& v)
|
||||
{
|
||||
for (auto iter = container.begin(); iter != container.end();)
|
||||
{
|
||||
if (*iter == v)
|
||||
iter = container.erase(iter);
|
||||
else
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief 移除容器所有元素都等于某值
|
||||
* @param[in] c 操作的容器
|
||||
* @param[in] v 要比较的值
|
||||
*/
|
||||
template<typename C, typename V>
|
||||
[[nodiscard]]
|
||||
C Erase(const C& c, const V& v)
|
||||
{
|
||||
C ret;
|
||||
for (auto& iter : c)
|
||||
{
|
||||
if (iter != v)
|
||||
ret.push_back(iter);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 移除容器所有元素 不在比较的容器
|
||||
* @param[in] container 操作的容器
|
||||
* @param[in] c_compare 比较的容器
|
||||
*/
|
||||
template<typename C, typename C1>
|
||||
size_t EraseNot(C& container, const C1& c_compare)
|
||||
{
|
||||
size_t ret = 0;
|
||||
for (auto iter = container.begin(); iter != container.end();)
|
||||
{
|
||||
auto iter1 = find(c_compare.begin(), c_compare.end(), *iter);
|
||||
if (iter1 == c_compare.end())
|
||||
{
|
||||
iter = container.erase(iter);
|
||||
++ret;
|
||||
}
|
||||
else
|
||||
++iter;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 替换容器所有元素都等于某值
|
||||
* @param[in] c 操作的容器
|
||||
* @param[in] v 要替换的值
|
||||
* @param[in] v_new 新值
|
||||
*/
|
||||
template<typename C, typename V>
|
||||
void Replace(C& c, const V& v, const V& v_new)
|
||||
{
|
||||
for (auto& iter : c)
|
||||
{
|
||||
if (iter == v)
|
||||
iter = v_new;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief 替换容器所有元素都等于某值
|
||||
* @param[in] c 操作的容器
|
||||
* @param[in] v 要替换的值
|
||||
* @param[in] v_new 新值
|
||||
*/
|
||||
template<typename C, typename V>
|
||||
[[nodiscard]]
|
||||
C Replace(const C& c, const V& v, const V& v_new)
|
||||
{
|
||||
C ret = c;
|
||||
Replace(ret, v, v_new);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 对容器每个元素进行delete操作
|
||||
* @param[in] c 操作的容器
|
||||
* @param[in] clear 为真时调用clear
|
||||
*/
|
||||
template<typename C>
|
||||
void Delete(C& c, bool clear = true)
|
||||
{
|
||||
for (auto& iter : c)
|
||||
{
|
||||
delete iter;
|
||||
}
|
||||
if (clear)
|
||||
c.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* @file dl_range_fill.h
|
||||
* @brief 填充操作
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 24-02-09
|
||||
*
|
||||
* @note 填充容器,不修改容器大小
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
//#include <algorithm>
|
||||
//#include <cmath>
|
||||
//
|
||||
//#include "math/dl_algorithm.h"
|
||||
|
||||
//! 填充算法(不改变容器大小)
|
||||
namespace dl::Fill
|
||||
{
|
||||
/**
|
||||
* @brief 填充同一值
|
||||
*/
|
||||
template<typename C, typename T>
|
||||
void Value(C& c, const T& v)
|
||||
{
|
||||
for (auto& iter : c)
|
||||
iter = v;
|
||||
}
|
||||
/**
|
||||
* @brief 填充0
|
||||
*/
|
||||
template<typename C, typename T>
|
||||
void Zero(C& c)
|
||||
{
|
||||
for (auto& iter : c)
|
||||
iter = 0;
|
||||
}
|
||||
/**
|
||||
* @brief 填充等差数列
|
||||
*/
|
||||
template<typename C, typename T>
|
||||
void Sequence(C& c, const T& a, const T& d = 1)
|
||||
{
|
||||
size_t i = 0;
|
||||
for (auto& iter : c)
|
||||
{
|
||||
iter = a + d * i;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief 填充array
|
||||
*/
|
||||
template<typename T, size_t N>
|
||||
constexpr Array<T, N> ArrayN(const T& v)
|
||||
{
|
||||
Array<T, N> ret;
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
{
|
||||
ret[i] = v;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @brief 填充array
|
||||
*/
|
||||
template<std::size_t N, typename T>
|
||||
constexpr Array<Size::value_type, N> Size(const T& v)
|
||||
{
|
||||
return ArrayN<Size::value_type, N>(v);
|
||||
}
|
||||
/**
|
||||
* @brief 填充vector
|
||||
*/
|
||||
template<typename T>
|
||||
std::vector<T> VectorN(const T& v, size_t n)
|
||||
{
|
||||
return { n, v };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* @file dl_range_find.h
|
||||
* @brief 查找
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 23-06-22
|
||||
*
|
||||
* @note
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base/dl_vector2.h"
|
||||
|
||||
//! 查找算法
|
||||
namespace dl::Find
|
||||
{
|
||||
/**
|
||||
* @brief find,返回下标
|
||||
* @note 失败返回-1
|
||||
*/
|
||||
template<typename T, typename V>
|
||||
size_t FirstIndex(const T& container, const V& v)
|
||||
{
|
||||
for (size_t i = 0; i < container.size(); ++i)
|
||||
{
|
||||
if (container[i] == v)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief find,返回下标
|
||||
* @note 失败返回 -1, -1
|
||||
*/
|
||||
//template<typename T, typename V>
|
||||
//SizeT FirstIndex(const Vector2<T, size_t>& container, const V& v)
|
||||
//{
|
||||
// for (size_t j = 0; j < container.GetHeight(); ++j)
|
||||
// {
|
||||
// for (size_t i = 0; i < container.GetWidth(); ++i)
|
||||
// {
|
||||
// if (container.Get(j, i) == v)
|
||||
// {
|
||||
// return { i, j };
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return { -1_zu, -1_zu };
|
||||
//}
|
||||
|
||||
/**
|
||||
* @brief find,返回指针
|
||||
* @note 失败返回nullptr
|
||||
*/
|
||||
template<typename C, typename F>
|
||||
auto FirstYes(C& container, F func)
|
||||
{
|
||||
for (auto& iter : container)
|
||||
{
|
||||
if (func(iter))
|
||||
{
|
||||
return &iter;
|
||||
}
|
||||
}
|
||||
using V = std::decay_t<decltype(container)>;
|
||||
using T = typename V::value_type;
|
||||
return (T*)nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* @file dl_range_select.h
|
||||
* @brief 范围操作
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 23-06-22
|
||||
*
|
||||
* @note 从容器选择最符合的一个元素
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include <numeric>
|
||||
#include <type_traits>
|
||||
|
||||
//! 容器选择操作
|
||||
namespace dl::Select
|
||||
{
|
||||
/**
|
||||
* @brief 返回容器最大值
|
||||
* @param[in] container 操作的容器
|
||||
* @retval 为空时,返回类型的最小值
|
||||
*/
|
||||
template<typename C>
|
||||
constexpr auto Max(const C& container)
|
||||
{
|
||||
using V = std::decay_t<decltype(container)>;
|
||||
using T = typename V::value_type;
|
||||
T ret = std::numeric_limits<T>::lowest();
|
||||
for (auto& iter : container)
|
||||
{
|
||||
ret = (std::max)(ret, iter);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @brief 返回容器最小值
|
||||
* @param[in] container 操作的容器
|
||||
* @retval 为空时,返回类型的最大值
|
||||
*/
|
||||
template<typename C>
|
||||
constexpr auto Min(const C& container)
|
||||
{
|
||||
using V = std::decay_t<decltype(container)>;
|
||||
using T = typename V::value_type;
|
||||
T ret = (std::numeric_limits<T>::max)();
|
||||
for (auto& iter : container)
|
||||
{
|
||||
ret = (std::min)(ret, iter);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 返回容器最大值(计算结果)
|
||||
* @param[in] container 操作的容器
|
||||
* @retval 为空时,返回类型的最小值
|
||||
*/
|
||||
template<typename C, typename F>
|
||||
constexpr auto Max(const C& container, F func)
|
||||
{
|
||||
using V = std::decay_t<decltype(container)>;
|
||||
using T = typename V::value_type;
|
||||
using T1 = decltype(func(T{}));
|
||||
T1 ret = (std::numeric_limits<T1>::min)();
|
||||
for (auto& iter : container)
|
||||
{
|
||||
ret = (std::max)(ret, func(iter));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @brief 返回容器最小值(计算结果)
|
||||
* @param[in] container 操作的容器
|
||||
* @retval 为空时,返回类型的最大值
|
||||
*/
|
||||
template<typename C, typename F>
|
||||
constexpr auto Min(const C& container, F func)
|
||||
{
|
||||
using V = std::decay_t<decltype(container)>;
|
||||
using T = typename V::value_type;
|
||||
using T1 = decltype(func(T{}));
|
||||
T1 ret = (std::numeric_limits<T1>::max)();
|
||||
for (auto& iter : container)
|
||||
{
|
||||
ret = (std::min)(ret, func(iter));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 返回容器最大值
|
||||
* @param[in] container 操作的容器,不能为空
|
||||
* @retval 返回对象的引用
|
||||
*/
|
||||
template<typename C, typename F>
|
||||
constexpr auto& MaxRef(C& container, F func)
|
||||
{
|
||||
using V = std::decay_t<decltype(container)>;
|
||||
using T = typename V::value_type;
|
||||
using T_RET = std::invoke_result_t<F, T&>;
|
||||
T_RET v_max = (std::numeric_limits<T_RET>::min)();
|
||||
T& ret = *container.begin();
|
||||
for (auto& iter : container)
|
||||
{
|
||||
T_RET v = func(iter);
|
||||
if (v > v_max)
|
||||
{
|
||||
v_max = v;
|
||||
ret = iter;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @brief 返回容器最小值
|
||||
* @param[in] container 操作的容器,不能为空
|
||||
* @retval 返回对象的引用
|
||||
*/
|
||||
template<typename C, typename F>
|
||||
constexpr auto& MinRef(C& container, F func)
|
||||
{
|
||||
using V = std::decay_t<decltype(container)>;
|
||||
using T = typename V::value_type;
|
||||
using T_RET = std::invoke_result_t<F, T&>;
|
||||
T_RET v_min = (std::numeric_limits<T_RET>::max)();
|
||||
T& ret = *container.begin();
|
||||
for (auto& iter : container)
|
||||
{
|
||||
T_RET v = func(iter);
|
||||
if (v < v_min)
|
||||
{
|
||||
v_min = v;
|
||||
ret = iter;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取容器元素,如果小了,就扩容
|
||||
* @attention 对引用取地址,并非原本引用对象的地址
|
||||
* @attention resize可能导致重分配内存,但不会修改旧元素值
|
||||
*/
|
||||
template<typename T>
|
||||
T& CreateIfEmpty(std::vector<T>& vec, std::size_t n)
|
||||
{
|
||||
if (n >= vec.size())
|
||||
vec.resize(n + 1);
|
||||
return vec[n];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取容器元素,如果小了,就扩容
|
||||
*/
|
||||
template<typename T>
|
||||
T* CreateIfEmpty(std::vector<T>* vec, std::size_t n)
|
||||
{
|
||||
if (n >= vec->size())
|
||||
vec->resize(n + 1);
|
||||
return &(*vec)[n];
|
||||
}
|
||||
/**
|
||||
* @brief 获取容器元素,如果小了,就扩容
|
||||
*/
|
||||
template<typename T>
|
||||
T& CreateIfEmpty(std::vector<std::vector<T>>& vec, std::size_t n0, std::size_t n1)
|
||||
{
|
||||
if (n0 >= vec.size())
|
||||
vec.resize(n0 + 1);
|
||||
return CreateIfEmpty(vec[n0], n1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* @file dl_range_sub.h
|
||||
* @brief 子串操作
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
* @author lveyou
|
||||
* @date 23-06-22
|
||||
*
|
||||
* @note
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
//! 类似子串的操作
|
||||
namespace dl::Sub
|
||||
{
|
||||
/**
|
||||
* @brief 子串匹配
|
||||
* @param a 容器a
|
||||
* @param b 容器b
|
||||
* @retval b是a的子串,则返回true
|
||||
*/
|
||||
template<typename T>
|
||||
bool IsSub(const T& a, const T& b)
|
||||
{
|
||||
return std::search(a.begin(), a.end(), b.begin(), b.end()) != a.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 子串匹配
|
||||
* @retval b是a的子串,并且在头部,则返回true
|
||||
*/
|
||||
template<typename T>
|
||||
bool IsBegin(const T& a, const T& b)
|
||||
{
|
||||
auto iter_a = a.begin();
|
||||
auto iter_b = b.begin();
|
||||
while (iter_b != b.end())
|
||||
{
|
||||
if (iter_a == a.end())
|
||||
return false;
|
||||
if (*iter_b != *iter_a)
|
||||
return false;
|
||||
++iter_a;
|
||||
++iter_b;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 区间匹配
|
||||
* @retval 从c中取得 (a, b)
|
||||
* @note 传入name(xx)yy)、(、),返回xx
|
||||
*/
|
||||
template<typename T, typename V>
|
||||
T Range(const T& c, const V& a, const V& b)
|
||||
{
|
||||
auto iter_a = std::find(c.begin(), c.end(), a);
|
||||
if (iter_a == c.end())
|
||||
return {};
|
||||
++iter_a;
|
||||
auto iter_b = iter_a;
|
||||
|
||||
while (iter_b != c.end())
|
||||
{
|
||||
if (*iter_b == b)
|
||||
return { iter_a, iter_b };
|
||||
++iter_b;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
/**
|
||||
* @brief 返回尾部
|
||||
* @retval 从c中取得 (a, 正无穷)
|
||||
*/
|
||||
template<typename T, typename V>
|
||||
T Tail(const T& c, const V& a)
|
||||
{
|
||||
auto iter = std::find(c.begin(), c.end(), a);
|
||||
if (iter == c.end())
|
||||
return {};
|
||||
return { ++iter , c.end() };
|
||||
}
|
||||
/**
|
||||
* @brief 子串匹配
|
||||
* @retval b是a的子串,并且在尾部,则返回true
|
||||
*/
|
||||
template<typename T>
|
||||
bool IsTail(const T& a, const T& b)
|
||||
{
|
||||
auto iter_a = a.rbegin();
|
||||
auto iter_b = b.rbegin();
|
||||
while (iter_b != b.rend())
|
||||
{
|
||||
if (iter_a == a.rend())
|
||||
return false;
|
||||
if (*iter_b != *iter_a)
|
||||
return false;
|
||||
++iter_a;
|
||||
++iter_b;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//template <typename T, typename F>
|
||||
//T RangeUntil(const T& c, const F& func)
|
||||
//{
|
||||
//
|
||||
//}
|
||||
|
||||
/**
|
||||
* @brief 子串替换
|
||||
* @param[in] a 原串
|
||||
* @param[in] sub 子串
|
||||
* @param[in] tar 替换为
|
||||
* @note 替换所有子串
|
||||
*/
|
||||
template<typename T>
|
||||
T ReplaceAll(const T& a, const T& sub, const T& tar)
|
||||
{
|
||||
if (sub.empty())
|
||||
return a;
|
||||
T ret;
|
||||
auto iter_a = a.begin();
|
||||
while (iter_a != a.end())
|
||||
{
|
||||
bool equal = true;
|
||||
auto iter0 = iter_a;
|
||||
auto iter1 = sub.begin();
|
||||
while (iter1 != sub.end())
|
||||
{
|
||||
if (iter0 == a.end()
|
||||
|| iter1 == sub.end()
|
||||
|| *iter0 != *iter1)
|
||||
{
|
||||
equal = false;
|
||||
break;
|
||||
}
|
||||
++iter0;
|
||||
++iter1;
|
||||
}
|
||||
if (equal)
|
||||
{
|
||||
ret += tar;
|
||||
iter_a += sub.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.push_back(*iter_a);
|
||||
++iter_a;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,331 @@
|
||||
#include "dl_string.h"
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
||||
#include <wcwidth.h>
|
||||
|
||||
|
||||
namespace dl
|
||||
{
|
||||
std::string to_string(std::error_code code)
|
||||
{
|
||||
return fmt::format("{}({}): {}",
|
||||
code.category().name(),
|
||||
code.value(),
|
||||
CodeCvt::MultiByteToUtf8(code.message()));
|
||||
}
|
||||
|
||||
std::string to_string(std::exception& e)
|
||||
{
|
||||
return CodeCvt::MultiByteToUtf8(e.what());
|
||||
}
|
||||
|
||||
namespace String
|
||||
{
|
||||
std::string Sprintf(const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
int len;
|
||||
|
||||
va_start(args, format);
|
||||
len = vsnprintf(nullptr, 0, format, args) + 1;
|
||||
va_end(args);
|
||||
|
||||
std::string ret;
|
||||
ret.resize(len);
|
||||
|
||||
va_start(args, format);
|
||||
vsnprintf((char*)ret.data(), len, format, args);
|
||||
va_end(args);
|
||||
|
||||
ret.pop_back();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::string CvtRelativePath(std::string path_cur, std::string_view path)
|
||||
{
|
||||
if (!IsRelativePath(path))
|
||||
return std::string{ path };
|
||||
|
||||
|
||||
//直到首位不是 “./”和“../”
|
||||
size_t i = 0;
|
||||
size_t size = path.size();
|
||||
while ((i < size)
|
||||
&& (path[i] == '.'))
|
||||
{
|
||||
if ((i + 1 < size)
|
||||
&& (path[i + 1] == '/'))
|
||||
{//当前目录
|
||||
i += 2;
|
||||
}
|
||||
else if ((i + 2 < size)
|
||||
&& (path[i + 1] == '.' && path[i + 2] == '/'))
|
||||
{//向上目录
|
||||
i += 3;
|
||||
path_cur.pop_back();
|
||||
Erase::TailFromLast(path_cur, '/');
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
return path_cur + std::string(path.begin() + i, path.end());
|
||||
}
|
||||
|
||||
bool GetPathAndRes(std::string_view path_root, std::string_view path_name, std::string& path_real, std::string& res_name, std::string_view name /*= ""*/)
|
||||
{
|
||||
if (IsRelativePath(path_name))
|
||||
{
|
||||
path_real = fmt::format("{}{}", path_root, path_name);
|
||||
if (name.empty())
|
||||
{
|
||||
res_name = path_name;
|
||||
if (Erase::TailFromLast(res_name, '.'))
|
||||
res_name.pop_back();//去后缀
|
||||
Every::Replace(res_name, '/', '.');//斜杠变.
|
||||
}
|
||||
else
|
||||
res_name = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (name.empty())
|
||||
{
|
||||
path_real = path_name;
|
||||
res_name = "error";
|
||||
log_err0("绝对路径加载,必须设定资源名字!");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
path_real = path_name;
|
||||
res_name = name;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string GetResName(std::string_view path_root, std::string_view path_name)
|
||||
{
|
||||
std::string name = std::string{ path_name };
|
||||
auto iter_path = name.find(path_root);
|
||||
if (iter_path != 0)
|
||||
{
|
||||
log_err0("路径错误:" + std::string{ name });
|
||||
}
|
||||
else
|
||||
name.erase(0, path_root.size());
|
||||
|
||||
if (Erase::TailFromLast(name, '.'))//去后缀
|
||||
{
|
||||
name.pop_back();
|
||||
}
|
||||
|
||||
if (Any::Equal(name, '\\'))
|
||||
{
|
||||
log_err("路径存在反斜杠:{}", name);
|
||||
Every::Replace(name, '\\', '.');
|
||||
}
|
||||
Every::Replace(name, '/', '.');
|
||||
return name;
|
||||
}
|
||||
|
||||
std::vector<std::string> FormatString2(const Vector2<std::string>& arr)
|
||||
{
|
||||
auto W = arr.GetWidth();
|
||||
auto H = arr.GetHeight();
|
||||
using Index = decltype(W);
|
||||
|
||||
//每一列得到一个最大宽度
|
||||
std::vector<Index> mul_col;
|
||||
mul_col.resize(W);
|
||||
for (Index j = 0; j < H; ++j)
|
||||
{
|
||||
for (Index i = 0; i < W; ++i)
|
||||
{
|
||||
if (arr[j][i].size() > mul_col[i])
|
||||
mul_col[i] = (Index)arr[j][i].size();
|
||||
}
|
||||
}
|
||||
//合并每行
|
||||
std::vector<std::string> ret;
|
||||
ret.resize(H);
|
||||
for (Index i = 0; i < W; ++i)
|
||||
{
|
||||
std::string fmt = std::string("{:<") + std::to_string(mul_col[i] + 1) + "}";
|
||||
for (Index j = 0; j < H; ++j)
|
||||
{
|
||||
ret[j] += fmt::vformat(fmt, fmt::make_format_args(arr[j][i]));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<std::string> ParseCommand(std::string_view cmd)
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
if (cmd.empty())
|
||||
return ret;
|
||||
size_t i = 0;
|
||||
// 跳过起始空白
|
||||
while (cmd[i] == ' ' || cmd[i] == '\t')
|
||||
{
|
||||
++i;
|
||||
}
|
||||
|
||||
int mode = 0; // 空白模式、普通匹配、字符串模式
|
||||
std::string temp;
|
||||
while (cmd[i])
|
||||
{
|
||||
const char& ch = cmd[i];
|
||||
if (mode == 0)
|
||||
{
|
||||
if (ch == '\"')
|
||||
mode = 2;
|
||||
else if (ch == ' ' || ch == '\t')
|
||||
;
|
||||
else
|
||||
{
|
||||
temp.push_back(ch);
|
||||
mode = 1;
|
||||
}
|
||||
}
|
||||
else if (mode == 1)
|
||||
{
|
||||
if (ch == ' ' || ch == '\t')
|
||||
{
|
||||
ret.push_back(temp);
|
||||
temp.clear();
|
||||
mode = 0;
|
||||
}
|
||||
else
|
||||
temp.push_back(ch);
|
||||
}
|
||||
else if (mode == 2)
|
||||
{
|
||||
if (ch == '\"' && (i + 1 >= cmd.size() || cmd[i + 1] == ' ' || cmd[i + 1] == '\t'))
|
||||
{
|
||||
ret.push_back(temp);
|
||||
temp.clear();
|
||||
mode = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp.push_back(ch);
|
||||
}
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
// 添加最后一个参数
|
||||
if (!temp.empty())
|
||||
ret.push_back(temp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string FillEndl(std::string_view str, char ch /*= ' '*/)
|
||||
{
|
||||
std::wstring wstr = CodeCvt::Utf8ToWideChar(str);
|
||||
|
||||
size_t max_w = 0;
|
||||
size_t count = 0;
|
||||
for (auto& iter : wstr)
|
||||
{
|
||||
if (iter != L'\n')
|
||||
count += Wcwidth(iter);
|
||||
else
|
||||
{
|
||||
if (count > max_w)
|
||||
max_w = count;
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
std::wstring ret;
|
||||
count = 0;
|
||||
for (auto& iter : wstr)
|
||||
{
|
||||
if (iter != L'\n')
|
||||
{
|
||||
ret.push_back(iter);
|
||||
count += Wcwidth(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; count < max_w; ++count)
|
||||
ret.push_back(ch);
|
||||
ret.push_back(L'\n');
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
return CodeCvt::WideCharToUtf8(ret);
|
||||
}
|
||||
|
||||
size_t Wcwidth(wchar_t ch)
|
||||
{
|
||||
int ret = wcwidth(ch);
|
||||
//log_warn("{}:{}", GetUtf8ByWchar(ch), ret);
|
||||
if (ret < 0)
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string to_string(BufferView buf)
|
||||
{
|
||||
std::string ret = { (char*)buf.data(), buf.size() };
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::string to_string_hex(BufferView buf, bool upper/* = false*/, bool add_tag /*= false*/)
|
||||
{
|
||||
std::string ret;
|
||||
if (add_tag)
|
||||
ret += "0x";
|
||||
|
||||
if (!upper)
|
||||
{
|
||||
for (size_t i = 0; i < buf.size(); ++i)
|
||||
{
|
||||
ret += fmt::format("{:02x}", (unsigned char)buf[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < buf.size(); ++i)
|
||||
{
|
||||
ret += fmt::format("{:02X}", (unsigned char)buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string to_string_check(BufferView buf, bool tips)
|
||||
{
|
||||
std::string ret = { (char*)buf.data(), buf.size() };
|
||||
if (!CodeCvt::Utf8::Check(ret))
|
||||
{
|
||||
if(tips)
|
||||
log_warn("转换失败,非utf8编码!");
|
||||
return {};
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string to_string_auto(BufferView buf, bool add_tag /*= false*/)
|
||||
{
|
||||
std::string ret = to_string_check(buf, false);
|
||||
if (!ret.empty())
|
||||
return ret;
|
||||
return to_string_hex(buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||