Compare commits
419 Commits
3.0
...
2.1.2-stab
| Author | SHA1 | Date | |
|---|---|---|---|
| c508b5b2e1 | |||
| b65e553440 | |||
| 7c47769aa2 | |||
| 0669c9816e | |||
| 23789f49dd | |||
| 8e380677cb | |||
| e4bbc1067a | |||
| 5aac8eeb0f | |||
| b351d4cbc1 | |||
| 1f2293d5cc | |||
| 8322c1aa64 | |||
| 8fca6870c4 | |||
| 9f3c594f9e | |||
| b3d0596c4b | |||
| 6b5a852bd8 | |||
| 25a62a3e32 | |||
| b61d7e6261 | |||
| 9c8ecb45f8 | |||
| 8a5596322d | |||
| 93a83c81f0 | |||
| af7fd899f4 | |||
| d66740175e | |||
| 5672852351 | |||
| 349e62835b | |||
| ff490e42da | |||
| b1fc41a301 | |||
| 3cd976366e | |||
| 6e9584e0c5 | |||
| c24c2ca17b | |||
| d2240404e3 | |||
| 01b8beb023 | |||
| 4f35fdd1e3 | |||
| 0b6d4e92b5 | |||
| d8223ffa75 | |||
| b5bdc60f58 | |||
| ba50bb9cb1 | |||
| 2a60bf1cd9 | |||
| 1bb1b6986c | |||
| 4c9c43735a | |||
| 6940830627 | |||
| 27a801df99 | |||
| f520e7788e | |||
| 580031e6f5 | |||
| d5e4011bc3 | |||
| 1397019424 | |||
| eea6c43676 | |||
| 3a4c412153 | |||
| 9b0be3753b | |||
| 5698571235 | |||
| 0701e7c2d8 | |||
| 2fbae72d14 | |||
| dbeb1ca114 | |||
| 0aebdb346a | |||
| 71b35c527f | |||
| a282579f5c | |||
| f08aa02688 | |||
| a8bc2f64ad | |||
| 85585c7fc5 | |||
| c5bff5073e | |||
| f10a78e5c0 | |||
| 5354d7ddcc | |||
| ff3891f88e | |||
| 5bfd0bbe5e | |||
| fa816730c0 | |||
| 01f3399ed0 | |||
| 1e34e8d5e1 | |||
| f184455187 | |||
| c07fe5e8de | |||
| 5b27f05e7e | |||
| 2e74bdab35 | |||
| 916e79a5bf | |||
| f95694ee86 | |||
| 6227e8f343 | |||
| 608e3f3097 | |||
| ef009a8b91 | |||
| 1a41d3351a | |||
| 17399de0e1 | |||
| fe81402257 | |||
| b56c00cc56 | |||
| 13cdc2a6f5 | |||
| fd5e01d1cd | |||
| b328d2eb00 | |||
| fde651ebf8 | |||
| 39ce4a49fa | |||
| 6ad84850ab | |||
| c0743f898a | |||
| 8589a1b117 | |||
| 40de567297 | |||
| 1e646e2797 | |||
| 4a7d5f7b0e | |||
| a86dae5761 | |||
| 7a77fd1cd5 | |||
| ac9f0aea1a | |||
| 3bb1709fd7 | |||
| 00fdcf3cd0 | |||
| 7ef71b9013 | |||
| e8a6cbc897 | |||
| 47ae6c6507 | |||
| 5e79ac72b7 | |||
| a46a643f90 | |||
| c030e602e5 | |||
| 19b31297ec | |||
| 4635671de5 | |||
| 8f23be8752 | |||
| 490f51a202 | |||
| 1a7f14b206 | |||
| e1dfaaf786 | |||
| 3f6fe2f3f1 | |||
| 2fff8e8cde | |||
| 754e9aa60a | |||
| a2048efd72 | |||
| 70a6791150 | |||
| 6e0de0cce8 | |||
| 04def2161e | |||
| b3443fd848 | |||
| 5546929712 | |||
| d8b0070b8c | |||
| 904285f4b4 | |||
| 53fea7f196 | |||
| fd1022fd29 | |||
| 24a440a34f | |||
| 5ede1a1226 | |||
| 17422f1f86 | |||
| 49e22aa83f | |||
| 6d86a63648 | |||
| a3582fa3cb | |||
| 326978dcce | |||
| 76233a3022 | |||
| ed2c369785 | |||
| 220bcbf7c0 | |||
| 3e2247ca53 | |||
| bf3cf5505e | |||
| bcc887bbe5 | |||
| 9b32df9cab | |||
| 601f056b6f | |||
| 14b46c4263 | |||
| 8a813e2a1e | |||
| 679e9f413c | |||
| 19ce11b908 | |||
| 28944e95e7 | |||
| 2d6dabc68e | |||
| 9219ac7e44 | |||
| e3dc319f78 | |||
| 221346521c | |||
| f1c2d70f1a | |||
| 3e127ce3fd | |||
| 0413d85add | |||
| 7d09222b37 | |||
| dd8b87f58e | |||
| 36a4c54593 | |||
| 51fe9fc132 | |||
| 9e1e5daddf | |||
| bc8dabf3d2 | |||
| fada9d7a8e | |||
| 82b458f160 | |||
| 64f38490df | |||
| c282ac8ec7 | |||
| 210618c5e2 | |||
| 2b00fdc679 | |||
| d7ec768805 | |||
| 86c6aabf27 | |||
| e5f210693c | |||
| 7e3360ae01 | |||
| 67f65f6639 | |||
| dbca4ee3fe | |||
| cd828bd5fc | |||
| da4a870bc4 | |||
| ce54b6ea8b | |||
| 5ee9a9962f | |||
| f629b1fd3e | |||
| eaf803f71e | |||
| a7389217f8 | |||
| e259bf8bbb | |||
| 561c1f17a1 | |||
| 7c92b401f1 | |||
| d44e6ea268 | |||
| 1185da656f | |||
| c78aef5812 | |||
| 91af714d39 | |||
| 5033fc92f4 | |||
| 1038c1f856 | |||
| 8087be05c7 | |||
| a20da0c048 | |||
| d67bbd183e | |||
| 647b287a1e | |||
| 91df1ebff6 | |||
| 62d1e39113 | |||
| b492dd78bd | |||
| a27aee241c | |||
| e3be51f87c | |||
| 68b6b50d28 | |||
| 06c47e6f8a | |||
| e56961f58b | |||
| b0013f32bf | |||
| 58daf901f9 | |||
| 887b1de1db | |||
| caf42f77d2 | |||
| 9f9d1eed7b | |||
| 0af331d1c0 | |||
| 7a17d72e84 | |||
| 52bf8bd168 | |||
| f3b42e049d | |||
| a130520a7c | |||
| 85a7105345 | |||
| dcd4b80c13 | |||
| 5a49e45d21 | |||
| 7143401e25 | |||
| f4414e3e03 | |||
| aa1367595e | |||
| d96842b80e | |||
| 8bf3bc3449 | |||
| f1bd2f6f56 | |||
| e04ec9565b | |||
| 8263fca121 | |||
| 1022705707 | |||
| 4ff4177acc | |||
| c8a97c3678 | |||
| 82e8721715 | |||
| bfea3f1d9a | |||
| 4cd640f684 | |||
| 995dcb610c | |||
| 55414bc573 | |||
| 819ccdd340 | |||
| ea1e180e4a | |||
| 575e986bde | |||
| 846db09038 | |||
| fae2863a5e | |||
| 56b03e7208 | |||
| c9d7f77c6f | |||
| 14e45a55d4 | |||
| 7d25d20861 | |||
| e88a540b91 | |||
| 2287bac8f7 | |||
| 00b0f3dfde | |||
| 64b083b496 | |||
| 9b71cae50f | |||
| 8a8ace8fa0 | |||
| 2261c65f19 | |||
| a418304def | |||
| ea48675ffa | |||
| d5ee98bb2c | |||
| 728ac94313 | |||
| a8502ae6f6 | |||
| 04255541a0 | |||
| 17edff2f84 | |||
| b4edaa892d | |||
| 81bc271619 | |||
| 5f540a17cc | |||
| 4b6809a2b3 | |||
| 280728c0c7 | |||
| 35cdb1a49b | |||
| 3df8f79c9f | |||
| 99d82f3033 | |||
| f250c0cf50 | |||
| 55a5631986 | |||
| 8cb09bf9d0 | |||
| 58e2652f94 | |||
| 3f941faf4d | |||
| b3bf3c392a | |||
| c757787fed | |||
| 1ae1deabfa | |||
| 22680a30f1 | |||
| ce1138cb02 | |||
| a139c7afe6 | |||
| e51cd3d454 | |||
| a7d6894a9f | |||
| 6775cce469 | |||
| 9e20b39b3d | |||
| 0462bf01a2 | |||
| cf427eeb7a | |||
| cd03f8cce2 | |||
| d0ff75c91c | |||
| 82dfaf7af6 | |||
| c0ba08b8d5 | |||
| ba095b8dcc | |||
| 9593863a92 | |||
| 97ebfddaaf | |||
| 342b1408d5 | |||
| 359b5f3b25 | |||
| 5b942f056a | |||
| 44ba542de6 | |||
| f63b338e0f | |||
| 13108317ae | |||
| 12d4d65668 | |||
| 56dc7aa568 | |||
| f315d352ec | |||
| ef0bcc7e20 | |||
| b2a58da321 | |||
| de13e52b9b | |||
| 73e7ccabf5 | |||
| 721599c797 | |||
| ab231cd3fb | |||
| 268b3446c6 | |||
| d7925ca09d | |||
| d613952300 | |||
| a3c58999e2 | |||
| 4b2243f82e | |||
| 6fc894d652 | |||
| 5adb75c2e7 | |||
| a827734e03 | |||
| f4f5855168 | |||
| f4da1e9ed2 | |||
| a5fe7ffbcd | |||
| 02487a4be1 | |||
| 228ee4363e | |||
| 36b1521cdc | |||
| d1ad94acf0 | |||
| 63b5a80088 | |||
| 45a5769162 | |||
| b9399e93ad | |||
| 33223e7a8a | |||
| 12edde80f2 | |||
| c8299249e4 | |||
| 1d175be921 | |||
| 94e5c48004 | |||
| 4084ec4869 | |||
| d3b549f2a3 | |||
| 4ca83c635f | |||
| e788ffff65 | |||
| 6a0d47f34c | |||
| e6d49fb54c | |||
| eed5d878e8 | |||
| 521b5bd90f | |||
| 8dca3f3f42 | |||
| d2aa006ddb | |||
| ec32c33799 | |||
| 9b9870ed9f | |||
| a72945f4e3 | |||
| 3ff8dea5f9 | |||
| 2b43d0a028 | |||
| ee23649813 | |||
| 75f51aece9 | |||
| 5653ac41f9 | |||
| 6c22cab856 | |||
| 71dc733ad2 | |||
| 04ade4d639 | |||
| 20c3b35dd5 | |||
| 323dec7dd5 | |||
| 3b691907e9 | |||
| 85eca7bc93 | |||
| 2e6ce4b362 | |||
| a1df4f138c | |||
| 0aad82e921 | |||
| aae720e488 | |||
| 772a590261 | |||
| f90370886f | |||
| c44757c2b7 | |||
| ffe5ecd67d | |||
| e0ddef3164 | |||
| 7178399548 | |||
| c007d31e52 | |||
| 3f30a22cb0 | |||
| d6dc8f4644 | |||
| c4f79716d3 | |||
| 4a9461fded | |||
| 49dd7b38bc | |||
| bfcfb58efc | |||
| ed96689d8c | |||
| 125a9f0b06 | |||
| fd58f8dce8 | |||
| adcf45b627 | |||
| 48d1e8bd4e | |||
| 73b40d1457 | |||
| e7772e43d3 | |||
| de5f49aac5 | |||
| 2ab7e6daab | |||
| 68c7da5a35 | |||
| a3a065b458 | |||
| 9ea76ff46d | |||
| cd6afd5f1d | |||
| 265715f5b2 | |||
| cd8beea3bf | |||
| 0657d43960 | |||
| a21b9caa2a | |||
| 83864514f9 | |||
| b1ea299edf | |||
| 103b04e529 | |||
| 07caf4438d | |||
| 6df46803a7 | |||
| cccc35e427 | |||
| fa1f5e55de | |||
| 6a563949c7 | |||
| f9aeb91850 | |||
| 71a9efe604 | |||
| 5f9e6d2b48 | |||
| 6327fc47c8 | |||
| 3cbd6b8701 | |||
| 4890db7fef | |||
| df3d2b25d8 | |||
| 743c63670e | |||
| e26acc39da | |||
| 1a53c4d3c2 | |||
| 37fc61f986 | |||
| 16fc229e5d | |||
| 4f07998552 | |||
| 3b7ab73cab | |||
| bbb543735c | |||
| ed931d3b59 | |||
| 720305d98e | |||
| 676b60a8b5 | |||
| 0c76ba32cc | |||
| c5e2c83dcd | |||
| 9cc700a0ab | |||
| 569966f3bb | |||
| 58556f5f95 | |||
| 229b172977 | |||
| c56ea7cf91 | |||
| 1913e4a040 | |||
| 2b35ba4815 | |||
| d853eb2fb7 | |||
| 36eeedb357 | |||
| 5f18c5cb46 | |||
| f25e9a08e1 | |||
| 4f8f9a4dbf | |||
| dd97502788 | |||
| d55304c56f | |||
| 03a4b8cbc8 | |||
| 2f0df52fe7 | |||
| fd6f62fd9a |
@ -1,35 +0,0 @@
|
||||
os: Visual Studio 2015
|
||||
|
||||
environment:
|
||||
HOME: "%HOMEDRIVE%%HOMEPATH%"
|
||||
PYTHON: C:\Python27
|
||||
SCONS_CACHE_ROOT: "%HOME%\\scons_cache"
|
||||
SCONS_CACHE_LIMIT: 512
|
||||
matrix:
|
||||
- VS: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
|
||||
GD_PLATFORM: windows
|
||||
TOOLS: yes
|
||||
TARGET: release_debug
|
||||
ARCH: amd64
|
||||
|
||||
init:
|
||||
- ps: if ($env:APPVEYOR_REPO_BRANCH -ne "master") { $env:APPVEYOR_CACHE_SKIP_SAVE = "true" }
|
||||
|
||||
cache:
|
||||
- "%SCONS_CACHE_ROOT%"
|
||||
|
||||
install:
|
||||
- SET "PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
|
||||
- pip install -U wheel # needed for pip install scons to work, otherwise a flag is missing
|
||||
- pip install scons==3.0.1
|
||||
- if defined VS call "%VS%" %ARCH% # if defined - so we can also use mingw
|
||||
|
||||
before_build:
|
||||
- echo %GD_PLATFORM%
|
||||
- python --version
|
||||
- scons --version
|
||||
- cl.exe
|
||||
- set "SCONS_CACHE=%SCONS_CACHE_ROOT%\%APPVEYOR_REPO_BRANCH%"
|
||||
|
||||
build_script:
|
||||
- scons platform=%GD_PLATFORM% target=%TARGET% tools=%TOOLS% verbose=yes progress=no gdnative_wrapper=yes
|
||||
126
.clang-format
126
.clang-format
@ -1,126 +0,0 @@
|
||||
# Commented out parameters are those with the same value as base LLVM style
|
||||
# We can uncomment them if we want to change their value, or enforce the
|
||||
# chosen value in case the base style changes (last sync: Clang 6.0.1).
|
||||
---
|
||||
### General config, applies to all languages ###
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
# AlignConsecutiveAssignments: false
|
||||
# AlignConsecutiveDeclarations: false
|
||||
# AlignEscapedNewlines: Right
|
||||
# AlignOperands: true
|
||||
AlignTrailingComments: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
# AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortIfStatementsOnASingleLine: true
|
||||
# AllowShortLoopsOnASingleLine: false
|
||||
# AlwaysBreakAfterDefinitionReturnType: None
|
||||
# AlwaysBreakAfterReturnType: None
|
||||
# AlwaysBreakBeforeMultilineStrings: false
|
||||
# AlwaysBreakTemplateDeclarations: false
|
||||
# BinPackArguments: true
|
||||
# BinPackParameters: true
|
||||
# BraceWrapping:
|
||||
# AfterClass: false
|
||||
# AfterControlStatement: false
|
||||
# AfterEnum: false
|
||||
# AfterFunction: false
|
||||
# AfterNamespace: false
|
||||
# AfterObjCDeclaration: false
|
||||
# AfterStruct: false
|
||||
# AfterUnion: false
|
||||
# AfterExternBlock: false
|
||||
# BeforeCatch: false
|
||||
# BeforeElse: false
|
||||
# IndentBraces: false
|
||||
# SplitEmptyFunction: true
|
||||
# SplitEmptyRecord: true
|
||||
# SplitEmptyNamespace: true
|
||||
# BreakBeforeBinaryOperators: None
|
||||
# BreakBeforeBraces: Attach
|
||||
# BreakBeforeInheritanceComma: false
|
||||
BreakBeforeTernaryOperators: false
|
||||
# BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: AfterColon
|
||||
# BreakStringLiterals: true
|
||||
ColumnLimit: 0
|
||||
# CommentPragmas: '^ IWYU pragma:'
|
||||
# CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
# DerivePointerAlignment: false
|
||||
# DisableFormat: false
|
||||
# ExperimentalAutoDetectBinPacking: false
|
||||
# FixNamespaceComments: true
|
||||
# ForEachMacros:
|
||||
# - foreach
|
||||
# - Q_FOREACH
|
||||
# - BOOST_FOREACH
|
||||
# IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '".*"'
|
||||
Priority: 1
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 2
|
||||
- Regex: '^<.*'
|
||||
Priority: 3
|
||||
# IncludeIsMainRegex: '(Test)?$'
|
||||
IndentCaseLabels: true
|
||||
# IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
# IndentWrappedFunctionNames: false
|
||||
# JavaScriptQuotes: Leave
|
||||
# JavaScriptWrapImports: true
|
||||
# KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
# MacroBlockBegin: ''
|
||||
# MacroBlockEnd: ''
|
||||
# MaxEmptyLinesToKeep: 1
|
||||
# NamespaceIndentation: None
|
||||
# PenaltyBreakAssignment: 2
|
||||
# PenaltyBreakBeforeFirstCallParameter: 19
|
||||
# PenaltyBreakComment: 300
|
||||
# PenaltyBreakFirstLessLess: 120
|
||||
# PenaltyBreakString: 1000
|
||||
# PenaltyExcessCharacter: 1000000
|
||||
# PenaltyReturnTypeOnItsOwnLine: 60
|
||||
# PointerAlignment: Right
|
||||
# RawStringFormats:
|
||||
# - Delimiter: pb
|
||||
# Language: TextProto
|
||||
# BasedOnStyle: google
|
||||
# ReflowComments: true
|
||||
# SortIncludes: true
|
||||
# SortUsingDeclarations: true
|
||||
# SpaceAfterCStyleCast: false
|
||||
# SpaceAfterTemplateKeyword: true
|
||||
# SpaceBeforeAssignmentOperators: true
|
||||
# SpaceBeforeParens: ControlStatements
|
||||
# SpaceInEmptyParentheses: false
|
||||
# SpacesBeforeTrailingComments: 1
|
||||
# SpacesInAngles: false
|
||||
# SpacesInContainerLiterals: true
|
||||
# SpacesInCStyleCastParentheses: false
|
||||
# SpacesInParentheses: false
|
||||
# SpacesInSquareBrackets: false
|
||||
TabWidth: 4
|
||||
UseTab: Always
|
||||
---
|
||||
### C++ specific config ###
|
||||
Language: Cpp
|
||||
Standard: Cpp03
|
||||
---
|
||||
### ObjC specific config ###
|
||||
Language: ObjC
|
||||
ObjCBlockIndentWidth: 4
|
||||
# ObjCSpaceAfterProperty: false
|
||||
# ObjCSpaceBeforeProtocolList: true
|
||||
---
|
||||
### Java specific config ###
|
||||
Language: Java
|
||||
# BreakAfterJavaFieldAnnotations: false
|
||||
...
|
||||
@ -4,14 +4,6 @@ root = true
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_style = tab
|
||||
insert_final_newline = true
|
||||
|
||||
[*.{cpp,hpp,c,h,mm}]
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.py]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[.travis.yml]
|
||||
indent_style = space
|
||||
|
||||
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -4,8 +4,6 @@
|
||||
drivers/* linguist-vendored
|
||||
|
||||
*.cpp eol=lf
|
||||
*.mm eol=lf
|
||||
*.h eol=lf
|
||||
*.py eol=lf
|
||||
*.hpp eol=lf
|
||||
*.xml eol=lf
|
||||
|
||||
65
.gitignore
vendored
65
.gitignore
vendored
@ -1,5 +1,29 @@
|
||||
# Godot auto generated files
|
||||
*.gen.*
|
||||
platform/server/logo.h
|
||||
platform/android/logo.h
|
||||
platform/bb10/logo.h
|
||||
platform/iphone/logo.h
|
||||
platform/javascript/logo.h
|
||||
platform/osx/logo.h
|
||||
platform/windows/logo.h
|
||||
platform/x11/logo.h
|
||||
drivers/gles2/shaders/*.h
|
||||
modules/register_module_types.cpp
|
||||
core/version.h
|
||||
core/method_bind.inc
|
||||
core/method_bind_ext.inc
|
||||
core/script_encryption_key.cpp
|
||||
core/global_defaults.cpp
|
||||
drivers/unix/os_unix_global_settings_path.cpp
|
||||
tools/editor/register_exporters.cpp
|
||||
tools/editor/doc_data_compressed.h
|
||||
tools/editor/certs_compressed.h
|
||||
tools/editor/editor_icons.cpp
|
||||
tools/editor/translations.h
|
||||
tools/editor/builtin_fonts.h
|
||||
.fscache
|
||||
make.bat
|
||||
log.txt
|
||||
|
||||
# Documentation generated by doxygen or from classes.xml
|
||||
doc/_build/
|
||||
@ -17,8 +41,6 @@ platform/android/java/build.gradle
|
||||
platform/android/java/AndroidManifest.xml
|
||||
platform/android/java/libs/*
|
||||
platform/android/java/assets
|
||||
platform/android/java/.idea/*
|
||||
platform/android/java/*.iml
|
||||
|
||||
# General c++ generated files
|
||||
*.lib
|
||||
@ -36,9 +58,6 @@ platform/android/java/*.iml
|
||||
.deps/*
|
||||
.dirstamp
|
||||
|
||||
# Gprof output
|
||||
gmon.out
|
||||
|
||||
# Vim temp files
|
||||
*.swo
|
||||
*.swp
|
||||
@ -46,24 +65,13 @@ gmon.out
|
||||
# QT project files
|
||||
*.config
|
||||
*.creator
|
||||
*.creator.*
|
||||
*.files
|
||||
*.includes
|
||||
|
||||
# Eclipse CDT files
|
||||
.cproject
|
||||
.settings/
|
||||
|
||||
# Geany/geany-plugins files
|
||||
*.geany
|
||||
.geanyprj
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
logs/
|
||||
|
||||
# for projects that use SCons for building: http://http://www.scons.org/
|
||||
.sconf_temp
|
||||
.sconsign.dblite
|
||||
*.pyc
|
||||
|
||||
@ -88,19 +96,11 @@ build/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
*.debug
|
||||
*.dSYM
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# Hints for improving IntelliSense, created together with VS project
|
||||
cpp.hint
|
||||
|
||||
# Visualizers for the VS debugger
|
||||
*.natvis
|
||||
|
||||
#NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
@ -143,9 +143,7 @@ ipch/
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.opendb
|
||||
*.VC.VC.opendb
|
||||
enc_temp_folder/
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
@ -245,9 +243,6 @@ node_modules/
|
||||
#Kdevelop project files
|
||||
*.kdev4
|
||||
|
||||
# xCode
|
||||
xcuserdata
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
@ -305,12 +300,6 @@ godot.creator.*
|
||||
projects/
|
||||
platform/windows/godot_res.res
|
||||
|
||||
# Visual Studio 2017 and Visual Studio Code workspace folder
|
||||
/.vs
|
||||
# Visual Studio Code folder (and files) that are created
|
||||
# when the C/C++ extension (https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) is used
|
||||
/.vscode
|
||||
|
||||
# Visual Studio Code workspace file
|
||||
*.code-workspace
|
||||
|
||||
# Scons progress indicator
|
||||
.scons_node_count
|
||||
|
||||
115
.mailmap
115
.mailmap
@ -1,115 +0,0 @@
|
||||
Alexander Holland <alexander.holland@live.de>
|
||||
Alexander Holland <alexander.holland@live.de> <alexander.holland@haw-hamburg.de>
|
||||
Alexander Holland <alexander.holland@live.de> <AlexHolly>
|
||||
Andrea Catania <info@andreacatania.com>
|
||||
Andreas Haas <liu.gam3@gmail.com>
|
||||
Andreas Haas <liu.gam3@gmail.com> <hinsbart@gmail.com>
|
||||
Andreas Haas <liu.gam3@gmail.com> <hinsbart@users.noreply.github.com>
|
||||
Andreas Haas <liu.gam3@gmail.com> <entenflugstuhl@gmail.com>
|
||||
Anish Bhobe <anishbhobe@hotmail.com>
|
||||
Anutrix <numaanzaheerahmed@yahoo.com>
|
||||
Aren Villanueva <arenvillanueva@yomogi-soft.com> <aren@displaysweet.com>
|
||||
Ariel Manzur <ariel@godotengine.org>
|
||||
Ariel Manzur <ariel@godotengine.org> <punto@godotengine.org>
|
||||
Ariel Manzur <ariel@godotengine.org> <ariel@okamstudio.com>
|
||||
Ariel Manzur <ariel@godotengine.org> <punto@Ariels-Mac-mini.local>
|
||||
Ariel Manzur <ariel@godotengine.org> <punto@Ariels-Mac-mini-2.local>
|
||||
Bastiaan Olij <mux213@gmail.com>
|
||||
Benjamin <mafortion.benjamin@gmail.com>
|
||||
Bernhard Liebl <Bernhard.Liebl@gmx.org> <poke1024@gmx.de>
|
||||
Bernhard Liebl <Bernhard.Liebl@gmx.org> <poke1024@gmx.org>
|
||||
Chaosus <chaosus89@gmail.com>
|
||||
Chris Bradfield <chris@kidscancode.org> <cb@scribe.net>
|
||||
Clay John <claynjohn@gmail.com>
|
||||
Clay John <claynjohn@gmail.com> <clayjohn@shaw.ca>
|
||||
Dana Olson <dana@shineuponthee.com> <adolson@gmail.com>
|
||||
Daniel J. Ramirez <djrmuv@gmail.com>
|
||||
Erik Selecký <35656626+rxlecky@users.noreply.github.com>
|
||||
Erik Selecký <35656626+rxlecky@users.noreply.github.com> <35656626+SeleckyErik@users.noreply.github.com>
|
||||
Fabian <supagu@gmail.com>
|
||||
Ferenc Arn <tagcup@yahoo.com>
|
||||
Ferenc Arn <tagcup@yahoo.com> <tagcup@users.noreply.github.com>
|
||||
Fredia Huya-Kouadio <fhuyakou@gmail.com>
|
||||
Fredia Huya-Kouadio <fhuyakou@gmail.com> <fhuya@google.com>
|
||||
Geequlim <geequlim@gmail.com>
|
||||
Gilles Roudiere <gilles.roudiere@gmail.com>
|
||||
Gilles Roudiere <gilles.roudiere@gmail.com> <gilles.roudiere@laas.fr>
|
||||
Gordon MacPherson <gordon@gordonite.tech>
|
||||
Guilherme Felipe <guilhermefelipecgs@gmail.com>
|
||||
Hanif Bin Ariffin <hanif.ariffin.4326@gmail.com>
|
||||
Hein-Pieter van Braam-Stewart <hp@tmm.cx>
|
||||
Hubert Jarosz <marqin.pl@gmail.com>
|
||||
Hubert Jarosz <marqin.pl@gmail.com> <marqin.pl+git@gmail.com>
|
||||
Hugo Locurcio <hugo.locurcio@hugo.pro> <hugo.l@openmailbox.org>
|
||||
Hugo Locurcio <hugo.locurcio@hugo.pro> <Calinou@users.noreply.github.com>
|
||||
Hugo Locurcio <hugo.locurcio@hugo.pro> Calinou <calinou@opmbx.org>
|
||||
Ian Bishop <ianb96@gmail.com>
|
||||
Ignacio Etcheverry <ignalfonsore@gmail.com>
|
||||
Ignacio Etcheverry <ignalfonsore@gmail.com> <neikeq@users.noreply.github.com>
|
||||
Ilaria Cislaghi <cislaghi.ilaria@gmail.com>
|
||||
Ilaria Cislaghi <cislaghi.ilaria@gmail.com> <ilaria.cislaghi@simedis.com>
|
||||
Indah Sylvia <ISylvox@yahoo.com>
|
||||
J08nY <johny@neuromancer.sk> <jancar.jj@gmail.com>
|
||||
J08nY <johny@neuromancer.sk> <J08nY@users.noreply.github.com>
|
||||
Jakub Grzesik <kubecz3k@gmail.com>
|
||||
Jérôme Gully <jerome.gully0@gmail.com>
|
||||
JFonS <joan.fonssanchez@gmail.com>
|
||||
Juan Linietsky <reduzio@gmail.com>
|
||||
Juan Linietsky <reduzio@gmail.com> <juan@godotengine.org>
|
||||
Juan Linietsky <reduzio@gmail.com> <juan@okamstudio.com>
|
||||
Juan Linietsky <reduzio@gmail.com> <reduz@Juans-MBP.fibertel.com.ar>
|
||||
Juan Linietsky <reduzio@gmail.com> <red@kyoko>
|
||||
Julian Murgia <the.straton@gmail.com>
|
||||
Kanabenki <lucien.menassol@gmail.com> <18357657+Kanabenki@users.noreply.github.com>
|
||||
Kelly Thomas <kelly.thomas@hotmail.com.au>
|
||||
K. S. Ernest (iFire) Lee <ernest.lee@chibifire.com>
|
||||
Leon Krause <lk@leonkrause.com> <eska@eska.me>
|
||||
Leon Krause <lk@leonkrause.com> <eska014@users.noreply.github.com>
|
||||
Manuel Strey <manuel.strey@gmx.de>
|
||||
Marcelo Fernandez <marcelofg55@gmail.com>
|
||||
Marcin Zawiejski <dragmz@gmail.com>
|
||||
Mariano Javier Suligoy <marianognu.easyrpg@gmail.com>
|
||||
Mario Schlack <m4r10.5ch14ck@gmail.com>
|
||||
marxin <mliska@suse.cz>
|
||||
marynate <mary.w.nate@gmail.com> <marynate@github.com>
|
||||
Max Hilbrunner <m.hilbrunner@gmail.com>
|
||||
Max Hilbrunner <m.hilbrunner@gmail.com> <mhilbrunner@users.noreply.github.com>
|
||||
Michael Alexsander <michaelalexsander@protonmail.com>
|
||||
Nathan Lovato <nathan@gdquest.com>
|
||||
Nathan Warden <nathan@nathanwarden.com> <nathanwardenlee@icloud.com>
|
||||
Nils ANDRÉ-CHANG <nils@nilsand.re>
|
||||
Nils ANDRÉ-CHANG <nils@nilsand.re> <nils.andre.chang@gmail.com>
|
||||
Nuno Donato <nunodonato@gmail.com> <n.donato@estrelasustentavel.pt>
|
||||
Pedro J. Estébanez <pedrojrulez@gmail.com> <RandomShaper@users.noreply.github.com>
|
||||
Paul Batty <p_batty@hotmail.co.uk>
|
||||
Paul Batty <p_batty@hotmail.co.uk> <Paulb23@users.noreply.github.com>
|
||||
Pawel Kowal <pkowal1982@gmail.com> <pawel.kowal@javart.eu>
|
||||
Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
|
||||
Pieter-Jan Briers <pieterjan.briers+git@gmail.com> <pieterjan.briers@gmail.com>
|
||||
Poommetee Ketson <poommetee@protonmail.com>
|
||||
Przemysław Gołąb (n-pigeon) <golab.przemyslaw@gmail.com>
|
||||
Ralf Hölzemer <r.hoelzemer@posteo.de> <rollenrolm@posteo.de>
|
||||
Ralf Hölzemer <r.hoelzemer@posteo.de> <rollenrolm@users.noreply.github.com>
|
||||
Ramesh Ravone <ramesh.maran443@gmail.com>
|
||||
RaphaelHunter <raphael10241024@gmail.com>
|
||||
RaphaelHunter <raphael10241024@gmail.com> <Raphael10241024@gmail.com>
|
||||
RaphaelHunter <raphael10241024@gmail.com> <raphael20141024@gmail.com>
|
||||
Rémi Verschelde <rverschelde@gmail.com> <remi@verschelde.fr>
|
||||
Rhody Lugo <rhodylugo@gmail.com> <rhodylugo@me.com>
|
||||
Robin Hübner <profan@prfn.se> <robinhubner@gmail.com>
|
||||
romulox_x <romulox_x@yahoo.com>
|
||||
Ruslan Mustakov <r.mustakov@gmail.com> <ruslan.mustakov@xored.com>
|
||||
Saracen <SaracenOne@gmail.com>
|
||||
sheepandshepherd <sheepandshepherd@hotmail.com> <sheepandshepherd@users.noreply.github.com>
|
||||
Swarnim Arun <swarnimarun11@gmail.com>
|
||||
Theo Hallenius <redsymbzone@hotmail.com>
|
||||
Thomas Herzog <therzog@mail.de>
|
||||
Thomas Herzog <therzog@mail.de> <thomas.herzog@mail.com>
|
||||
Thomas Herzog <therzog@mail.de> <thomas.herzog@simedis.com>
|
||||
Twarit <wtwarit@gmail.com>
|
||||
V.VamsiKrishna <vk@bsb.in> <vamsikrishna.v@gmail.com>
|
||||
Wilhem Barbier <nounoursheureux@openmailbox.org> <wilhem.b@free.fr>
|
||||
Wilhem Barbier <nounoursheureux@openmailbox.org> <schtroumps31@gmail.com>
|
||||
Will Nations <willnationsdev@gmail.com>
|
||||
yg2f <yoann@terminajones.com>
|
||||
Zher Huei Lee <lee.zh.92@gmail.com>
|
||||
157
.travis.yml
157
.travis.yml
@ -1,109 +1,78 @@
|
||||
language: cpp
|
||||
|
||||
# OS config, depends on actual 'os' in build matrix
|
||||
dist: trusty
|
||||
sudo: false
|
||||
|
||||
env:
|
||||
global:
|
||||
- SCONS_CACHE=$HOME/.scons_cache/$TRAVIS_BRANCH
|
||||
- SCONS_CACHE_LIMIT=1024
|
||||
- OPTIONS="verbose=yes progress=no gdnative_wrapper=yes"
|
||||
- secure: "QLFRizqry/Y5pnEZvDlQz5S3YydQ+600u4rHEzFgUTd0heYeQaETXAQeMzp0ymuG1BkdRAl5YJoLVJgAzjwI9hrvugvoUlh2//SfpqZCHN/Q1fYbtGgNTn01R3VFEpcfYQL93I2EjrxVm0WTM4PwCvMO+hU0aWTRDvCt1Lty0kMR+RMDQOO/woqunoXh5wvFNxTJJkAmuLe0v962DJYOIwJAnqMLR0aFYjmeQJ20bc/2X5oLt+WuJDuf/lGj6WSlD6z/o/kL3YxHoUyw4A/HAZ2IX0IfNHKuay60ESWzl/NlobnePiPwHAE2pdDVu//q16fanb9VeYnBYRFse49TpFRb86Lo+Qz8nKDJqpQEIY0YKNCFqekrubqTM++Lj6QvGpykQZNxUhybmELcEsRG4PS0UMvCpebdnJD46nNB+DtO2Lgb4xXDLQwpq19z1wizq/XDQ5hz61TIIx8+i8TsgdSQKCTeWovd4HcD4CVjAD5XTLGgyRmI/zC2d+lTnKo6W9diLq/bX/Goq2QPeaTPABqv817IaJka2JyugQ7Qal/+gNTjYRRsimRCL9B2tVh+Uh8rWhTFhQL4QbP5P65HF+p8qojUzqtAhPMbZ8mxUtNukUI3liVgPgiMss96sG0nTVglFgkkAkEjIMFnqMSKnTfG812K4jIhp2jCO2Q3NeI="
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $SCONS_CACHE
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
env:
|
||||
- GODOT_TARGET=iphone
|
||||
- GODOT_TARGET=osx
|
||||
- GODOT_TARGET=x11
|
||||
- GODOT_TARGET=android
|
||||
- GODOT_TARGET=windows
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- env: STATIC_CHECKS=yes
|
||||
os: linux
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-trusty-6.0
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang-format-6.0
|
||||
- libstdc++6 # >= 4.9 needed for clang-format-6.0
|
||||
exclude:
|
||||
- os: linux
|
||||
env: GODOT_TARGET=iphone
|
||||
- os: linux
|
||||
env: GODOT_TARGET=osx
|
||||
- os: linux
|
||||
env: GODOT_TARGET=android
|
||||
- os: osx
|
||||
env: GODOT_TARGET=x11
|
||||
- os: osx
|
||||
env: GODOT_TARGET=windows
|
||||
- compiler: gcc
|
||||
env: GODOT_TARGET=iphone
|
||||
- compiler: gcc
|
||||
env: GODOT_TARGET=osx
|
||||
- compiler: clang
|
||||
env: GODOT_TARGET=android
|
||||
- compiler: clang
|
||||
env: GODOT_TARGET=windows
|
||||
- compiler: clang
|
||||
env: GODOT_TARGET=x11
|
||||
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "godotengine/godot"
|
||||
description: "Godot Engine Coverity scans"
|
||||
notification_email: coverity@godotengine.org
|
||||
build_command_prepend: ""
|
||||
build_command: "scons p=x11 -j2 $OPTIONS"
|
||||
branch_pattern: coverity_scan
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- build-essential
|
||||
- scons
|
||||
- pkg-config
|
||||
- libx11-dev
|
||||
- libxcursor-dev
|
||||
- libasound2-dev
|
||||
- libfreetype6-dev
|
||||
- libgl1-mesa-dev
|
||||
- libglu1-mesa-dev
|
||||
- libssl-dev
|
||||
- libxinerama-dev
|
||||
- libxrandr-dev
|
||||
|
||||
- env: GODOT_TARGET=x11 TOOLS=yes CACHE_NAME=${GODOT_TARGET}-tools-mono-gcc EXTRA_ARGS="module_mono_enabled=yes mono_glue=no"
|
||||
os: linux
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- mono
|
||||
packages:
|
||||
- &linux_deps [libasound2-dev, libfreetype6-dev, libgl1-mesa-dev, libglu1-mesa-dev, libx11-dev, libxcursor-dev, libxi-dev, libxinerama-dev, libxrandr-dev]
|
||||
- &linux_mono_deps [mono-devel, msbuild]
|
||||
# For cross-compiling to Windows.
|
||||
- binutils-mingw-w64-i686
|
||||
- binutils-mingw-w64-x86-64
|
||||
- gcc-mingw-w64-i686
|
||||
- gcc-mingw-w64-x86-64
|
||||
- g++-mingw-w64-i686
|
||||
- g++-mingw-w64-x86-64
|
||||
- mingw-w64
|
||||
|
||||
- env: GODOT_TARGET=x11 TOOLS=no CACHE_NAME=${GODOT_TARGET}-clang
|
||||
os: linux
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- *linux_deps
|
||||
|
||||
- env: GODOT_TARGET=android TOOLS=no CACHE_NAME=${GODOT_TARGET}-clang
|
||||
os: linux
|
||||
compiler: clang
|
||||
|
||||
- env: GODOT_TARGET=osx TOOLS=yes CACHE_NAME=${GODOT_TARGET}-tools-clang
|
||||
os: osx
|
||||
osx_image: xcode9.3
|
||||
compiler: clang
|
||||
|
||||
- env: GODOT_TARGET=iphone TOOLS=no CACHE_NAME=${GODOT_TARGET}-clang
|
||||
os: osx
|
||||
osx_image: xcode9.3
|
||||
compiler: clang
|
||||
|
||||
- env: GODOT_TARGET=server TOOLS=yes CACHE_NAME=${GODOT_TARGET}-tools-gcc
|
||||
os: linux
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- *linux_deps
|
||||
|
||||
before_install:
|
||||
- if [ "$STATIC_CHECKS" = "yes" ]; then
|
||||
unset SCONS_CACHE;
|
||||
fi
|
||||
|
||||
install:
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$GODOT_TARGET" = "android" ]; then
|
||||
misc/travis/android-tools-linux.sh;
|
||||
fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
misc/travis/scons-local-osx.sh;
|
||||
fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$GODOT_TARGET" = "android" ]; then
|
||||
misc/travis/android-tools-osx.sh;
|
||||
fi
|
||||
|
||||
before_script:
|
||||
- if [ "$GODOT_TARGET" = "android" ]; then
|
||||
export ANDROID_HOME=$TRAVIS_BUILD_DIR/godot-dev/build-tools/android-sdk;
|
||||
export ANDROID_NDK_ROOT=$TRAVIS_BUILD_DIR/godot-dev/build-tools/android-ndk;
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; brew install scons; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$GODOT_TARGET" = "android" ]; then
|
||||
brew update; travis_wait 20 brew install -v android-sdk;
|
||||
travis_wait 20 brew install -v android-ndk | grep -v "inflating:" | grep -v "creating:";
|
||||
export ANDROID_HOME=/usr/local/opt/android-sdk; export ANDROID_NDK_ROOT=/usr/local/opt/android-ndk;
|
||||
fi
|
||||
|
||||
script:
|
||||
- if [ "$STATIC_CHECKS" = "yes" ]; then
|
||||
sh ./misc/travis/clang-format.sh;
|
||||
else
|
||||
scons -j2 CC=$CC CXX=$CXX platform=$GODOT_TARGET TOOLS=$TOOLS $EXTRA_ARGS $OPTIONS;
|
||||
fi
|
||||
- scons platform=$GODOT_TARGET CXX=$CXX openssl=builtin
|
||||
|
||||
177
AUTHORS.md
177
AUTHORS.md
@ -1,177 +0,0 @@
|
||||
# Godot Engine authors
|
||||
|
||||
Godot Engine is developed by a community of voluntary contributors who
|
||||
contribute code, bug reports, documentation, artwork, support, etc.
|
||||
|
||||
It is impossible to list them all; nevertheless, this file aims at listing
|
||||
the developers who contributed significant patches to this MIT licensed
|
||||
source code. "Significant" is arbitrarily decided, but should be fair :)
|
||||
|
||||
GitHub usernames are indicated in parentheses, or as sole entry when no other
|
||||
name is available.
|
||||
|
||||
## Project Founders
|
||||
|
||||
Juan Linietsky (reduz)
|
||||
Ariel Manzur (punto-)
|
||||
|
||||
## Lead Developer
|
||||
|
||||
Juan Linietsky (reduz)
|
||||
|
||||
## Project Manager
|
||||
|
||||
Rémi Verschelde (akien-mga)
|
||||
|
||||
## Developers
|
||||
|
||||
(in alphabetical order, with over 10 commits excluding merges)
|
||||
|
||||
Aaron Franke (aaronfranke)
|
||||
Alexander Holland (AlexHolly)
|
||||
Alexey Khoroshavin (allkhor)
|
||||
Alket Rexhepi (alketii)
|
||||
Andrea Catania (AndreaCatania)
|
||||
Andreas Haas (Hinsbart)
|
||||
Andrii Doroshenko (Xrayez)
|
||||
Andy Moss (MillionOstrich)
|
||||
Anish Bhobe (KidRigger)
|
||||
Anton Yabchinskiy (a12n)
|
||||
Anutrix
|
||||
Aren Villanueva (kurikaesu)
|
||||
Ariel Manzur (punto-)
|
||||
Bastiaan Olij (BastiaanOlij)
|
||||
Ben Brookshire (sheepandshepherd)
|
||||
Benjamin Larsson (Nallebeorn)
|
||||
Bernard Liebl (poke1024)
|
||||
Błażej Szczygieł (zaps166)
|
||||
Bojidar Marinov (bojidar-bg)
|
||||
Bruno Lourenço (MadEqua)
|
||||
bruvzg
|
||||
Cameron Reikes (creikey)
|
||||
Camille Mohr-Daurat (pouleyKetchoupp)
|
||||
Carl Olsson (not-surt)
|
||||
Carter Anderson (cart)
|
||||
Chris Bradfield (cbscribe)
|
||||
Clay John (clayjohn)
|
||||
Dana Olson (adolson)
|
||||
Daniel J. Ramirez (djrm)
|
||||
Daniel Rakos (aqnuep)
|
||||
dankan1890
|
||||
David Sichma (DavidSichma)
|
||||
Dharkael (lupoDharkael)
|
||||
Dmitry Koteroff (Krakean)
|
||||
DualMatrix
|
||||
Emmanuel Barroga (codecustard)
|
||||
Emmanuel Leblond (touilleMan)
|
||||
Eoin O'Neill (Eoin-ONeill-Yokai)
|
||||
Eric Lasota (elasota)
|
||||
Eric Rybicki (ericrybick)
|
||||
Erik Selecký (rxlecky)
|
||||
est31
|
||||
Fabian Mathews (supagu)
|
||||
Fabio Alessandrelli (Faless)
|
||||
Ferenc Arn (tagcup)
|
||||
Franklin Sobrinho (TheHX)
|
||||
Fredia Huya-Kouadio (m4gr3d)
|
||||
Geequlim
|
||||
George Marques (vnen)
|
||||
Gerrit Großkopf (Grosskopf)
|
||||
Gilles Roudiere (groud)
|
||||
Gordon MacPherson (RevoluPowered)
|
||||
Guilherme Felipe de C. G. da Silva (guilhermefelipecgs)
|
||||
Hanif Bin Ariffin (hbina)
|
||||
Haoyu Qiu (timothyqiu)
|
||||
Hein-Pieter van Braam-Stewart (hpvb)
|
||||
Hiroshi Ogawa (hi-ogawa)
|
||||
homer666
|
||||
Hubert Jarosz (Marqin)
|
||||
Hugo Locurcio (Calinou)
|
||||
Ian Bishop (ianb96)
|
||||
Ibrahn Sahir (ibrahn)
|
||||
Ignacio Etcheverry (neikeq)
|
||||
Ilaria Cislaghi (QbieShay)
|
||||
Indah Sylvia (ISylvox)
|
||||
J08nY
|
||||
Jakub Grzesik (kubecz3k)
|
||||
Jérôme Gully (Nutriz)
|
||||
Joan Fons Sanchez (JFonS)
|
||||
Johan Manuel (29jm)
|
||||
Joshua Grams (JoshuaGrams)
|
||||
Juan Linietsky (reduz)
|
||||
Julian Murgia (StraToN)
|
||||
Justo Delgado (mrcdk)
|
||||
Kelly Thomas (KellyThomas)
|
||||
Kostadin Damyanov (Max-Might)
|
||||
K. S. Ernest (iFire) Lee (fire)
|
||||
Leon Krause (eska014)
|
||||
Lucien Menassol (Kanabenki)
|
||||
m4nu3lf
|
||||
Marcel Admiraal (madmiraal)
|
||||
Marcelo Fernandez (marcelofg55)
|
||||
Marc Gilleron (Zylann)
|
||||
Marcin Zawiejski (dragmz)
|
||||
Mariano Javier Suligoy (MarianoGnu)
|
||||
Mario Schlack (hurikhan)
|
||||
Martin Capitanio (capnm)
|
||||
Martin Liška (marxin)
|
||||
Martin Sjursen (binbitten)
|
||||
marynate
|
||||
Masoud BH (masoudbh3)
|
||||
Matthias Hölzl (hoelzl)
|
||||
Max Hilbrunner (mhilbrunner)
|
||||
merumelu
|
||||
Michael Alexsander (YeldhamDev)
|
||||
MichiRecRoom (LikeLakers2)
|
||||
mrezai
|
||||
muiroc
|
||||
Nathan Warden (NathanWarden)
|
||||
Nils André-Chang (NilsIrl)
|
||||
Nuno Donato (nunodonato)
|
||||
Ovnuniarchos
|
||||
Pascal Richter (ShyRed)
|
||||
Patrick (firefly2442)
|
||||
Paul Batty (Paulb23)
|
||||
Paul Joannon (paulloz)
|
||||
Paul Trojahn (ptrojahn)
|
||||
Pawel Kowal (pkowal1982)
|
||||
Pedro J. Estébanez (RandomShaper)
|
||||
Pieter-Jan Briers (PJB3005)
|
||||
Poommetee Ketson (Noshyaar)
|
||||
Przemysław Gołąb (n-pigeon)
|
||||
Rafał Mikrut (qarmin)
|
||||
Ralf Hölzemer (rollenrolm)
|
||||
Ramesh Ravone (RameshRavone)
|
||||
raphael10241024
|
||||
Ray Koopa (RayKoopa)
|
||||
Rémi Verschelde (akien-mga)
|
||||
Rhody Lugo (rraallvv)
|
||||
Roberto F. Arroyo (robfram)
|
||||
Robin Hübner (profan)
|
||||
romulox-x
|
||||
Ruslan Mustakov (endragor)
|
||||
Saniko (sanikoyes)
|
||||
santouits
|
||||
SaracenOne
|
||||
sersoong
|
||||
Shiqing (kawa-yoiko)
|
||||
Simon Wenner (swenner)
|
||||
Swarnim Arun (minraws)
|
||||
Theo Hallenius (TheoXD)
|
||||
Thomas Herzog (karroffel)
|
||||
Timo Schwarzer (timoschwarzer)
|
||||
Timo (toger5)
|
||||
Tomasz Chabora (KoBeWi)
|
||||
Twarit Waikar (IronicallySerious)
|
||||
Vinzenz Feenstra (vinzenz)
|
||||
박한얼 (volzhs)
|
||||
V. Vamsi Krishna (vkbsb)
|
||||
Wilhem Barbier (nounoursheureux)
|
||||
Will Nations (willnationsdev)
|
||||
Wilson E. Alvarez (Rubonnek)
|
||||
Xavier Cho (mysticfall)
|
||||
yg2f (SuperUserNameMan)
|
||||
Yuri Roubinsky (Chaosus)
|
||||
Zak Stam (zaksnet)
|
||||
Zher Huei Lee (leezh)
|
||||
ZuBsPaCe
|
||||
286
CHANGELOG.md
286
CHANGELOG.md
@ -1,286 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
## [3.0.6] - 2018-07-29
|
||||
|
||||
### Added
|
||||
|
||||
- Upgrade bundled OpenSSL to 1.0.2o.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Security issue relating to deserializing Variants.
|
||||
- Several editor crashes.
|
||||
- GLTF import fixes.
|
||||
- Windows: Fix touch/pen input.
|
||||
- Mono: --build-solutions now forces editor mode.
|
||||
- Mono: Several bugfixes.
|
||||
- Headless: Fix scene imports.
|
||||
|
||||
## [3.0.5] - 2018-07-08
|
||||
|
||||
### Added
|
||||
|
||||
- 'android_add_asset_dir('...') method to Android module gradle build config.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Android exporter no longer writes unnecessary permissions to the exported APK.
|
||||
- Segfault when quitting the editor.
|
||||
- Debugger 'focus stealing' now works more reliably.
|
||||
- Subresources are now always saved when saving a scene.
|
||||
- WebAssembly: Supply proper CORS heards.
|
||||
- Mono: Annotated signal loading in exported projects.
|
||||
- Mono: Serveral fixes.
|
||||
|
||||
## [3.0.4] - 2018-06-23
|
||||
|
||||
### Added
|
||||
|
||||
- Fix for Bullet's heightmap collider.
|
||||
- Several documentation fixes.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Threading problem causing asset library to crash on low threadcount systems.
|
||||
|
||||
## [3.0.3] - 2018-06-13
|
||||
|
||||
### Added
|
||||
|
||||
- C# projects can now be exported for Windows, Linux, and MacOS targets.
|
||||
- Universal translation of touch to mouse.
|
||||
- Dynamic fonts can now have a hinting mode set.
|
||||
- print_tree_pretty() was added allowing a graphical view of the scene tree.
|
||||
- Restore purchases feature for iOS.
|
||||
- AudioStreamPlayer, AudioStreamPlayer2D, and AudioStreamPlayer3D now have a pitch scale property.
|
||||
- Show origin and Show viewport setting in 2D editor.
|
||||
- You can now set Godot windows as 'always on top'.
|
||||
- --print-fps options to print FPS to stdout.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Mono: Signal parameters no longer crash the engine.
|
||||
- Asset library thread usage, this makes the asset library more responsive.
|
||||
- Several GLTF import fixes.
|
||||
- Several memory leaks.
|
||||
- iPhone X support.
|
||||
- Several fixes to audio drivers (WASAPI and PulseAudio).
|
||||
- Several crashes.
|
||||
- Export PCK/ZIP now works again.
|
||||
|
||||
## [3.0.2] - 2018-03-03
|
||||
|
||||
### Added
|
||||
|
||||
- Mono: We now display stack traces for inner exceptions.
|
||||
- Mono: Bundle mscorlib.dll with Godot to improve portability.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Running a scene from a project with a main scene now works again (regression in 3.0.1).
|
||||
- Correct line spacing in RichTextLabel (regression in 3.0.1).
|
||||
- TextureProgress now correctly displays when progress > 62 (regression in 3.0.1).
|
||||
- The editor no longer complains about using an enum from an autoloaded resource (regression in 3.0.1).
|
||||
- Pressing Escape no longer closes unexpected subwindows (regression in 3.0.1).
|
||||
- Fix spelling of `apply_torque_impulse()` and deprecate the misspelled method.
|
||||
- Gizmos are now properly hidden on scene load if the object they control is hidden.
|
||||
- Remove spurious errors when using a PanoramaSky without textures.
|
||||
- Show tooltips in the editor when physics object picking is disabled.
|
||||
- Fix a serialization bug that could cause tscn files to grow very large.
|
||||
- Do not show the project manager unless no project was found at all.
|
||||
- The animation editor time offset indicator no longer 'walks' when resizing the editor.
|
||||
- Allow creation of an in-tscn file GDScript function even if the filename suggested already exists.
|
||||
- Mono: Godot no longer crashes when opening a project created with an older release.
|
||||
- Mono: Fix builds of tools=no builds.
|
||||
- Mono: Fix transformation regression since 3.0.1
|
||||
- Android: We now require GLESv3 support in the manifest.
|
||||
- Android: Fix intermittent audio driver crash.
|
||||
|
||||
## [3.0.1] - 2018-02-25
|
||||
|
||||
### Added
|
||||
|
||||
- The 'server' platform is back as it was in Godot 2.1.
|
||||
- It is now again possible to run a headless Godot on Linux.
|
||||
- New CLI options
|
||||
- --build-solutions: build C# solutions without starting the editor.
|
||||
- --quit: quit the engine after the first main loop iteration.
|
||||
- It is now possible to scale an .obj mesh when importing.
|
||||
- Type icons can now be enabled in the editor again.
|
||||
- New GLSL built-in functions in the shader language
|
||||
- radians
|
||||
- degrees
|
||||
- asinh
|
||||
- acosh
|
||||
- atanh
|
||||
- exp2
|
||||
- log2
|
||||
- roundEven
|
||||
- New GDScript features
|
||||
- `OS.center_window()`.
|
||||
- `StreamPeerTCP.set_no_delay()`.
|
||||
- `EditorPlugin.remove_control_from_container()`.
|
||||
- A button has been added to the debugger to copy the error messages.
|
||||
- The Ctrl toggles snapping in the 3D viewport.
|
||||
- Support has been added for a new .escn, for use with the new Blender exporter.
|
||||
- CA certificates have been updated to the latest Mozilla bundle.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Copy/pasting from the editor on X11 will now work more reliably.
|
||||
- The lightmap baker will now use all available cores on Windows.
|
||||
- Fixed missing text in some FileDialog buttons.
|
||||
- Fixes to HTTP requests on the HTML5 platform.
|
||||
- Many, many fixes and improvements to C# support (including a [Signal] attribute).
|
||||
- Static linking of `libgcc_s` as well as `libstdc++` for better Linux binary portability.
|
||||
- Fix broken APK expansion on Android.
|
||||
- Several crashes in the editor have been fixed.
|
||||
- Many documentation fixes.
|
||||
- Several hiDPI fixes.
|
||||
|
||||
## Changed
|
||||
|
||||
- Bullet physics now correctly calculates effective gravity on KinematicBodies.
|
||||
- Setting the color `v` member now correctly sets the `s` member.
|
||||
- RichTextLabels now correctly determine the baseline for all fonts.
|
||||
- SpinBoxes now correctly calculate their initial size.
|
||||
- OGG streams now correctly signal the end of playback.
|
||||
|
||||
## [3.0] - 2018-01-29
|
||||
|
||||
### Added
|
||||
|
||||
- Physically-based renderer using OpenGL ES 3.0.
|
||||
- Uses the Disney PBR model, with clearcoat, sheen and anisotropy parameters available.
|
||||
- Uses a forward renderer, supporting multi-sample anti-aliasing (MSAA).
|
||||
- Parallax occlusion mapping.
|
||||
- Reflection probes.
|
||||
- Screen-space reflections.
|
||||
- Real-time global illumination using voxel cone tracing (GIProbe).
|
||||
- Proximity fade and distance fade (useful for creating soft particles and various effects).
|
||||
- [Lightmapper](https://godotengine.org/article/introducing-new-last-minute-lightmapper) for lower-end desktop and mobile platforms, as an alternative to GIProbe.
|
||||
- New SpatialMaterial resource, replacing FixedMaterial.
|
||||
- Multiple passes can now be specified (with an optional "grow" property), allowing for effects such as cel shading.
|
||||
- Brand new 3D post-processing system.
|
||||
- Depth of field (near and far).
|
||||
- Fog, supporting light transmittance, sun-oriented fog, depth fog and height fog.
|
||||
- Tonemapping and Auto-exposure.
|
||||
- Screen-space ambient occlusion.
|
||||
- Multi-stage glow and bloom, supporting optional bicubic upscaling for better quality.
|
||||
- Color grading and various adjustments.
|
||||
- Rewritten audio engine from scratch.
|
||||
- Supports audio routing with arbitrary number of channels, including Area-based audio redirection ([video](https://youtu.be/K2XOBaJ5OQ0)).
|
||||
- More than a dozen of audio effects included.
|
||||
- Rewritten 3D physics using [Bullet](http://bulletphysics.org/).
|
||||
- UDP-based high-level networking API using [ENet](http://enet.bespin.org/).
|
||||
- IPv6 support for all of the engine's networking APIs.
|
||||
- Visual scripting.
|
||||
- Rewritten import system.
|
||||
- Assets are now referenced with their source files, then imported in a transparent manner by the engine.
|
||||
- Imported assets are now cached in a `.import` directory, making distribution and versioning easier.
|
||||
- Support for ETC2 compression.
|
||||
- Support for uncompressed Targa (.tga) textures, allowing for faster importing.
|
||||
- Rewritten export system.
|
||||
- GPU-based texture compression can now be tweaked per-target.
|
||||
- Support for exporting resource packs to build DLC / content addons.
|
||||
- Improved GDScript.
|
||||
- Pattern matching using the `match` keyword.
|
||||
- `$` shorthand for `get_node()`.
|
||||
- Setters and getters for node properties.
|
||||
- Underscores in number literals are now allowed for improved readability (for example,`1_000_000`).
|
||||
- Improved performance (+20% to +40%, based on various benchmarks).
|
||||
- [Feature tags](http://docs.godotengine.org/en/latest/learning/workflow/export/feature_tags.html) in the Project Settings, for custom per-platform settings.
|
||||
- Full support for the [glTF 2.0](https://www.khronos.org/gltf/) 3D interchange format.
|
||||
- Freelook and fly navigation to the 3D editor.
|
||||
- Built-in editor logging (logging standard output to a file), disabled by default.
|
||||
- Improved, more intuitive file chooser in the editor.
|
||||
- Smoothed out 3D editor zooming, panning and movement.
|
||||
- Toggleable rendering information box in the 3D editor viewport.
|
||||
- FPS display can also be enabled in the editor viewport.
|
||||
- Ability to render the 3D editor viewport at half resolution to achieve better performance.
|
||||
- GDNative for binding languages like C++ to Godot as dynamic libraries.
|
||||
- Community bindings for [D](https://github.com/GodotNativeTools/godot-d), [Nim](https://github.com/pragmagic/godot-nim) and [Python](https://github.com/touilleMan/godot-python) are available.
|
||||
- Editor settings and export templates are now versioned, making it easier to use several Godot versions on the same system.
|
||||
- Optional soft shadows for 2D rendering.
|
||||
- HDR sky support.
|
||||
- Ability to toggle V-Sync while the project is running.
|
||||
- Panorama sky support (sphere maps).
|
||||
- Support for WebM videos (VP8/VP9 with Vorbis/Opus).
|
||||
- Exporting to HTML5 using WebAssembly.
|
||||
- C# support using Mono.
|
||||
- The Mono module is disabled by default, and needs to be compiled in at build-time.
|
||||
- The latest Mono version (5.4) can be used, fully supporting C# 7.0.
|
||||
- Support for rasterizing SVG to images on-the-fly, using the nanosvg library.
|
||||
- Editor icons are now in SVG format, making them better-looking at non-integer scales.
|
||||
- Due to the library used, only simpler SVGs are well-supported, more complex SVGs may not render correctly.
|
||||
- Support for oversampling DynamicFonts, keeping them sharp when scaled to high resolutions.
|
||||
- Improved StyleBoxFlat.
|
||||
- Border widths can now be set per-corner.
|
||||
- Support for anti-aliased rounded and beveled corners.
|
||||
- Support for soft drop shadows.
|
||||
- VeryLoDPI (75%) and MiDPI (150%) scaling modes for the editor.
|
||||
- Improved internationalization support for projects.
|
||||
- Language changes are now effective without reloading the current scene.
|
||||
- Implemented missing features in the HTML5 platform.
|
||||
- Cursor style changes.
|
||||
- Cursor capturing and hiding.
|
||||
- Improved styling and presentation of HTML5 exports.
|
||||
- A spinner is now displayed during loading.
|
||||
- Rewritten the 2D and 3D particle systems.
|
||||
- Particles are now GPU-based, allowing their use in much higher quantities than before.
|
||||
- Meshes can now be used as particles.
|
||||
- Particles can now be emitted from a mesh's shape.
|
||||
- Properties can now be modified over time using an editable curve.
|
||||
- Custom particle shaders can now be used.
|
||||
- New editor theme, with customizable base color, highlight color and contrast.
|
||||
- A light editor theme option is now available, with icons suited to light backgrounds.
|
||||
- Alternative dark gray and Arc colors are available out of the box.
|
||||
- New adaptive text editor theme, adjusting automatically based on the editor colors.
|
||||
- Support for macOS trackpad gestures in the editor.
|
||||
- Exporting to macOS now creates a `.dmg` disk image if exporting from an editor running on macOS.
|
||||
- Signing the macOS export now is possible if running macOS (requires a valid code signing certificate).
|
||||
- Exporting to Windows now changes the exported project's icon using `rcedit` (requires WINE if exporting from Linux or macOS).
|
||||
- Improved build system.
|
||||
- Support for compiling using Visual Studio 2017.
|
||||
- [SCons](http://scons.org/) 3.0 and Python 3 are now supported (SCons 2.5 and Python 2.7 still work).
|
||||
- Link-time optimization can now be enabled by passing `use_lto=yes` to the SCons command line.
|
||||
- Produces faster and sometimes smaller binaries.
|
||||
- Currently only supported with GCC and MSVC.
|
||||
- Added a progress percentage when compiling Godot.
|
||||
- `.zip` archives are automatically created when compiling HTML5 export templates.
|
||||
- Easier and more powerful way to create editor plugins with EditorPlugin and related APIs.
|
||||
|
||||
### Changed
|
||||
|
||||
- Increased the default low-processor-usage mode FPS limit (60 → 125).
|
||||
- This makes the editor smoother and more responsive.
|
||||
- Increased the default 3D editor camera's field of view (55 → 70).
|
||||
- Increased the default 3D Camera node's field of view (65 → 70).
|
||||
- Changed the default editor font (Droid Sans → [Noto Sans](https://www.google.com/get/noto/)).
|
||||
- Changed the default script editor font (Source Code Pro → [Hack](http://sourcefoundry.org/hack/))
|
||||
- Renamed `engine.cfg` to `project.godot`.
|
||||
- This allows users to open a project by double-clicking the file if Godot is associated to `.godot` files.
|
||||
- Some methods from the `OS` singleton were moved to the new `Engine` singleton.
|
||||
- Switched from [GLEW](http://glew.sourceforge.net/) to [GLAD](http://glad.dav1d.de/) for OpenGL wrapping.
|
||||
- Changed the SCons build flag for simple logs (`colored=yes` → `verbose=no`).
|
||||
- The HTML5 platform now uses WebGL 2.0 (instead of 1.0).
|
||||
- Redesigned the Godot logo to be more legible at small sizes.
|
||||
|
||||
### Deprecated
|
||||
|
||||
- `opacity` and `self_opacity` are replaced by `modulate` and `self_modulate` in all 2D nodes, allowing for full color changes in addition to opacity changes.
|
||||
|
||||
### Removed
|
||||
|
||||
- Skybox support.
|
||||
- Replaced with panorama skies, which are easier to import.
|
||||
- Opus audio codec support.
|
||||
- This is due to the way the new audio engine is designed.
|
||||
- HTML5 export using asm.js.
|
||||
- Only WebAssembly is supported now, since all browsers supporting WebGL 2.0 also support WebAssembly.
|
||||
|
||||
[3.0]: https://github.com/godotengine/godot/compare/2.1-stable...3.0-stable
|
||||
152
CONTRIBUTING.md
152
CONTRIBUTING.md
@ -1,170 +1,58 @@
|
||||
# How to contribute efficiently
|
||||
|
||||
Sections covered in this file:
|
||||
|
||||
* [Reporting bugs or proposing features](#reporting-bugs-or-proposing-features)
|
||||
* [Contributing pull requests](#contributing-pull-requests)
|
||||
* [Contributing to Godot's translation](#contributing-to-godots-translation)
|
||||
* [Communicating with developers](#communicating-with-developers)
|
||||
|
||||
**Please read the first section before reporting a bug!**
|
||||
|
||||
## Reporting bugs or proposing features
|
||||
|
||||
The golden rule is to **always open *one* issue for *one* bug**. If you notice
|
||||
several bugs and want to report them, make sure to create one new issue for
|
||||
each of them.
|
||||
The golden rule is to **always open *one* issue for *one* bug**. If you notice several bugs and want to report them, make sure to create one new issue for each of them.
|
||||
|
||||
Everything referred to hereafter as "bug" also applies for feature requests.
|
||||
Everything refered to hereafter as "bug" also applies for feature requests.
|
||||
|
||||
If you are reporting a new issue, you will make our life much simpler (and the
|
||||
fix come much sooner) by following those guidelines:
|
||||
If you are reporting a new issue, you will make our life much simpler (and the fix come much sooner) by following those guidelines:
|
||||
|
||||
#### Search first in the existing database
|
||||
|
||||
Issues are often reported several times by various users. It's a good practice
|
||||
to **search first** in the issues database before reporting your issue. If you
|
||||
don't find a relevant match or if you are unsure, don't hesitate to **open a
|
||||
new issue**. The bugsquad will handle it from there if it's a duplicate.
|
||||
Issues are often reported several times by various users. It's a good practice to **search first** in the issues database before reporting your issue. If you don't find a relevant match or if you are unsure, don't hesitate to **open a new issue**. The bugsquad will handle it from there if it's a duplicate.
|
||||
|
||||
#### Specify the platform
|
||||
|
||||
Godot runs on a large variety of platforms and operating systems and devices.
|
||||
If you believe your issue is device/platform dependent (for example if it is
|
||||
related to the rendering, crashes or compilation errors), please specify:
|
||||
#### Specify the platform
|
||||
|
||||
Godot runs on a large variety of platforms and operating systems and devices. If you believe your issue is device/platform dependent (for example if it is related to the rendering, crashes or compilation errors), please specify:
|
||||
* Operating system
|
||||
* Device (including architecture, e.g. x86, x86_64, arm, etc.)
|
||||
* GPU model (and driver in use if you know it)
|
||||
|
||||
#### Specify steps to reproduce
|
||||
|
||||
Many bugs can't be reproduced unless specific steps are taken. Please **specify
|
||||
the exact steps** that must be taken to reproduce the condition, and try to
|
||||
keep them as minimal as possible.
|
||||
Many bugs can't be reproduced unless specific steps are taken. Please **specify the exact steps** that must be taken to reproduce the condition, and try to keep them as minimal as possible.
|
||||
|
||||
#### Provide a simple, example project
|
||||
|
||||
Sometimes an unexpected behavior happens in your project. In such case,
|
||||
understand that:
|
||||
* What happens to you may not happen to other users.
|
||||
* We can't take the time to look at your project, understand how it is set up
|
||||
and then figure out why it's failing.
|
||||
Sometimes an unexpected behavior happens in your project. In such case, understand that:
|
||||
|
||||
To speed up our work, please prepare for us **a simple project** that isolates
|
||||
and reproduces the issue. This is always the **the best way for us to fix it**.
|
||||
You can attach a zip file with the minimal project directly to the bug report,
|
||||
by drag and dropping the file in the GitHub edition field.
|
||||
* What happens to you may not happen to other users.
|
||||
* We can't take the time to look at your project, understand how it is set up and then figure out why it's failing.
|
||||
|
||||
To speed up our work, please prepare for us **a simple project** that isolates and reproduces the issue. This is always the **the best way for us to fix it**. You can attach a zip file with the minimal project directly to the bug report, by drag and dropping the file in the GitHub edition field.
|
||||
|
||||
## Contributing pull requests
|
||||
|
||||
If you want to add new engine functionalities, please make sure that:
|
||||
|
||||
* This functionality is desired.
|
||||
* You talked to other developers on how to implement it best (on either
|
||||
communication channel, and maybe in a GitHub issue first before making your
|
||||
PR).
|
||||
* Even if it does not get merged, your PR is useful for future work by another
|
||||
developer.
|
||||
* You talked to other developers on how to implement it best (on either communication channel, and maybe in a GitHub issue first before making your PR).
|
||||
* Even if it does not get merged, your PR is useful for future work by another developer.
|
||||
|
||||
Similar rules can be applied when contributing bug fixes - it's always best to
|
||||
discuss the implementation in the bug report first if you are not 100% about
|
||||
what would be the best fix.
|
||||
|
||||
In addition to the following tips, also take a look at the
|
||||
[Engine development guide](http://docs.godotengine.org/en/latest/development/cpp/)
|
||||
for an introduction to developing on Godot.
|
||||
Similar rules can be applied when contributing bug fixes - it's always best to discuss the implementation in the bug report first if you are not 100% about what would be the best fix.
|
||||
|
||||
#### Be nice to the git history
|
||||
|
||||
Try to make simple PRs that handle one specific topic. Just like for reporting
|
||||
issues, it's better to open 3 different PRs that each address a different issue
|
||||
than one big PR with three commits.
|
||||
Try to make simple PRs with that handle one specific topic. Just like for reporting issues, it's better to open 3 different PRs that each address a different issue than one big PR with three commits.
|
||||
|
||||
When updating your fork with upstream changes, please use ``git pull --rebase``
|
||||
to avoid creating "merge commits". Those commits unnecessarily pollute the git
|
||||
history when coming from PRs.
|
||||
When updating your fork with upstream changes, please use ``git pull --rebase`` to avoid creating "merge commits". Those commits unnecessarily pollute the git history when coming from PRs.
|
||||
|
||||
Also try to make commits that bring the engine from one stable state to another
|
||||
stable state, i.e. if your first commit has a bug that you fixed in the second
|
||||
commit, try to merge them together before making your pull request (see ``git
|
||||
rebase -i`` and relevant help about rebasing or amending commits on the
|
||||
Internet).
|
||||
Also try to make commits that bring the engine from one stable state to another stable state, i.e. if your first commit has a bug that you fixed in the second commit, try to merge them together before making your pull request (see ``git rebase -i`` and relevant help about rebasing or ammending commits on the Internet).
|
||||
|
||||
This git style guide has some good practices to have in mind:
|
||||
[Git Style Guide](https://github.com/agis-/git-style-guide)
|
||||
|
||||
#### Format your commit logs with readability in mind
|
||||
|
||||
The way you format your commit logs is quite important to ensure that the
|
||||
commit history and changelog will be easy to read and understand. A git commit
|
||||
log is formatted as a short title (first line) and an extended description
|
||||
(everything after the first line and an empty separation line).
|
||||
|
||||
The short title is the most important part, as it is what will appear in the
|
||||
`shortlog` changelog (one line per commit, so no description shown) or in the
|
||||
GitHub interface unless you click the "expand" button. As the name tells it,
|
||||
try to keep that first line relatively short (ideally <= 50 chars, though it's
|
||||
rare to be able to tell enough in so few characters, so you can go a bit
|
||||
higher) - it should describe what the commit does globally, while details would
|
||||
go in the description. Typically, if you can't keep the title short because you
|
||||
have too much stuff to mention, it means that you should probably split your
|
||||
changes in several commits :)
|
||||
|
||||
Here's an example of a well-formatted commit log (note how the extended
|
||||
description is also manually wrapped at 80 chars for readability):
|
||||
|
||||
```
|
||||
Prevent French fries carbonization by fixing heat regulation
|
||||
|
||||
When using the French fries frying module, Godot would not regulate the heat
|
||||
and thus bring the oil bath to supercritical liquid conditions, thus causing
|
||||
unwanted side effects in the physics engine.
|
||||
|
||||
By fixing the regulation system via an added binding to the internal feature,
|
||||
this commit now ensures that Godot will not go past the ebullition temperature
|
||||
of cooking oil under normal atmospheric conditions.
|
||||
|
||||
Fixes #1789, long live the Realm!
|
||||
```
|
||||
|
||||
*Note:* When using the GitHub online editor (or worse, the drag and drop
|
||||
feature), *please* edit the commit title to something meaningful. Commits named
|
||||
"Update my_file.cpp" will not be accepted.
|
||||
|
||||
## Contributing to Godot's translation
|
||||
|
||||
You can contribute to Godot's translation from the [Hosted
|
||||
Weblate](https://hosted.weblate.org/projects/godot-engine/godot), an open
|
||||
source and web-based translation platform. Please refer to the [translation
|
||||
readme](editor/translations/README.md) for more information.
|
||||
|
||||
## Communicating with developers
|
||||
|
||||
The Godot Engine community has [many communication
|
||||
channels](https://godotengine.org/community), some used more for user-level
|
||||
discussions and support, others more for development discussions.
|
||||
|
||||
To communicate with developers (e.g. to discuss a feature you want to implement
|
||||
or a bug you want to fix), the following channels can be used:
|
||||
- [GitHub issues](https://github.com/godotengine/godot/issues): If there is an
|
||||
existing issue about a topic you want to discuss, just add a comment to it -
|
||||
all developers watch the repository and will get an email notification. You
|
||||
can also create a new issue - please keep in mind to create issues only to
|
||||
discuss quite specific points about the development, and not general user
|
||||
feedback or support requests.
|
||||
- [#godotengine-devel IRC channel on
|
||||
Freenode](https://webchat.freenode.net/?channels=godotengine-devel): You will
|
||||
find most core developers there, so it's the go-to channel for direct chat
|
||||
about Godot Engine development. Feel free to start discussing something there
|
||||
to get some early feedback before writing up a detailed proposal in a GitHub
|
||||
issue.
|
||||
- [devel@godotengine.org mailing
|
||||
list](https://listengine.tuxfamily.org/godotengine.org/devel/): Mailing list
|
||||
for Godot developers, used primarily to announce developer meetings on IRC
|
||||
and other important discussions that need to reach people directly in their
|
||||
mailbox. See the [index
|
||||
page](https://listengine.tuxfamily.org/godotengine.org/devel/) for
|
||||
subscription instructions.
|
||||
This git style guide has some good practices to have in mind: https://github.com/agis-/git-style-guide
|
||||
|
||||
Thanks!
|
||||
|
||||
|
||||
1644
COPYRIGHT.txt
1644
COPYRIGHT.txt
File diff suppressed because it is too large
Load Diff
529
DONORS.md
529
DONORS.md
@ -1,529 +0,0 @@
|
||||
# Donors to the Godot Engine project
|
||||
|
||||
Godot Engine is a non-profit project developed by a community of voluntary
|
||||
contributors, as well as occasional paid contributors thanks to the financial
|
||||
support of generous donors.
|
||||
|
||||
The ways to donate to the project, as well as details on how the funds are
|
||||
used, are described on [Godot's website](https://godotengine.org/donate).
|
||||
|
||||
The following is a list of the current monthly donors, to be have their
|
||||
generous deed immortalized in the next stable release of Godot Engine.
|
||||
|
||||
## Platinum sponsors
|
||||
|
||||
Heroic Labs <https://heroiclabs.com>
|
||||
Interblock <http://interblockgaming.com>
|
||||
|
||||
## Gold sponsors
|
||||
|
||||
Gamblify <https://www.gamblify.com>
|
||||
Moonwards <https://www.moonwards.com>
|
||||
|
||||
## Mini sponsors
|
||||
|
||||
AD Ford
|
||||
Alan Beauchamp
|
||||
Anand Mallik
|
||||
Andres Hernandez
|
||||
Andrew Dunai
|
||||
Brandon Lamb
|
||||
Christian Baune
|
||||
Christopher Montesano
|
||||
Darkhan Baimyrza
|
||||
Darrin Massena
|
||||
Dov Zimring
|
||||
Edward Flick
|
||||
Gamechuck
|
||||
GameDev.net
|
||||
GameDev.tv
|
||||
Grady
|
||||
Hein-Pieter van Braam
|
||||
Jacob McKenney
|
||||
Javary Co.
|
||||
Jeffery Chiu
|
||||
Justin Arnold
|
||||
Justo Delgado Baudí
|
||||
Kyle Szklenski
|
||||
Matthieu Huvé
|
||||
Maxim Karsten
|
||||
Mike King
|
||||
Nathan Warden
|
||||
Neal Gompa (Conan Kudo)
|
||||
Péter Magyar
|
||||
Slobodan Milnovic
|
||||
Stephan Lanfermann
|
||||
Steve
|
||||
Tristan Pemble
|
||||
VilliHaukka
|
||||
|
||||
## Gold donors
|
||||
|
||||
Andrei
|
||||
Dave
|
||||
David Gehrig
|
||||
David Snopek
|
||||
Ed Morley
|
||||
Florian Krick
|
||||
Florian Rämisch
|
||||
Jakub Grzesik
|
||||
Manuele Finocchiaro
|
||||
Officine Pixel S.n.c.
|
||||
Retro Village
|
||||
Ronan Zeegers
|
||||
Sofox
|
||||
Taylor Ritenour
|
||||
Zaven Muradyan
|
||||
|
||||
Asher Glick
|
||||
Austen McRae
|
||||
Bernhard Werner
|
||||
beVR
|
||||
Carlo Cabanilla
|
||||
Daniel James
|
||||
David Giardi
|
||||
Default Name
|
||||
eggs
|
||||
Felix Bohmann
|
||||
Florian Breisch
|
||||
Gamejunkey
|
||||
Javier Roman
|
||||
Jay Horton
|
||||
Jon Woodward
|
||||
Karl Werf
|
||||
Keinan Powers
|
||||
Klavdij Voncina
|
||||
Lex Steers
|
||||
Luke
|
||||
Maciej Pendolski
|
||||
Matthew Hillier
|
||||
Mohamed Ikbel Boulabiar
|
||||
Mored4u
|
||||
Rob Messick
|
||||
Ryan Badour
|
||||
Sandro Jenny
|
||||
Scott Wadden
|
||||
Sergey
|
||||
thechris
|
||||
Tom Langwaldt
|
||||
tukon
|
||||
William Wold
|
||||
|
||||
Alex Khayrullin
|
||||
Chris Goddard
|
||||
Chris Serino
|
||||
Christian Padilla
|
||||
Conrad Curry
|
||||
Craig Smith
|
||||
Darrian Little
|
||||
Horváth Péter
|
||||
Ivan Trombley
|
||||
Jakub Dering
|
||||
Joan Fons
|
||||
Joshua Flores
|
||||
Krzysztof Jankowski
|
||||
Lord Bloodhound
|
||||
Pascal Grüter
|
||||
Petr Malac
|
||||
Rami
|
||||
Reneator
|
||||
Rob
|
||||
Robert Willes
|
||||
Ronnie Ashlock
|
||||
SKison
|
||||
Thomas Bjarnelöf
|
||||
Unseen Domains
|
||||
Valryia
|
||||
Vincent Henderson
|
||||
Wojciech Chojnacki
|
||||
Xavier PATRICELLI
|
||||
|
||||
Adam Nakonieczny
|
||||
Adam Neumann
|
||||
Alexander J Maynard
|
||||
Alexey Dyadchenko
|
||||
Alex Z
|
||||
Andreas Funke
|
||||
André Frélicot
|
||||
aoshiwik
|
||||
Ben Powell
|
||||
Carlos de Sousa Marques
|
||||
Charlie Whitfield
|
||||
Chase Taranto
|
||||
Chris Petrich
|
||||
Christian Leth Jeppesen
|
||||
Christoph Schröder
|
||||
Cody Parker
|
||||
Coldragon
|
||||
Craig Ostrin
|
||||
D
|
||||
Daniel Eichler
|
||||
David White
|
||||
Denis Janßen
|
||||
Easypete
|
||||
Eric Monson
|
||||
ethan ball
|
||||
Eugenio Hugo Salgüero Jáñez
|
||||
Fain
|
||||
flesk
|
||||
Gary Hulst
|
||||
gavlig
|
||||
GGGames.org
|
||||
Green Fox
|
||||
Guilherme Felipe de C. G. da Silva
|
||||
Halom Vered
|
||||
Heath Hayes
|
||||
Idzard Kwadijk
|
||||
Isaac Clausman
|
||||
Jared White
|
||||
Jeff Nyte
|
||||
Jeremy Sims
|
||||
Jerry Ling
|
||||
Joe Flood
|
||||
John G Gentzel
|
||||
Jon Hermansen
|
||||
Jose Malheiro
|
||||
Joshua Lesperance
|
||||
Juan Velandia
|
||||
Juraj Móza
|
||||
kinfox
|
||||
Marcelo Dornbusch Lopes
|
||||
Markus Fehr
|
||||
Markus Wiesner
|
||||
Martin Eigel
|
||||
Matt Eunson
|
||||
Max Bulai
|
||||
MuffinManKen
|
||||
Nick Nikitin
|
||||
Oliver Dick
|
||||
Patrick Ting
|
||||
Paul Hocker
|
||||
Paul Von Zimmerman
|
||||
Pete Goodwin
|
||||
pl
|
||||
Ranoller
|
||||
Robert Larnach
|
||||
Rocknight Studios
|
||||
Romildo Franco
|
||||
Samuel Judd
|
||||
Scott Pilet
|
||||
Sean Morgan
|
||||
SleepCircle
|
||||
spilldata
|
||||
Steve Hyatt
|
||||
Stoned Xander
|
||||
TheLevelOfDetail .
|
||||
Thomas Krampl
|
||||
Thomas Kurz
|
||||
Tobias Bocanegra
|
||||
Tricky Fat Cat
|
||||
Urho
|
||||
William Foster
|
||||
Zhou Tuizhi
|
||||
Zie Weaver
|
||||
蕭惟允
|
||||
|
||||
## Silver donors
|
||||
|
||||
1D_Inc
|
||||
Abraham Haskins
|
||||
Adam
|
||||
Adam Brunnmeier
|
||||
Adam Carr
|
||||
Adam Long
|
||||
Adam McCurdy
|
||||
Adam N Webber
|
||||
Adam Smeltzer
|
||||
Adam Szymański
|
||||
Adisibio
|
||||
Adrian Demetrescu
|
||||
Agustinus Arya
|
||||
Aidan O'Flannagain
|
||||
Aki Mimoto
|
||||
Alan Mervitz
|
||||
Alan Stice
|
||||
Albin Jonasson Svärdsby
|
||||
Alder Stefano
|
||||
Alessandro Senese
|
||||
Alexander Erlemann
|
||||
alex clavelle
|
||||
Allan Davis
|
||||
Allen Schade
|
||||
Andreas Evers
|
||||
Andreas Krampitz
|
||||
André Simões
|
||||
Andrew Thomas
|
||||
Anthony Staunton
|
||||
AP Condomines
|
||||
Arda Erol
|
||||
Armin Preiml
|
||||
Arseniy M
|
||||
Arthur S. Muszynski
|
||||
Asger
|
||||
Aubrey Falconer
|
||||
Avencherus
|
||||
B A
|
||||
Balázs Batári
|
||||
Benedikt
|
||||
Ben G
|
||||
Ben Phelan
|
||||
Ben Vercammen
|
||||
Bernd Jänichen
|
||||
Black Block
|
||||
Blair Allen
|
||||
Bobby CC Wong
|
||||
brian
|
||||
bugcaptor
|
||||
Burney Waring
|
||||
Cameron Meyer
|
||||
Carl van der Geest
|
||||
Carwyn Edwards
|
||||
Cassidy James
|
||||
Chris Brown
|
||||
Chris Chapin
|
||||
Christian Winter
|
||||
Christoffer Sundbom
|
||||
Christoph Brodmann
|
||||
Christopher Schmitt
|
||||
Christoph Woinke
|
||||
Clay Heaton
|
||||
Curt King
|
||||
Dancin Liao
|
||||
Daniel Johnson
|
||||
Daniel Kimblad
|
||||
Daniel Pontillo
|
||||
David May
|
||||
David Woodard
|
||||
DiCola Jamn
|
||||
Dominic Cooney
|
||||
Dominik Wetzel
|
||||
Donn Eddy
|
||||
Donovan Hutcheon
|
||||
Dragontrapper
|
||||
Dr Ewan Murray
|
||||
Duobix
|
||||
Duodecimal
|
||||
Dylan Todd
|
||||
Eduardo Teixeira
|
||||
Edward Herbert
|
||||
Edward Moulsdale
|
||||
Edward Swartz
|
||||
Egon Elbre
|
||||
Elias Nykrem
|
||||
Elmeri '- Duy Kevin Nguyen
|
||||
Ephemeral
|
||||
Eric Ellingson
|
||||
Eric Rogers
|
||||
Eric Williams
|
||||
Erkki Seppälä
|
||||
Evan Rose
|
||||
Fancy Ants Studios
|
||||
Fekinox
|
||||
Felix Kollmann
|
||||
Flaredown
|
||||
Forty Doubleu
|
||||
FuDiggity
|
||||
Gadzhi Kharkharov
|
||||
gamedev by Celio
|
||||
Gary Thomas
|
||||
George Marques
|
||||
GiulianoB
|
||||
Gordian Arragon
|
||||
Greg Olson
|
||||
GREGORY C FEIN
|
||||
Greg P
|
||||
Greyson Richey
|
||||
Grid
|
||||
Guldoman
|
||||
Hal A
|
||||
Heribert Hirth
|
||||
Hudson Thorpe-Doubble
|
||||
Hunter Jones
|
||||
Hylpher
|
||||
Ichiro Dohi
|
||||
Iiari
|
||||
iKlem
|
||||
IndustrialRobot
|
||||
Jaiden Gerig
|
||||
Jaime Ruiz-Borau Vizárraga
|
||||
Jako Danar
|
||||
James A F Manley
|
||||
Janders
|
||||
Jannik Gröger
|
||||
JARKKO PARVIAINEN
|
||||
Jarrod Davis
|
||||
Jeff Hungerford
|
||||
Jennifer Graves
|
||||
Jeremy Kahn
|
||||
Jesse Dubay
|
||||
Joel Fivat
|
||||
Joel Höglund
|
||||
Joel Setterberg
|
||||
Johannes Wuensch
|
||||
John Gabriel
|
||||
Jomei Jackson
|
||||
Jonas Rudlang
|
||||
Jonas Yamazaki
|
||||
Jonathan G
|
||||
Jonathon
|
||||
Jon Bonazza
|
||||
Jon Sully
|
||||
Jorge Caballero
|
||||
Jose Aleman
|
||||
Jose C. Rubio
|
||||
Joseph Catrambone
|
||||
Juanfran
|
||||
Judd
|
||||
Julian Murgia
|
||||
JungleRobba
|
||||
Justin Spedding
|
||||
KaDokta
|
||||
Kauzig
|
||||
Keedong Park
|
||||
Keith Bradner
|
||||
Kevin McPhillips
|
||||
kickmaniac
|
||||
Kiyohiro Kawamura (kyorohiro)
|
||||
Kjetil Haugland
|
||||
Klagsam
|
||||
KR McGinley
|
||||
KsyTek Games
|
||||
Kuan Cheang
|
||||
kycho
|
||||
Kyle Appelgate
|
||||
Laurent Tréguier
|
||||
Leonardo Dimano
|
||||
Levi Lindsey
|
||||
Linus Lind Lundgren
|
||||
Lionel Gaillard
|
||||
Luigi Renna
|
||||
LunaticInAHat
|
||||
Lurkars
|
||||
Major Haul
|
||||
Malcolm
|
||||
Malik Ahmed
|
||||
Malik Nejer
|
||||
Markus Michael Egger
|
||||
Martin Holas
|
||||
Martin Liška
|
||||
Marvin
|
||||
Mathieu Rimelen
|
||||
Matt Edwards
|
||||
Matthew Little
|
||||
Matti Pohjanvirta
|
||||
Maxime Blade
|
||||
Maxwell
|
||||
medecau
|
||||
Megasploot
|
||||
Melissa Mears
|
||||
mewin
|
||||
mhilbrunner
|
||||
Michael Haney
|
||||
Michael Labbe
|
||||
Mikael Olsson
|
||||
Mikayla
|
||||
Mike Birkhead
|
||||
Mike Cunningham
|
||||
Mitchell J. Wagner
|
||||
MoM
|
||||
Nathan Fish
|
||||
Natrim
|
||||
nee
|
||||
Neil Blakey-Milner
|
||||
Neil Wang
|
||||
Nerdforge
|
||||
Nicholas
|
||||
Nicholas Girga
|
||||
Nick Macholl
|
||||
Nicolás Montaña
|
||||
Nicolas SAN AGUSTIN
|
||||
Nima Farid
|
||||
NZ
|
||||
Oleg Reva
|
||||
Olivier
|
||||
Omar Delarosa
|
||||
Oscar Norlander
|
||||
Pan Ip
|
||||
Patrick Nafarrete
|
||||
Paul Gieske
|
||||
Paul Mason
|
||||
Paweł Kowal
|
||||
Pedro Assuncao
|
||||
Penguin
|
||||
Petrus Prinsloo
|
||||
Philip Cohoe
|
||||
Point08
|
||||
Rad Cat
|
||||
Rafa Laguna
|
||||
rainerLinux
|
||||
Raphael Leroux
|
||||
Remi Rampin
|
||||
Rémi Verschelde
|
||||
Ricardo Alcantara
|
||||
Richard Diss
|
||||
Richard Ivánek
|
||||
Robert Farr (Larington)
|
||||
Robert Hernandez
|
||||
Roberto Sánchez
|
||||
Roger Smith
|
||||
Roland Rząsa
|
||||
Roman Tinkov
|
||||
Ronald Ho Hip (CrimsonZA)
|
||||
Ronan
|
||||
Ryan Groom
|
||||
Ryan Hentz
|
||||
Sam.C
|
||||
Sam Edson
|
||||
Samuele Zolfanelli
|
||||
Sasori Olkof
|
||||
Scott D. Yelich
|
||||
Scott Longley
|
||||
Sebastian Michailidis
|
||||
Sergio Mello-Grand
|
||||
sgnsajgon
|
||||
Shane
|
||||
Shane Sicienski
|
||||
Shane Spoor
|
||||
Siim Raidma
|
||||
Simon Wenner
|
||||
SK
|
||||
smbe19
|
||||
smo1704
|
||||
Svenne Krap
|
||||
Terry
|
||||
tezuvholovdr
|
||||
thomas
|
||||
Thomas Bechtold
|
||||
Thomas Detoy
|
||||
Thomas Kelly
|
||||
Tim Drumheller
|
||||
Timothy B. MacDonald
|
||||
Tobbun
|
||||
Torgeir Lilleskog
|
||||
Torsten Crass
|
||||
Travis O'Brien
|
||||
Trent Skinner
|
||||
Troy Bonneau
|
||||
Tryggve Sollid
|
||||
Turgut Temucin
|
||||
Tyler Compton
|
||||
Tyler Stafos
|
||||
UltyX
|
||||
Vaughan Ling
|
||||
Victor
|
||||
Vigilant Watch
|
||||
Vincent Cloutier
|
||||
waka nya
|
||||
Wayne Haak
|
||||
werner mendizabal
|
||||
Wiley Thompson
|
||||
Will
|
||||
William Hogben
|
||||
Wyatt Goodin
|
||||
Yegor
|
||||
Yuri Sizov
|
||||
|
||||
## Bronze donors
|
||||
|
||||
There are even more donors that support the project with a small monthly donation.
|
||||
Every bit counts and we thank every one of them for their amazing support!
|
||||
10
ISSUE_TEMPLATE
Normal file
10
ISSUE_TEMPLATE
Normal file
@ -0,0 +1,10 @@
|
||||
**Operating system or device - Godot version:**
|
||||
|
||||
|
||||
**Issue description** (what happened, and what was expected):
|
||||
|
||||
|
||||
**Steps to reproduce:**
|
||||
|
||||
|
||||
**Link to minimal example project** (optional but very welcome):
|
||||
@ -1,21 +0,0 @@
|
||||
<!-- Please search existing issues for potential duplicates before filing yours:
|
||||
https://github.com/godotengine/godot/issues?q=is%3Aissue
|
||||
-->
|
||||
|
||||
**Godot version:**
|
||||
<!-- Specify commit hash if non-official. -->
|
||||
|
||||
|
||||
**OS/device including version:**
|
||||
<!-- Specify GPU model and drivers if graphics-related. -->
|
||||
|
||||
|
||||
**Issue description:**
|
||||
<!-- What happened, and what was expected. -->
|
||||
|
||||
|
||||
**Steps to reproduce:**
|
||||
|
||||
|
||||
**Minimal reproduction project:**
|
||||
<!-- Recommended as it greatly speeds up debugging. Drag and drop a zip archive to upload it. -->
|
||||
27
LICENSE.md
Normal file
27
LICENSE.md
Normal file
@ -0,0 +1,27 @@
|
||||
GODOT ENGINE
|
||||
http://www.godotengine.org
|
||||
|
||||
************************************************************************
|
||||
|
||||
Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.
|
||||
|
||||
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.
|
||||
|
||||
************************************************************************
|
||||
20
LICENSE.txt
20
LICENSE.txt
@ -1,20 +0,0 @@
|
||||
Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.
|
||||
Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)
|
||||
|
||||
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.
|
||||
@ -1,3 +1,2 @@
|
||||
Godot Logo (C) Andrea Calabró
|
||||
Distributed under the terms of the Creative Commons Attribution License
|
||||
version 3.0 (CC-BY 3.0) <https://creativecommons.org/licenses/by/3.0/legalcode>.
|
||||
Godot Logo (c) Andrea Calabró, distributed under the terms of the CC By License:
|
||||
https://creativecommons.org/licenses/by/3.0/legalcode
|
||||
17
README.md
17
README.md
@ -1,4 +1,4 @@
|
||||
[](https://godotengine.org)
|
||||
[](https://godotengine.org)
|
||||
|
||||
## Godot Engine
|
||||
|
||||
@ -26,8 +26,6 @@ Before being open sourced in February 2014, Godot had been developed by Juan
|
||||
Linietsky and Ariel Manzur (both still maintaining the project) for several
|
||||
years as an in-house engine, used to publish several work-for-hire titles.
|
||||
|
||||

|
||||
|
||||
### Getting the engine
|
||||
|
||||
#### Binary downloads
|
||||
@ -37,10 +35,10 @@ Official binaries for the Godot editor and the export templates can be found
|
||||
|
||||
#### Compiling from source
|
||||
|
||||
[See the official docs](http://docs.godotengine.org/en/latest/development/compiling/)
|
||||
[See the official docs](http://docs.godotengine.org/en/latest/reference/_compiling.html)
|
||||
for compilation instructions for every supported platform.
|
||||
|
||||
### Community and contributing
|
||||
### Community
|
||||
|
||||
Godot is not only an engine but an ever-growing community of users and engine
|
||||
developers. The main community channels are listed [on the homepage](https://godotengine.org/community).
|
||||
@ -49,14 +47,12 @@ To get in touch with the developers, the best way is to join the
|
||||
[#godotengine IRC channel](https://webchat.freenode.net/?channels=godotengine)
|
||||
on Freenode.
|
||||
|
||||
To get started contributing to the project, see the [contributing guide](CONTRIBUTING.md).
|
||||
|
||||
### Documentation and demos
|
||||
|
||||
The official documentation is hosted on [ReadTheDocs](http://docs.godotengine.org).
|
||||
It is maintained by the Godot community in its own [GitHub repository](https://github.com/godotengine/godot-docs).
|
||||
|
||||
The [class reference](http://docs.godotengine.org/en/latest/classes/)
|
||||
The [class reference](http://docs.godotengine.org/en/latest/classes/_classes.html)
|
||||
is also accessible from within the engine.
|
||||
|
||||
The official demos are maintained in their own [GitHub repository](https://github.com/godotengine/godot-demo-projects)
|
||||
@ -66,6 +62,5 @@ There are also a number of other learning resources provided by the community,
|
||||
such as text and video tutorials, demos, etc. Consult the [community channels](https://godotengine.org/community)
|
||||
for more info.
|
||||
|
||||
[](https://travis-ci.org/godotengine/godot)
|
||||
[](https://ci.appveyor.com/project/akien-mga/godot)
|
||||
[](https://www.codetriage.com/godotengine/godot)
|
||||
[](https://travis-ci.org/godotengine/godot)
|
||||
[](http://www.codetriage.com/godotengine/godot)
|
||||
|
||||
432
SConstruct
432
SConstruct
@ -1,18 +1,17 @@
|
||||
|
||||
#!/usr/bin/env python
|
||||
|
||||
EnsureSConsVersion(0, 98, 1)
|
||||
EnsureSConsVersion(0, 14)
|
||||
|
||||
|
||||
# System
|
||||
import glob
|
||||
import os
|
||||
import string
|
||||
import os
|
||||
import os.path
|
||||
import glob
|
||||
import sys
|
||||
|
||||
# Local
|
||||
import methods
|
||||
|
||||
# moved below to compensate with module version string
|
||||
# methods.update_version()
|
||||
methods.update_version()
|
||||
|
||||
# scan possible build platforms
|
||||
|
||||
@ -20,10 +19,10 @@ platform_list = [] # list of platforms
|
||||
platform_opts = {} # options for each platform
|
||||
platform_flags = {} # flags for each platform
|
||||
|
||||
|
||||
active_platforms = []
|
||||
active_platform_ids = []
|
||||
platform_exporters = []
|
||||
platform_apis = []
|
||||
global_defaults = []
|
||||
|
||||
for x in glob.glob("platform/*"):
|
||||
@ -31,13 +30,11 @@ for x in glob.glob("platform/*"):
|
||||
continue
|
||||
tmppath = "./" + x
|
||||
|
||||
sys.path.insert(0, tmppath)
|
||||
sys.path.append(tmppath)
|
||||
import detect
|
||||
|
||||
if (os.path.exists(x + "/export/export.cpp")):
|
||||
platform_exporters.append(x[9:])
|
||||
if (os.path.exists(x + "/api/api.cpp")):
|
||||
platform_apis.append(x[9:])
|
||||
if (os.path.exists(x + "/globals/global_defaults.cpp")):
|
||||
global_defaults.append(x[9:])
|
||||
if (detect.is_active()):
|
||||
@ -66,7 +63,7 @@ platform_arg = ARGUMENTS.get("platform", ARGUMENTS.get("p", False))
|
||||
if (os.name == "posix"):
|
||||
pass
|
||||
elif (os.name == "nt"):
|
||||
if (os.getenv("VCINSTALLDIR") == None or platform_arg == "android" or platform_arg == "javascript"):
|
||||
if (os.getenv("VSINSTALLDIR") == None or platform_arg == "android"):
|
||||
custom_tools = ['mingw']
|
||||
|
||||
env_base = Environment(tools=custom_tools)
|
||||
@ -76,13 +73,9 @@ env_base.AppendENVPath('PATH', os.getenv('PATH'))
|
||||
env_base.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH'))
|
||||
env_base.global_defaults = global_defaults
|
||||
env_base.android_maven_repos = []
|
||||
env_base.android_flat_dirs = []
|
||||
env_base.android_dependencies = []
|
||||
env_base.android_gradle_plugins = []
|
||||
env_base.android_gradle_classpath = []
|
||||
env_base.android_java_dirs = []
|
||||
env_base.android_res_dirs = []
|
||||
env_base.android_asset_dirs = []
|
||||
env_base.android_aidl_dirs = []
|
||||
env_base.android_jni_dirs = []
|
||||
env_base.android_default_config = []
|
||||
@ -92,44 +85,24 @@ env_base.android_appattributes_chunk = ""
|
||||
env_base.disabled_modules = []
|
||||
env_base.use_ptrcall = False
|
||||
env_base.split_drivers = False
|
||||
env_base.split_modules = False
|
||||
env_base.module_version_string = ""
|
||||
|
||||
# To decide whether to rebuild a file, use the MD5 sum only if the timestamp has changed.
|
||||
# http://scons.org/doc/production/HTML/scons-user/ch06.html#idm139837621851792
|
||||
env_base.Decider('MD5-timestamp')
|
||||
# Use cached implicit dependencies by default. Can be overridden by specifying `--implicit-deps-changed` in the command line.
|
||||
# http://scons.org/doc/production/HTML/scons-user/ch06s04.html
|
||||
env_base.SetOption('implicit_cache', 1)
|
||||
|
||||
|
||||
env_base.__class__.android_add_maven_repository = methods.android_add_maven_repository
|
||||
env_base.__class__.android_add_flat_dir = methods.android_add_flat_dir
|
||||
env_base.__class__.android_add_dependency = methods.android_add_dependency
|
||||
env_base.__class__.android_add_java_dir = methods.android_add_java_dir
|
||||
env_base.__class__.android_add_res_dir = methods.android_add_res_dir
|
||||
env_base.__class__.android_add_asset_dir = methods.android_add_asset_dir
|
||||
env_base.__class__.android_add_aidl_dir = methods.android_add_aidl_dir
|
||||
env_base.__class__.android_add_jni_dir = methods.android_add_jni_dir
|
||||
env_base.__class__.android_add_default_config = methods.android_add_default_config
|
||||
env_base.__class__.android_add_to_manifest = methods.android_add_to_manifest
|
||||
env_base.__class__.android_add_to_permissions = methods.android_add_to_permissions
|
||||
env_base.__class__.android_add_to_attributes = methods.android_add_to_attributes
|
||||
env_base.__class__.android_add_gradle_plugin = methods.android_add_gradle_plugin
|
||||
env_base.__class__.android_add_gradle_classpath = methods.android_add_gradle_classpath
|
||||
env_base.__class__.disable_module = methods.disable_module
|
||||
|
||||
env_base.__class__.add_module_version_string = methods.add_module_version_string
|
||||
|
||||
env_base.__class__.add_source_files = methods.add_source_files
|
||||
env_base.__class__.use_windows_spawn_fix = methods.use_windows_spawn_fix
|
||||
env_base.__class__.split_lib = methods.split_lib
|
||||
|
||||
env_base.__class__.add_shared_library = methods.add_shared_library
|
||||
env_base.__class__.add_library = methods.add_library
|
||||
env_base.__class__.add_program = methods.add_program
|
||||
env_base.__class__.CommandNoCache = methods.CommandNoCache
|
||||
|
||||
env_base["x86_libtheora_opt_gcc"] = False
|
||||
env_base["x86_libtheora_opt_vc"] = False
|
||||
|
||||
@ -139,6 +112,7 @@ customs = ['custom.py']
|
||||
|
||||
profile = ARGUMENTS.get("profile", False)
|
||||
if profile:
|
||||
import os.path
|
||||
if os.path.isfile(profile):
|
||||
customs.append(profile)
|
||||
elif os.path.isfile(profile + ".py"):
|
||||
@ -148,58 +122,48 @@ opts = Variables(customs, ARGUMENTS)
|
||||
|
||||
# Target build options
|
||||
opts.Add('arch', "Platform-dependent architecture (arm/arm64/x86/x64/mips/etc)", '')
|
||||
opts.Add(EnumVariable('bits', "Target platform bits", 'default', ('default', '32', '64', 'fat')))
|
||||
opts.Add('bits', "Target platform bits (default/32/64/fat)", 'default')
|
||||
opts.Add('p', "Platform (alias for 'platform')", '')
|
||||
opts.Add('platform', "Target platform (%s)" % ('|'.join(platform_list), ), '')
|
||||
opts.Add(EnumVariable('target', "Compilation target", 'debug', ('debug', 'release_debug', 'release')))
|
||||
opts.Add(BoolVariable('tools', "Build the tools a.k.a. the Godot editor", True))
|
||||
opts.Add(BoolVariable('use_lto', 'Use linking time optimization', False))
|
||||
opts.Add('platform', "Target platform: any in " + str(platform_list), '')
|
||||
opts.Add('target', "Compilation target (debug/release_debug/release)", 'debug')
|
||||
opts.Add('tools', "Build the tools a.k.a. the Godot editor (yes/no)", 'yes')
|
||||
|
||||
# Components
|
||||
opts.Add(BoolVariable('deprecated', "Enable deprecated features", True))
|
||||
opts.Add(BoolVariable('gdscript', "Build GDSCript support", True))
|
||||
opts.Add(BoolVariable('minizip', "Build minizip archive support", True))
|
||||
opts.Add(BoolVariable('xaudio2', "XAudio2 audio driver", False))
|
||||
opts.Add(BoolVariable('xml', "XML format support for resources", True))
|
||||
opts.Add('deprecated', "Enable deprecated features (yes/no)", 'yes')
|
||||
opts.Add('gdscript', "Build GDSCript support (yes/no)", 'yes')
|
||||
opts.Add('minizip', "Build minizip archive support (yes/no)", 'yes')
|
||||
opts.Add('xml', "XML format support for resources (yes/no)", 'yes')
|
||||
|
||||
# Advanced options
|
||||
opts.Add(BoolVariable('disable_3d', "Disable 3D nodes for smaller executable", False))
|
||||
opts.Add(BoolVariable('disable_advanced_gui', "Disable advanced 3D gui nodes and behaviors", False))
|
||||
opts.Add('disable_3d', "Disable 3D nodes for smaller executable (yes/no)", 'no')
|
||||
opts.Add('disable_advanced_gui', "Disable advance 3D gui nodes and behaviors (yes/no)", 'no')
|
||||
opts.Add('extra_suffix', "Custom extra suffix added to the base filename of all generated binary files", '')
|
||||
opts.Add('unix_global_settings_path', "UNIX-specific path to system-wide settings. Currently only used for templates", '')
|
||||
opts.Add(BoolVariable('verbose', "Enable verbose output for the compilation", False))
|
||||
opts.Add(BoolVariable('vsproj', "Generate Visual Studio Project", False))
|
||||
opts.Add(EnumVariable('warnings', "Set the level of warnings emitted during compilation", 'no', ('extra', 'all', 'moderate', 'no')))
|
||||
opts.Add(BoolVariable('progress', "Show a progress indicator during build", True))
|
||||
opts.Add(BoolVariable('dev', "If yes, alias for verbose=yes warnings=all", False))
|
||||
opts.Add(EnumVariable('macports_clang', "Build using clang from MacPorts", 'no', ('no', '5.0', 'devel')))
|
||||
opts.Add('verbose', "Enable verbose output for the compilation (yes/no)", 'yes')
|
||||
opts.Add('vsproj', "Generate Visual Studio Project. (yes/no)", 'no')
|
||||
|
||||
# Thirdparty libraries
|
||||
opts.Add(BoolVariable('builtin_bullet', "Use the builtin bullet library", True))
|
||||
opts.Add(BoolVariable('builtin_enet', "Use the builtin enet library", True))
|
||||
opts.Add(BoolVariable('builtin_freetype', "Use the builtin freetype library", True))
|
||||
opts.Add(BoolVariable('builtin_libogg', "Use the builtin libogg library", True))
|
||||
opts.Add(BoolVariable('builtin_libpng', "Use the builtin libpng library", True))
|
||||
opts.Add(BoolVariable('builtin_libtheora', "Use the builtin libtheora library", True))
|
||||
opts.Add(BoolVariable('builtin_libvorbis', "Use the builtin libvorbis library", True))
|
||||
opts.Add(BoolVariable('builtin_libvpx', "Use the builtin libvpx library", True))
|
||||
opts.Add(BoolVariable('builtin_libwebp', "Use the builtin libwebp library", True))
|
||||
opts.Add(BoolVariable('builtin_openssl', "Use the builtin openssl library", True))
|
||||
opts.Add(BoolVariable('builtin_opus', "Use the builtin opus library", True))
|
||||
opts.Add(BoolVariable('builtin_pcre2', "Use the builtin pcre2 library)", True))
|
||||
opts.Add(BoolVariable('builtin_recast', "Use the builtin recast library", True))
|
||||
opts.Add(BoolVariable('builtin_squish', "Use the builtin squish library", True))
|
||||
opts.Add(BoolVariable('builtin_thekla_atlas', "Use the builtin thekla_altas library", True))
|
||||
opts.Add(BoolVariable('builtin_zlib', "Use the builtin zlib library", True))
|
||||
opts.Add(BoolVariable('builtin_zstd', "Use the builtin zstd library", True))
|
||||
opts.Add(BoolVariable('no_editor_splash', "Don't use the custom splash screen for the editor", False))
|
||||
opts.Add('builtin_freetype', "Use the builtin freetype library (yes/no)", 'yes')
|
||||
opts.Add('builtin_glew', "Use the builtin glew library (yes/no)", 'yes')
|
||||
opts.Add('builtin_libmpcdec', "Use the builtin libmpcdec library (yes/no)", 'yes')
|
||||
opts.Add('builtin_libogg', "Use the builtin libogg library (yes/no)", 'yes')
|
||||
opts.Add('builtin_libpng', "Use the builtin libpng library (yes/no)", 'yes')
|
||||
opts.Add('builtin_libtheora', "Use the builtin libtheora library (yes/no)", 'yes')
|
||||
opts.Add('builtin_libvorbis', "Use the builtin libvorbis library (yes/no)", 'yes')
|
||||
opts.Add('builtin_libwebp', "Use the builtin libwebp library (yes/no)", 'yes')
|
||||
opts.Add('builtin_openssl', "Use the builtin openssl library (yes/no)", 'yes')
|
||||
opts.Add('builtin_opus', "Use the builtin opus library (yes/no)", 'yes')
|
||||
# (akien) Unbundling would require work in audio_stream_speex.{cpp,h}, but since speex was
|
||||
# removed in 3.0+ and this is only to preserve compatibility in 2.1, I haven't worked on it.
|
||||
# Patches welcome if anyone cares :)
|
||||
opts.Add('builtin_speex', "Use the builtin speex library (yes/no)", 'yes')
|
||||
opts.Add('builtin_squish', "Use the builtin squish library (yes/no)", 'yes')
|
||||
opts.Add('builtin_zlib', "Use the builtin zlib library (yes/no)", 'yes')
|
||||
|
||||
# Compilation environment setup
|
||||
# Environment setup
|
||||
opts.Add("CXX", "C++ compiler")
|
||||
opts.Add("CC", "C compiler")
|
||||
opts.Add("LINK", "Linker")
|
||||
opts.Add("CCFLAGS", "Custom flags for both the C and C++ compilers")
|
||||
opts.Add("CXXFLAGS", "Custom flags for the C++ compiler")
|
||||
opts.Add("CCFLAGS", "Custom flags for the C and C++ compilers")
|
||||
opts.Add("CFLAGS", "Custom flags for the C compiler")
|
||||
opts.Add("LINKFLAGS", "Custom flags for the linker")
|
||||
|
||||
@ -209,40 +173,35 @@ opts.Add("LINKFLAGS", "Custom flags for the linker")
|
||||
for k in platform_opts.keys():
|
||||
opt_list = platform_opts[k]
|
||||
for o in opt_list:
|
||||
opts.Add(o)
|
||||
opts.Add(o[0], o[1], o[2])
|
||||
|
||||
for x in module_list:
|
||||
module_enabled = True
|
||||
tmppath = "./modules/" + x
|
||||
sys.path.insert(0, tmppath)
|
||||
import config
|
||||
enabled_attr = getattr(config, "is_enabled", None)
|
||||
if (callable(enabled_attr) and not config.is_enabled()):
|
||||
module_enabled = False
|
||||
sys.path.remove(tmppath)
|
||||
sys.modules.pop('config')
|
||||
opts.Add(BoolVariable('module_' + x + '_enabled', "Enable module '%s'" % (x, ), module_enabled))
|
||||
opts.Add('module_' + x + '_enabled', "Enable module '" + x + "' (yes/no)", "yes")
|
||||
|
||||
opts.Update(env_base) # update environment
|
||||
Help(opts.GenerateHelpText(env_base)) # generate help
|
||||
|
||||
# add default include paths
|
||||
|
||||
env_base.Append(CPPPATH=['#core', '#core/math', '#editor', '#drivers', '#'])
|
||||
env_base.Append(CPPPATH=['#core', '#core/math', '#tools', '#drivers', '#'])
|
||||
|
||||
# configure ENV for platform
|
||||
env_base.platform_exporters = platform_exporters
|
||||
env_base.platform_apis = platform_apis
|
||||
|
||||
"""
|
||||
sys.path.append("./platform/"+env_base["platform"])
|
||||
import detect
|
||||
detect.configure(env_base)
|
||||
sys.path.remove("./platform/"+env_base["platform"])
|
||||
sys.modules.pop('detect')
|
||||
"""
|
||||
|
||||
if (env_base['target'] == 'debug'):
|
||||
env_base.Append(CPPFLAGS=['-DDEBUG_MEMORY_ALLOC'])
|
||||
env_base.Append(CPPFLAGS=['-DSCI_NAMESPACE'])
|
||||
|
||||
if (env_base['no_editor_splash']):
|
||||
env_base.Append(CPPFLAGS=['-DNO_EDITOR_SPLASH'])
|
||||
|
||||
if not env_base['deprecated']:
|
||||
env_base.Append(CPPFLAGS=['-DDISABLE_DEPRECATED'])
|
||||
if (env_base['deprecated'] != 'no'):
|
||||
env_base.Append(CPPFLAGS=['-DENABLE_DEPRECATED'])
|
||||
|
||||
env_base.platforms = {}
|
||||
|
||||
@ -257,19 +216,15 @@ elif env_base['p'] != "":
|
||||
|
||||
|
||||
if selected_platform in platform_list:
|
||||
tmppath = "./platform/" + selected_platform
|
||||
sys.path.insert(0, tmppath)
|
||||
|
||||
sys.path.append("./platform/" + selected_platform)
|
||||
import detect
|
||||
if "create" in dir(detect):
|
||||
env = detect.create(env_base)
|
||||
else:
|
||||
env = env_base.Clone()
|
||||
|
||||
if env['dev']:
|
||||
env["warnings"] = "all"
|
||||
env['verbose'] = True
|
||||
|
||||
if env['vsproj']:
|
||||
if env['vsproj'] == "yes":
|
||||
env.vs_incs = []
|
||||
env.vs_srcs = []
|
||||
|
||||
@ -283,14 +238,9 @@ if selected_platform in platform_list:
|
||||
if len(pieces) > 0:
|
||||
basename = pieces[0]
|
||||
basename = basename.replace('\\\\', '/')
|
||||
if os.path.isfile(basename + ".h"):
|
||||
env.vs_incs = env.vs_incs + [basename + ".h"]
|
||||
elif os.path.isfile(basename + ".hpp"):
|
||||
env.vs_incs = env.vs_incs + [basename + ".hpp"]
|
||||
if os.path.isfile(basename + ".c"):
|
||||
env.vs_srcs = env.vs_srcs + [basename + ".c"]
|
||||
elif os.path.isfile(basename + ".cpp"):
|
||||
env.vs_srcs = env.vs_srcs + [basename + ".cpp"]
|
||||
env.vs_srcs = env.vs_srcs + [basename + ".cpp"]
|
||||
env.vs_incs = env.vs_incs + [basename + ".h"]
|
||||
# print basename
|
||||
env.AddToVSProject = AddToVSProject
|
||||
|
||||
env.extra_suffix = ""
|
||||
@ -301,17 +251,17 @@ if selected_platform in platform_list:
|
||||
CCFLAGS = env.get('CCFLAGS', '')
|
||||
env['CCFLAGS'] = ''
|
||||
|
||||
env.Append(CCFLAGS=str(CCFLAGS).split())
|
||||
env.Append(CCFLAGS=string.split(str(CCFLAGS)))
|
||||
|
||||
CFLAGS = env.get('CFLAGS', '')
|
||||
env['CFLAGS'] = ''
|
||||
|
||||
env.Append(CFLAGS=str(CFLAGS).split())
|
||||
env.Append(CFLAGS=string.split(str(CFLAGS)))
|
||||
|
||||
LINKFLAGS = env.get('LINKFLAGS', '')
|
||||
env['LINKFLAGS'] = ''
|
||||
|
||||
env.Append(LINKFLAGS=str(LINKFLAGS).split())
|
||||
env.Append(LINKFLAGS=string.split(str(LINKFLAGS)))
|
||||
|
||||
flag_list = platform_flags[selected_platform]
|
||||
for f in flag_list:
|
||||
@ -321,53 +271,25 @@ if selected_platform in platform_list:
|
||||
# must happen after the flags, so when flags are used by configure, stuff happens (ie, ssl on x11)
|
||||
detect.configure(env)
|
||||
|
||||
if (env["warnings"] == 'yes'):
|
||||
print("WARNING: warnings=yes is deprecated; assuming warnings=all")
|
||||
|
||||
env.msvc = 0
|
||||
if (os.name == "nt" and os.getenv("VCINSTALLDIR") and (platform_arg == "windows" or platform_arg == "uwp")): # MSVC, needs to stand out of course
|
||||
env.msvc = 1
|
||||
disable_nonessential_warnings = ['/wd4267', '/wd4244', '/wd4305', '/wd4800'] # Truncations, narrowing conversions...
|
||||
if (env["warnings"] == 'extra'):
|
||||
env.Append(CCFLAGS=['/Wall']) # Implies /W4
|
||||
elif (env["warnings"] == 'all' or env["warnings"] == 'yes'):
|
||||
env.Append(CCFLAGS=['/W3'] + disable_nonessential_warnings)
|
||||
elif (env["warnings"] == 'moderate'):
|
||||
# C4244 shouldn't be needed here being a level-3 warning, but it is
|
||||
env.Append(CCFLAGS=['/W2'] + disable_nonessential_warnings)
|
||||
else: # 'no'
|
||||
env.Append(CCFLAGS=['/w'])
|
||||
# Set exception handling model to avoid warnings caused by Windows system headers.
|
||||
env.Append(CCFLAGS=['/EHsc'])
|
||||
else: # Rest of the world
|
||||
if (env["warnings"] == 'extra'):
|
||||
env.Append(CCFLAGS=['-Wall', '-Wextra'])
|
||||
elif (env["warnings"] == 'all' or env["warnings"] == 'yes'):
|
||||
env.Append(CCFLAGS=['-Wall'])
|
||||
elif (env["warnings"] == 'moderate'):
|
||||
env.Append(CCFLAGS=['-Wall', '-Wno-unused'])
|
||||
else: # 'no'
|
||||
env.Append(CCFLAGS=['-w'])
|
||||
env.Append(CCFLAGS=['-Werror=return-type'])
|
||||
|
||||
#env['platform_libsuffix'] = env['LIBSUFFIX']
|
||||
|
||||
suffix = "." + selected_platform
|
||||
|
||||
if (env["target"] == "release"):
|
||||
if env["tools"]:
|
||||
if (env["tools"] == "yes"):
|
||||
print("Tools can only be built with targets 'debug' and 'release_debug'.")
|
||||
sys.exit(255)
|
||||
suffix += ".opt"
|
||||
|
||||
env.Append(CCFLAGS=['-DNDEBUG'])
|
||||
|
||||
elif (env["target"] == "release_debug"):
|
||||
if env["tools"]:
|
||||
if (env["tools"] == "yes"):
|
||||
suffix += ".opt.tools"
|
||||
else:
|
||||
suffix += ".opt.debug"
|
||||
else:
|
||||
if env["tools"]:
|
||||
if (env["tools"] == "yes"):
|
||||
suffix += ".tools"
|
||||
else:
|
||||
suffix += ".debug"
|
||||
@ -383,72 +305,53 @@ if selected_platform in platform_list:
|
||||
|
||||
suffix += env.extra_suffix
|
||||
|
||||
sys.path.remove(tmppath)
|
||||
env["PROGSUFFIX"] = suffix + env["PROGSUFFIX"]
|
||||
env["OBJSUFFIX"] = suffix + env["OBJSUFFIX"]
|
||||
env["LIBSUFFIX"] = suffix + env["LIBSUFFIX"]
|
||||
env["SHLIBSUFFIX"] = suffix + env["SHLIBSUFFIX"]
|
||||
|
||||
sys.path.remove("./platform/" + selected_platform)
|
||||
sys.modules.pop('detect')
|
||||
|
||||
env.module_list = []
|
||||
env.doc_class_path = {}
|
||||
|
||||
for x in module_list:
|
||||
if not env['module_' + x + '_enabled']:
|
||||
if env['module_' + x + '_enabled'] != "yes":
|
||||
continue
|
||||
tmppath = "./modules/" + x
|
||||
sys.path.insert(0, tmppath)
|
||||
sys.path.append(tmppath)
|
||||
env.current_module = x
|
||||
import config
|
||||
if (config.can_build(selected_platform)):
|
||||
config.configure(env)
|
||||
env.module_list.append(x)
|
||||
try:
|
||||
doc_classes = config.get_doc_classes()
|
||||
doc_path = config.get_doc_path()
|
||||
for c in doc_classes:
|
||||
env.doc_class_path[c] = "modules/" + x + "/" + doc_path
|
||||
except:
|
||||
pass
|
||||
|
||||
sys.path.remove(tmppath)
|
||||
sys.modules.pop('config')
|
||||
|
||||
methods.update_version(env.module_version_string)
|
||||
|
||||
env["PROGSUFFIX"] = suffix + env.module_version_string + env["PROGSUFFIX"]
|
||||
env["OBJSUFFIX"] = suffix + env["OBJSUFFIX"]
|
||||
env["LIBSUFFIX"] = suffix + env["LIBSUFFIX"]
|
||||
env["SHLIBSUFFIX"] = suffix + env["SHLIBSUFFIX"]
|
||||
|
||||
if (env.use_ptrcall):
|
||||
env.Append(CPPFLAGS=['-DPTRCALL_ENABLED'])
|
||||
|
||||
# to test 64 bits compiltion
|
||||
# env.Append(CPPFLAGS=['-m64'])
|
||||
|
||||
if env['tools']:
|
||||
if (env['tools'] == 'yes'):
|
||||
env.Append(CPPFLAGS=['-DTOOLS_ENABLED'])
|
||||
if env['disable_3d']:
|
||||
if (env['disable_3d'] == 'yes'):
|
||||
env.Append(CPPFLAGS=['-D_3D_DISABLED'])
|
||||
if env['gdscript']:
|
||||
if (env['gdscript'] == 'yes'):
|
||||
env.Append(CPPFLAGS=['-DGDSCRIPT_ENABLED'])
|
||||
if env['disable_advanced_gui']:
|
||||
if (env['disable_advanced_gui'] == 'yes'):
|
||||
env.Append(CPPFLAGS=['-DADVANCED_GUI_DISABLED'])
|
||||
|
||||
if env['minizip']:
|
||||
if (env['minizip'] == 'yes'):
|
||||
env.Append(CPPFLAGS=['-DMINIZIP_ENABLED'])
|
||||
|
||||
if env['xml']:
|
||||
if (env['xml'] == 'yes'):
|
||||
env.Append(CPPFLAGS=['-DXML_ENABLED'])
|
||||
|
||||
if not env['verbose']:
|
||||
if (env['verbose'] == 'no'):
|
||||
methods.no_verbose(sys, env)
|
||||
|
||||
if (not env["platform"] == "server"): # FIXME: detect GLES3
|
||||
env.Append( BUILDERS = { 'GLES3_GLSL' : env.Builder(action = methods.build_gles3_headers, suffix = 'glsl.gen.h',src_suffix = '.glsl') } )
|
||||
|
||||
scons_cache_path = os.environ.get("SCONS_CACHE")
|
||||
if scons_cache_path != None:
|
||||
CacheDir(scons_cache_path)
|
||||
print("Scons cache enabled... (path: '" + scons_cache_path + "')")
|
||||
|
||||
Export('env')
|
||||
|
||||
# build subdirs, the build order is dependent on link order.
|
||||
@ -456,30 +359,54 @@ if selected_platform in platform_list:
|
||||
SConscript("core/SCsub")
|
||||
SConscript("servers/SCsub")
|
||||
SConscript("scene/SCsub")
|
||||
SConscript("editor/SCsub")
|
||||
SConscript("tools/SCsub")
|
||||
SConscript("drivers/SCsub")
|
||||
|
||||
SConscript("platform/SCsub")
|
||||
SConscript("modules/SCsub")
|
||||
SConscript("main/SCsub")
|
||||
|
||||
SConscript("platform/" + selected_platform + "/SCsub") # build selected platform
|
||||
|
||||
# Microsoft Visual Studio Project Generation
|
||||
if env['vsproj']:
|
||||
env['CPPPATH'] = [Dir(path) for path in env['CPPPATH']]
|
||||
methods.generate_vs_project(env, GetOption("num_jobs"))
|
||||
methods.generate_cpp_hint_file("cpp.hint")
|
||||
if (env['vsproj']) == "yes":
|
||||
|
||||
# Check for the existence of headers
|
||||
conf = Configure(env)
|
||||
if ("check_c_headers" in env):
|
||||
for header in env["check_c_headers"]:
|
||||
if (conf.CheckCHeader(header[0])):
|
||||
if (env.msvc):
|
||||
env.Append(CCFLAGS=['/D' + header[1]])
|
||||
else:
|
||||
env.Append(CCFLAGS=['-D' + header[1]])
|
||||
AddToVSProject(env.core_sources)
|
||||
AddToVSProject(env.main_sources)
|
||||
AddToVSProject(env.modules_sources)
|
||||
AddToVSProject(env.scene_sources)
|
||||
AddToVSProject(env.servers_sources)
|
||||
AddToVSProject(env.tool_sources)
|
||||
|
||||
# this env flag won't work, it needs to be set in env_base=Environment(MSVC_VERSION='9.0')
|
||||
# Even then, SCons still seems to ignore it and builds with the latest MSVC...
|
||||
# That said, it's not needed to be set so far but I'm leaving it here so that this comment
|
||||
# has a purpose.
|
||||
# env['MSVS_VERSION']='9.0'
|
||||
|
||||
# Calls a CMD with /C(lose) and /V(delayed environment variable expansion) options.
|
||||
# And runs vcvarsall bat for the propper arhitecture and scons for propper configuration
|
||||
env['MSVSBUILDCOM'] = 'cmd /V /C set "plat=$(PlatformTarget)" ^& (if "$(PlatformTarget)"=="x64" (set "plat=x86_amd64")) ^& set "tools=yes" ^& (if "$(Configuration)"=="release" (set "tools=no")) ^& call "$(VCInstallDir)vcvarsall.bat" !plat! ^& scons platform=windows target=$(Configuration) tools=!tools! -j2'
|
||||
env['MSVSREBUILDCOM'] = 'cmd /V /C set "plat=$(PlatformTarget)" ^& (if "$(PlatformTarget)"=="x64" (set "plat=x86_amd64")) ^& set "tools=yes" ^& (if "$(Configuration)"=="release" (set "tools=no")) & call "$(VCInstallDir)vcvarsall.bat" !plat! ^& scons platform=windows target=$(Configuration) tools=!tools! vsproj=yes -j2'
|
||||
env['MSVSCLEANCOM'] = 'cmd /V /C set "plat=$(PlatformTarget)" ^& (if "$(PlatformTarget)"=="x64" (set "plat=x86_amd64")) ^& set "tools=yes" ^& (if "$(Configuration)"=="release" (set "tools=no")) ^& call "$(VCInstallDir)vcvarsall.bat" !plat! ^& scons --clean platform=windows target=$(Configuration) tools=!tools! -j2'
|
||||
|
||||
# This version information (Win32, x64, Debug, Release, Release_Debug seems to be
|
||||
# required for Visual Studio to understand that it needs to generate an NMAKE
|
||||
# project. Do not modify without knowing what you are doing.
|
||||
debug_variants = ['debug|Win32'] + ['debug|x64']
|
||||
release_variants = ['release|Win32'] + ['release|x64']
|
||||
release_debug_variants = ['release_debug|Win32'] + ['release_debug|x64']
|
||||
variants = debug_variants + release_variants + release_debug_variants
|
||||
debug_targets = ['bin\\godot.windows.tools.32.exe'] + ['bin\\godot.windows.tools.64.exe']
|
||||
release_targets = ['bin\\godot.windows.opt.32.exe'] + ['bin\\godot.windows.opt.64.exe']
|
||||
release_debug_targets = ['bin\\godot.windows.opt.tools.32.exe'] + ['bin\\godot.windows.opt.tools.64.exe']
|
||||
targets = debug_targets + release_targets + release_debug_targets
|
||||
msvproj = env.MSVSProject(target=['#godot' + env['MSVSPROJECTSUFFIX']],
|
||||
incs=env.vs_incs,
|
||||
srcs=env.vs_srcs,
|
||||
runfile=targets,
|
||||
buildtarget=targets,
|
||||
auto_build_solution=1,
|
||||
variant=variants)
|
||||
|
||||
else:
|
||||
|
||||
@ -488,120 +415,3 @@ else:
|
||||
for x in platform_list:
|
||||
print("\t" + x)
|
||||
print("\nPlease run scons again with argument: platform=<string>")
|
||||
|
||||
|
||||
# The following only makes sense when the env is defined, and assumes it is
|
||||
if 'env' in locals():
|
||||
screen = sys.stdout
|
||||
# Progress reporting is not available in non-TTY environments since it
|
||||
# messes with the output (for example, when writing to a file)
|
||||
show_progress = (env['progress'] and sys.stdout.isatty())
|
||||
node_count = 0
|
||||
node_count_max = 0
|
||||
node_count_interval = 1
|
||||
node_count_fname = str(env.Dir('#')) + '/.scons_node_count'
|
||||
|
||||
import time, math
|
||||
|
||||
class cache_progress:
|
||||
# The default is 1 GB cache and 12 hours half life
|
||||
def __init__(self, path = None, limit = 1073741824, half_life = 43200):
|
||||
self.path = path
|
||||
self.limit = limit
|
||||
self.exponent_scale = math.log(2) / half_life
|
||||
if env['verbose'] and path != None:
|
||||
screen.write('Current cache limit is ' + self.convert_size(limit) + ' (used: ' + self.convert_size(self.get_size(path)) + ')\n')
|
||||
self.delete(self.file_list())
|
||||
|
||||
def __call__(self, node, *args, **kw):
|
||||
global node_count, node_count_max, node_count_interval, node_count_fname, show_progress
|
||||
if show_progress:
|
||||
# Print the progress percentage
|
||||
node_count += node_count_interval
|
||||
if (node_count_max > 0 and node_count <= node_count_max):
|
||||
screen.write('\r[%3d%%] ' % (node_count * 100 / node_count_max))
|
||||
screen.flush()
|
||||
elif (node_count_max > 0 and node_count > node_count_max):
|
||||
screen.write('\r[100%] ')
|
||||
screen.flush()
|
||||
else:
|
||||
screen.write('\r[Initial build] ')
|
||||
screen.flush()
|
||||
|
||||
def delete(self, files):
|
||||
if len(files) == 0:
|
||||
return
|
||||
if env['verbose']:
|
||||
# Utter something
|
||||
screen.write('\rPurging %d %s from cache...\n' % (len(files), len(files) > 1 and 'files' or 'file'))
|
||||
[os.remove(f) for f in files]
|
||||
|
||||
def file_list(self):
|
||||
if self.path == None:
|
||||
# Nothing to do
|
||||
return []
|
||||
# Gather a list of (filename, (size, atime)) within the
|
||||
# cache directory
|
||||
file_stat = [(x, os.stat(x)[6:8]) for x in glob.glob(os.path.join(self.path, '*', '*'))]
|
||||
if file_stat == []:
|
||||
# Nothing to do
|
||||
return []
|
||||
# Weight the cache files by size (assumed to be roughly
|
||||
# proportional to the recompilation time) times an exponential
|
||||
# decay since the ctime, and return a list with the entries
|
||||
# (filename, size, weight).
|
||||
current_time = time.time()
|
||||
file_stat = [(x[0], x[1][0], (current_time - x[1][1])) for x in file_stat]
|
||||
# Sort by the most resently accessed files (most sensible to keep) first
|
||||
file_stat.sort(key=lambda x: x[2])
|
||||
# Search for the first entry where the storage limit is
|
||||
# reached
|
||||
sum, mark = 0, None
|
||||
for i,x in enumerate(file_stat):
|
||||
sum += x[1]
|
||||
if sum > self.limit:
|
||||
mark = i
|
||||
break
|
||||
if mark == None:
|
||||
return []
|
||||
else:
|
||||
return [x[0] for x in file_stat[mark:]]
|
||||
|
||||
def convert_size(self, size_bytes):
|
||||
if size_bytes == 0:
|
||||
return "0 bytes"
|
||||
size_name = ("bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
|
||||
i = int(math.floor(math.log(size_bytes, 1024)))
|
||||
p = math.pow(1024, i)
|
||||
s = round(size_bytes / p, 2)
|
||||
return "%s %s" % (int(s) if i == 0 else s, size_name[i])
|
||||
|
||||
def get_size(self, start_path = '.'):
|
||||
total_size = 0
|
||||
for dirpath, dirnames, filenames in os.walk(start_path):
|
||||
for f in filenames:
|
||||
fp = os.path.join(dirpath, f)
|
||||
total_size += os.path.getsize(fp)
|
||||
return total_size
|
||||
|
||||
def progress_finish(target, source, env):
|
||||
global node_count, progressor
|
||||
with open(node_count_fname, 'w') as f:
|
||||
f.write('%d\n' % node_count)
|
||||
progressor.delete(progressor.file_list())
|
||||
|
||||
try:
|
||||
with open(node_count_fname) as f:
|
||||
node_count_max = int(f.readline())
|
||||
except:
|
||||
pass
|
||||
|
||||
cache_directory = os.environ.get("SCONS_CACHE")
|
||||
# Simple cache pruning, attached to SCons' progress callback. Trim the
|
||||
# cache directory to a size not larger than cache_limit.
|
||||
cache_limit = float(os.getenv("SCONS_CACHE_LIMIT", 1024)) * 1024 * 1024
|
||||
progressor = cache_progress(cache_directory, cache_limit)
|
||||
Progress(progressor, interval = node_count_interval)
|
||||
|
||||
progress_finish_command = Command('progress_finish', [], progress_finish)
|
||||
AlwaysBuild(progress_finish_command)
|
||||
|
||||
64
compat.py
64
compat.py
@ -1,64 +0,0 @@
|
||||
import sys
|
||||
|
||||
if sys.version_info < (3,):
|
||||
def isbasestring(s):
|
||||
return isinstance(s, basestring)
|
||||
def open_utf8(filename, mode):
|
||||
return open(filename, mode)
|
||||
def byte_to_str(x):
|
||||
return str(ord(x))
|
||||
import cStringIO
|
||||
def StringIO():
|
||||
return cStringIO.StringIO()
|
||||
def encode_utf8(x):
|
||||
return x
|
||||
def decode_utf8(x):
|
||||
return x
|
||||
def iteritems(d):
|
||||
return d.iteritems()
|
||||
def escape_string(s):
|
||||
if isinstance(s, unicode):
|
||||
s = s.encode('ascii')
|
||||
result = ''
|
||||
for c in s:
|
||||
if not (32 <= ord(c) < 127) or c in ('\\', '"'):
|
||||
result += '\\%03o' % ord(c)
|
||||
else:
|
||||
result += c
|
||||
return result
|
||||
|
||||
else:
|
||||
def isbasestring(s):
|
||||
return isinstance(s, (str, bytes))
|
||||
def open_utf8(filename, mode):
|
||||
return open(filename, mode, encoding="utf-8")
|
||||
def byte_to_str(x):
|
||||
return str(x)
|
||||
import io
|
||||
def StringIO():
|
||||
return io.StringIO()
|
||||
import codecs
|
||||
def encode_utf8(x):
|
||||
return codecs.utf_8_encode(x)[0]
|
||||
def decode_utf8(x):
|
||||
return codecs.utf_8_decode(x)[0]
|
||||
def iteritems(d):
|
||||
return iter(d.items())
|
||||
def charcode_to_c_escapes(c):
|
||||
rev_result = []
|
||||
while c >= 256:
|
||||
c, low = (c // 256, c % 256)
|
||||
rev_result.append('\\%03o' % low)
|
||||
rev_result.append('\\%03o' % c)
|
||||
return ''.join(reversed(rev_result))
|
||||
def escape_string(s):
|
||||
result = ''
|
||||
if isinstance(s, str):
|
||||
s = s.encode('utf-8')
|
||||
for c in s:
|
||||
if not(32 <= c < 127) or c in (ord('\\'), ord('"')):
|
||||
result += charcode_to_c_escapes(c)
|
||||
else:
|
||||
result += chr(c)
|
||||
return result
|
||||
|
||||
61
core/SCsub
61
core/SCsub
@ -5,7 +5,6 @@ Import('env')
|
||||
env.core_sources = []
|
||||
|
||||
|
||||
# Generate global defaults
|
||||
gd_call = ""
|
||||
gd_inc = ""
|
||||
|
||||
@ -14,16 +13,14 @@ for x in env.global_defaults:
|
||||
gd_inc += '#include "platform/' + x + '/globals/global_defaults.h"\n'
|
||||
gd_call += "\tregister_" + x + "_global_defaults();\n"
|
||||
|
||||
gd_cpp = '#include "project_settings.h"\n'
|
||||
gd_cpp = '#include "globals.h"\n'
|
||||
gd_cpp += gd_inc
|
||||
gd_cpp += "void ProjectSettings::register_global_defaults() {\n" + gd_call + "\n}\n"
|
||||
gd_cpp += "void Globals::register_global_defaults() {\n" + gd_call + "\n}\n"
|
||||
|
||||
f = open("global_defaults.gen.cpp", "w")
|
||||
f = open("global_defaults.cpp", "wb")
|
||||
f.write(gd_cpp)
|
||||
f.close()
|
||||
|
||||
|
||||
# Generate AES256 script encryption key
|
||||
import os
|
||||
txt = "0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0"
|
||||
if ("SCRIPT_AES256_ENCRYPTION_KEY" in os.environ):
|
||||
@ -47,64 +44,24 @@ if ("SCRIPT_AES256_ENCRYPTION_KEY" in os.environ):
|
||||
txt = "0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0"
|
||||
print("Invalid AES256 encryption key, not 64 bits hex: " + e)
|
||||
|
||||
f = open("script_encryption_key.gen.cpp", "w")
|
||||
f.write("#include \"project_settings.h\"\nuint8_t script_encryption_key[32]={" + txt + "};\n")
|
||||
f = open("script_encryption_key.cpp", "wb")
|
||||
f.write("#include \"globals.h\"\nuint8_t script_encryption_key[32]={" + txt + "};\n")
|
||||
f.close()
|
||||
|
||||
|
||||
# Add required thirdparty code. Header paths are hardcoded, we don't need to append
|
||||
# to the include path (saves a few chars on the compiler invocation for touchy MSVC...)
|
||||
thirdparty_dir = "#thirdparty/misc/"
|
||||
thirdparty_sources = [
|
||||
# C sources
|
||||
"base64.c",
|
||||
"fastlz.c",
|
||||
"sha256.c",
|
||||
"smaz.c",
|
||||
|
||||
# C++ sources
|
||||
"aes256.cpp",
|
||||
"hq2x.cpp",
|
||||
"md5.cpp",
|
||||
"pcg.cpp",
|
||||
"triangulator.cpp",
|
||||
]
|
||||
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
|
||||
env.add_source_files(env.core_sources, thirdparty_sources)
|
||||
|
||||
# Minizip library, can be unbundled in theory
|
||||
# However, our version has some custom modifications, so it won't compile with the system one
|
||||
thirdparty_minizip_dir = "#thirdparty/minizip/"
|
||||
thirdparty_minizip_sources = [
|
||||
"ioapi.c",
|
||||
"unzip.c",
|
||||
"zip.c",
|
||||
]
|
||||
thirdparty_minizip_sources = [thirdparty_minizip_dir + file for file in thirdparty_minizip_sources]
|
||||
env.add_source_files(env.core_sources, thirdparty_minizip_sources)
|
||||
|
||||
if 'builtin_zstd' in env and env['builtin_zstd']:
|
||||
SConscript("#thirdparty/zstd/SCsub")
|
||||
|
||||
|
||||
# Godot's own sources
|
||||
env.add_source_files(env.core_sources, "*.cpp")
|
||||
|
||||
|
||||
# Make binders
|
||||
Export('env')
|
||||
|
||||
import make_binders
|
||||
env.CommandNoCache(['method_bind.gen.inc', 'method_bind_ext.gen.inc'], 'make_binders.py', make_binders.run)
|
||||
env.Command(['method_bind.inc', 'method_bind_ext.inc'], 'make_binders.py', make_binders.run)
|
||||
|
||||
|
||||
# Chain load SCsubs
|
||||
SConscript('os/SCsub')
|
||||
SConscript('math/SCsub')
|
||||
SConscript('io/SCsub')
|
||||
SConscript('bind/SCsub')
|
||||
SConscript('helper/SCsub')
|
||||
|
||||
lib = env.Library("core", env.core_sources)
|
||||
|
||||
# Build it all as a library
|
||||
lib = env.add_library("core", env.core_sources)
|
||||
env.Prepend(LIBS=[lib])
|
||||
Export('env')
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,18 +26,17 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef ALLOCATORS_H
|
||||
#define ALLOCATORS_H
|
||||
|
||||
#include "os/memory.h"
|
||||
template <int PREALLOC_COUNT = 64, int MAX_HANDS = 8>
|
||||
template<int PREALLOC_COUNT=64, int MAX_HANDS=8>
|
||||
class BalloonAllocator {
|
||||
|
||||
enum {
|
||||
|
||||
USED_FLAG = (1 << 30),
|
||||
USED_MASK = USED_FLAG - 1
|
||||
USED_FLAG=(1<<30),
|
||||
USED_MASK=USED_FLAG-1
|
||||
};
|
||||
|
||||
struct Balloon {
|
||||
@ -48,6 +46,7 @@ class BalloonAllocator {
|
||||
uint32_t hand;
|
||||
};
|
||||
|
||||
|
||||
struct Hand {
|
||||
|
||||
int used;
|
||||
@ -56,132 +55,136 @@ class BalloonAllocator {
|
||||
Balloon *last;
|
||||
};
|
||||
|
||||
|
||||
Hand hands[MAX_HANDS];
|
||||
|
||||
|
||||
|
||||
public:
|
||||
void *alloc(size_t p_size) {
|
||||
|
||||
size_t max = (1 << MAX_HANDS);
|
||||
ERR_FAIL_COND_V(p_size > max, NULL);
|
||||
void* alloc(size_t p_size) {
|
||||
|
||||
unsigned int hand = 0;
|
||||
size_t max=(1<<MAX_HANDS);
|
||||
ERR_FAIL_COND_V( p_size>max, NULL );
|
||||
|
||||
while (p_size > (size_t)(1 << hand))
|
||||
++hand;
|
||||
unsigned int hand=0;
|
||||
|
||||
Hand &h = hands[hand];
|
||||
while(p_size>(size_t)(1<<hand)) ++hand;
|
||||
|
||||
if (h.used == h.allocated) {
|
||||
Hand &h=hands[hand];
|
||||
|
||||
for (int i = 0; i < PREALLOC_COUNT; i++) {
|
||||
if (h.used==h.allocated) {
|
||||
|
||||
Balloon *b = (Balloon *)memalloc(sizeof(Balloon) + (1 << hand));
|
||||
b->hand = hand;
|
||||
for(int i=0;i<PREALLOC_COUNT;i++) {
|
||||
|
||||
Balloon *b = (Balloon*)memalloc(sizeof(Balloon)+(1<<hand));
|
||||
b->hand=hand;
|
||||
if (h.last) {
|
||||
|
||||
b->prev = h.last;
|
||||
h.last->next = b;
|
||||
h.last = b;
|
||||
b->prev=h.last;
|
||||
h.last->next=b;
|
||||
h.last=b;
|
||||
} else {
|
||||
|
||||
b->prev = NULL;
|
||||
h.last = b;
|
||||
h.first = b;
|
||||
b->prev=NULL;
|
||||
h.last=b;
|
||||
h.first=b;
|
||||
}
|
||||
}
|
||||
|
||||
h.last->next = NULL;
|
||||
h.allocated += PREALLOC_COUNT;
|
||||
h.last->next=NULL;
|
||||
h.allocated+=PREALLOC_COUNT;
|
||||
}
|
||||
|
||||
Balloon *pick = h.last;
|
||||
Balloon *pick=h.last;
|
||||
|
||||
ERR_FAIL_COND_V((pick->hand & USED_FLAG), NULL);
|
||||
ERR_FAIL_COND_V( (pick->hand&USED_FLAG), NULL );
|
||||
|
||||
// remove last
|
||||
h.last = h.last->prev;
|
||||
h.last->next = NULL;
|
||||
h.last=h.last->prev;
|
||||
h.last->next=NULL;
|
||||
|
||||
pick->next = h.first;
|
||||
h.first->prev = pick;
|
||||
pick->prev = NULL;
|
||||
h.first = pick;
|
||||
pick->next=h.first;
|
||||
h.first->prev=pick;
|
||||
pick->prev=NULL;
|
||||
h.first=pick;
|
||||
h.used++;
|
||||
pick->hand |= USED_FLAG;
|
||||
pick->hand|=USED_FLAG;
|
||||
|
||||
return (void *)(pick + 1);
|
||||
return (void*)(pick+1);
|
||||
}
|
||||
|
||||
void free(void *p_ptr) {
|
||||
void free(void* p_ptr) {
|
||||
|
||||
Balloon *b = (Balloon *)p_ptr;
|
||||
b -= 1;
|
||||
Balloon *b=(Balloon*)p_ptr;
|
||||
b-=1;
|
||||
|
||||
ERR_FAIL_COND(!(b->hand & USED_FLAG));
|
||||
ERR_FAIL_COND(!(b->hand&USED_FLAG) );
|
||||
|
||||
b->hand = b->hand & USED_MASK; // not used
|
||||
int hand = b->hand;
|
||||
b->hand=b->hand&USED_MASK; // not used
|
||||
int hand=b->hand;
|
||||
|
||||
Hand &h = hands[hand];
|
||||
Hand &h=hands[hand];
|
||||
|
||||
if (b == h.first)
|
||||
h.first = b->next;
|
||||
if (b==h.first)
|
||||
h.first=b->next;
|
||||
|
||||
if (b->prev)
|
||||
b->prev->next = b->next;
|
||||
b->prev->next=b->next;
|
||||
if (b->next)
|
||||
b->next->prev = b->prev;
|
||||
b->next->prev=b->prev;
|
||||
|
||||
if (h.last != b) {
|
||||
h.last->next = b;
|
||||
b->prev = h.last;
|
||||
b->next = NULL;
|
||||
h.last = b;
|
||||
if (h.last!=b) {
|
||||
h.last->next=b;
|
||||
b->prev=h.last;
|
||||
b->next=NULL;
|
||||
h.last=b;
|
||||
}
|
||||
|
||||
h.used--;
|
||||
|
||||
if (h.used <= (h.allocated - (PREALLOC_COUNT * 2))) { // this is done to ensure no alloc/free is done constantly
|
||||
if (h.used<=(h.allocated-(PREALLOC_COUNT*2))) { // this is done to ensure no alloc/free is done constantly
|
||||
|
||||
for (int i = 0; i < PREALLOC_COUNT; i++) {
|
||||
ERR_CONTINUE(h.last->hand & USED_FLAG);
|
||||
for(int i=0;i<PREALLOC_COUNT;i++) {
|
||||
ERR_CONTINUE( h.last->hand& USED_FLAG );
|
||||
|
||||
Balloon *new_last = h.last->prev;
|
||||
Balloon *new_last=h.last->prev;
|
||||
if (new_last)
|
||||
new_last->next = NULL;
|
||||
memfree(h.last);
|
||||
h.last = new_last;
|
||||
new_last->next=NULL;
|
||||
memfree( h.last );
|
||||
h.last=new_last;
|
||||
}
|
||||
h.allocated -= PREALLOC_COUNT;
|
||||
h.allocated-=PREALLOC_COUNT;
|
||||
}
|
||||
}
|
||||
|
||||
BalloonAllocator() {
|
||||
|
||||
for (int i = 0; i < MAX_HANDS; i++) {
|
||||
for(int i=0;i<MAX_HANDS;i++) {
|
||||
|
||||
hands[i].allocated = 0;
|
||||
hands[i].used = 0;
|
||||
hands[i].first = NULL;
|
||||
hands[i].last = NULL;
|
||||
hands[i].allocated=0;
|
||||
hands[i].used=0;
|
||||
hands[i].first=NULL;
|
||||
hands[i].last=NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void clear() {
|
||||
|
||||
for (int i = 0; i < MAX_HANDS; i++) {
|
||||
for(int i=0;i<MAX_HANDS;i++) {
|
||||
|
||||
while (hands[i].first) {
|
||||
while(hands[i].first) {
|
||||
|
||||
Balloon *b = hands[i].first;
|
||||
hands[i].first = b->next;
|
||||
Balloon *b=hands[i].first;
|
||||
hands[i].first=b->next;
|
||||
memfree(b);
|
||||
}
|
||||
|
||||
hands[i].allocated = 0;
|
||||
hands[i].used = 0;
|
||||
hands[i].first = NULL;
|
||||
hands[i].last = NULL;
|
||||
hands[i].allocated=0;
|
||||
hands[i].used=0;
|
||||
hands[i].first=NULL;
|
||||
hands[i].last=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,4 +194,5 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // ALLOCATORS_H
|
||||
|
||||
231
core/array.cpp
231
core/array.cpp
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,36 +26,48 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "array.h"
|
||||
|
||||
#include "hashfuncs.h"
|
||||
#include "object.h"
|
||||
#include "variant.h"
|
||||
#include "vector.h"
|
||||
#include "hashfuncs.h"
|
||||
#include "variant.h"
|
||||
#include "object.h"
|
||||
|
||||
struct ArrayPrivate {
|
||||
|
||||
SafeRefCount refcount;
|
||||
Vector<Variant> array;
|
||||
bool shared;
|
||||
};
|
||||
|
||||
void Array::_ref(const Array &p_from) const {
|
||||
void Array::_ref(const Array& p_from) const {
|
||||
|
||||
ArrayPrivate *_fp = p_from._p;
|
||||
|
||||
ERR_FAIL_COND(!_fp); // should NOT happen.
|
||||
|
||||
if (_fp == _p)
|
||||
return; // whatever it is, nothing to do here move along
|
||||
return; //wathever it is, nothing to do here move along
|
||||
|
||||
bool success = _fp->refcount.ref();
|
||||
|
||||
ERR_FAIL_COND(!success); // should really not happen either
|
||||
ERR_FAIL_COND(!success); //should really not happen either
|
||||
|
||||
_unref();
|
||||
|
||||
_p = p_from._p;
|
||||
if (_fp->shared) {
|
||||
|
||||
_p = p_from._p;
|
||||
|
||||
} else {
|
||||
|
||||
_p = memnew( ArrayPrivate );
|
||||
_p->shared=false;
|
||||
_p->refcount.init();
|
||||
_p->array=_fp->array;
|
||||
|
||||
if (_fp->refcount.unref())
|
||||
memdelete(_fp);
|
||||
}
|
||||
}
|
||||
|
||||
void Array::_unref() const {
|
||||
@ -67,17 +78,19 @@ void Array::_unref() const {
|
||||
if (_p->refcount.unref()) {
|
||||
memdelete(_p);
|
||||
}
|
||||
_p = NULL;
|
||||
_p=NULL;
|
||||
}
|
||||
|
||||
Variant &Array::operator[](int p_idx) {
|
||||
|
||||
Variant& Array::operator[](int p_idx) {
|
||||
|
||||
return _p->array[p_idx];
|
||||
}
|
||||
|
||||
const Variant &Array::operator[](int p_idx) const {
|
||||
const Variant& Array::operator[](int p_idx) const {
|
||||
|
||||
return _p->array[p_idx];
|
||||
|
||||
}
|
||||
|
||||
int Array::size() const {
|
||||
@ -93,26 +106,31 @@ void Array::clear() {
|
||||
_p->array.clear();
|
||||
}
|
||||
|
||||
bool Array::operator==(const Array &p_array) const {
|
||||
bool Array::is_shared() const {
|
||||
|
||||
return _p == p_array._p;
|
||||
return _p->shared;
|
||||
}
|
||||
|
||||
bool Array::operator==(const Array& p_array) const {
|
||||
|
||||
return _p==p_array._p;
|
||||
}
|
||||
|
||||
uint32_t Array::hash() const {
|
||||
|
||||
uint32_t h = hash_djb2_one_32(0);
|
||||
uint32_t h=hash_djb2_one_32(0);
|
||||
|
||||
for (int i = 0; i < _p->array.size(); i++) {
|
||||
for (int i=0;i<_p->array.size();i++) {
|
||||
|
||||
h = hash_djb2_one_32(_p->array[i].hash(), h);
|
||||
h = hash_djb2_one_32( _p->array[i].hash(), h);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
void Array::operator=(const Array &p_array) {
|
||||
void Array::operator=(const Array& p_array) {
|
||||
|
||||
_ref(p_array);
|
||||
}
|
||||
void Array::push_back(const Variant &p_value) {
|
||||
void Array::push_back(const Variant& p_value) {
|
||||
|
||||
_p->array.push_back(p_value);
|
||||
}
|
||||
@ -122,12 +140,12 @@ Error Array::resize(int p_new_size) {
|
||||
return _p->array.resize(p_new_size);
|
||||
}
|
||||
|
||||
void Array::insert(int p_pos, const Variant &p_value) {
|
||||
void Array::insert(int p_pos, const Variant& p_value) {
|
||||
|
||||
_p->array.insert(p_pos, p_value);
|
||||
_p->array.insert(p_pos,p_value);
|
||||
}
|
||||
|
||||
void Array::erase(const Variant &p_value) {
|
||||
void Array::erase(const Variant& p_value) {
|
||||
|
||||
_p->array.erase(p_value);
|
||||
}
|
||||
@ -142,12 +160,12 @@ Variant Array::back() const {
|
||||
return operator[](_p->array.size() - 1);
|
||||
}
|
||||
|
||||
int Array::find(const Variant &p_value, int p_from) const {
|
||||
int Array::find(const Variant& p_value, int p_from) const {
|
||||
|
||||
return _p->array.find(p_value, p_from);
|
||||
}
|
||||
|
||||
int Array::rfind(const Variant &p_value, int p_from) const {
|
||||
int Array::rfind(const Variant& p_value, int p_from) const {
|
||||
|
||||
if (_p->array.size() == 0)
|
||||
return -1;
|
||||
@ -161,9 +179,9 @@ int Array::rfind(const Variant &p_value, int p_from) const {
|
||||
p_from = _p->array.size() - 1;
|
||||
}
|
||||
|
||||
for (int i = p_from; i >= 0; i--) {
|
||||
for (int i=p_from; i>=0; i--) {
|
||||
|
||||
if (_p->array[i] == p_value) {
|
||||
if(_p->array[i] == p_value){
|
||||
return i;
|
||||
};
|
||||
};
|
||||
@ -171,20 +189,20 @@ int Array::rfind(const Variant &p_value, int p_from) const {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Array::find_last(const Variant &p_value) const {
|
||||
int Array::find_last(const Variant& p_value) const {
|
||||
|
||||
return rfind(p_value);
|
||||
}
|
||||
|
||||
int Array::count(const Variant &p_value) const {
|
||||
int Array::count(const Variant& p_value) const {
|
||||
|
||||
if (_p->array.size() == 0)
|
||||
if(_p->array.size() == 0)
|
||||
return 0;
|
||||
|
||||
int amount = 0;
|
||||
for (int i = 0; i < _p->array.size(); i++) {
|
||||
int amount=0;
|
||||
for (int i=0; i<_p->array.size(); i++) {
|
||||
|
||||
if (_p->array[i] == p_value) {
|
||||
if(_p->array[i] == p_value){
|
||||
amount++;
|
||||
};
|
||||
};
|
||||
@ -192,7 +210,7 @@ int Array::count(const Variant &p_value) const {
|
||||
return amount;
|
||||
}
|
||||
|
||||
bool Array::has(const Variant &p_value) const {
|
||||
bool Array::has(const Variant& p_value) const {
|
||||
return _p->array.find(p_value, 0) != -1;
|
||||
}
|
||||
|
||||
@ -201,43 +219,33 @@ void Array::remove(int p_pos) {
|
||||
_p->array.remove(p_pos);
|
||||
}
|
||||
|
||||
void Array::set(int p_idx, const Variant &p_value) {
|
||||
|
||||
operator[](p_idx) = p_value;
|
||||
void Array::set(int p_idx,const Variant& p_value) {
|
||||
|
||||
operator[](p_idx)=p_value;
|
||||
}
|
||||
|
||||
const Variant &Array::get(int p_idx) const {
|
||||
const Variant& Array::get(int p_idx) const {
|
||||
|
||||
return operator[](p_idx);
|
||||
}
|
||||
|
||||
Array Array::duplicate() const {
|
||||
|
||||
Array new_arr;
|
||||
int element_count = size();
|
||||
new_arr.resize(element_count);
|
||||
for (int i = 0; i < element_count; i++) {
|
||||
new_arr[i] = get(i);
|
||||
}
|
||||
|
||||
return new_arr;
|
||||
}
|
||||
struct _ArrayVariantSort {
|
||||
|
||||
_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
|
||||
bool valid = false;
|
||||
_FORCE_INLINE_ bool operator()(const Variant& p_l, const Variant& p_r) const {
|
||||
bool valid=false;
|
||||
Variant res;
|
||||
Variant::evaluate(Variant::OP_LESS, p_l, p_r, res, valid);
|
||||
Variant::evaluate(Variant::OP_LESS,p_l,p_r,res,valid);
|
||||
if (!valid)
|
||||
res = false;
|
||||
res=false;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
Array &Array::sort() {
|
||||
void Array::sort() {
|
||||
|
||||
_p->array.sort_custom<_ArrayVariantSort>();
|
||||
return *this;
|
||||
|
||||
}
|
||||
|
||||
struct _ArrayVariantSortCustom {
|
||||
@ -245,111 +253,64 @@ struct _ArrayVariantSortCustom {
|
||||
Object *obj;
|
||||
StringName func;
|
||||
|
||||
_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
|
||||
_FORCE_INLINE_ bool operator()(const Variant& p_l, const Variant& p_r) const {
|
||||
|
||||
const Variant *args[2] = { &p_l, &p_r };
|
||||
const Variant*args[2]={&p_l,&p_r};
|
||||
Variant::CallError err;
|
||||
bool res = obj->call(func, args, 2, err);
|
||||
if (err.error != Variant::CallError::CALL_OK)
|
||||
res = false;
|
||||
bool res = obj->call(func,args,2,err);
|
||||
if (err.error!=Variant::CallError::CALL_OK)
|
||||
res=false;
|
||||
return res;
|
||||
|
||||
}
|
||||
};
|
||||
Array &Array::sort_custom(Object *p_obj, const StringName &p_function) {
|
||||
void Array::sort_custom(Object *p_obj,const StringName& p_function){
|
||||
|
||||
ERR_FAIL_NULL_V(p_obj, *this);
|
||||
ERR_FAIL_NULL(p_obj);
|
||||
|
||||
SortArray<Variant,_ArrayVariantSortCustom> avs;
|
||||
avs.compare.obj=p_obj;
|
||||
avs.compare.func=p_function;
|
||||
avs.sort(_p->array.ptr(),_p->array.size());
|
||||
|
||||
SortArray<Variant, _ArrayVariantSortCustom> avs;
|
||||
avs.compare.obj = p_obj;
|
||||
avs.compare.func = p_function;
|
||||
avs.sort(_p->array.ptrw(), _p->array.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Less>
|
||||
_FORCE_INLINE_ int bisect(const Vector<Variant> &p_array, const Variant &p_value, bool p_before, const Less &p_less) {
|
||||
|
||||
int lo = 0;
|
||||
int hi = p_array.size();
|
||||
if (p_before) {
|
||||
while (lo < hi) {
|
||||
const int mid = (lo + hi) / 2;
|
||||
if (p_less(p_array.get(mid), p_value)) {
|
||||
lo = mid + 1;
|
||||
} else {
|
||||
hi = mid;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (lo < hi) {
|
||||
const int mid = (lo + hi) / 2;
|
||||
if (p_less(p_value, p_array.get(mid))) {
|
||||
hi = mid;
|
||||
} else {
|
||||
lo = mid + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return lo;
|
||||
}
|
||||
|
||||
int Array::bsearch(const Variant &p_value, bool p_before) {
|
||||
|
||||
return bisect(_p->array, p_value, p_before, _ArrayVariantSort());
|
||||
}
|
||||
|
||||
int Array::bsearch_custom(const Variant &p_value, Object *p_obj, const StringName &p_function, bool p_before) {
|
||||
|
||||
ERR_FAIL_NULL_V(p_obj, 0);
|
||||
|
||||
_ArrayVariantSortCustom less;
|
||||
less.obj = p_obj;
|
||||
less.func = p_function;
|
||||
|
||||
return bisect(_p->array, p_value, p_before, less);
|
||||
}
|
||||
|
||||
Array &Array::invert() {
|
||||
void Array::invert(){
|
||||
|
||||
_p->array.invert();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Array::push_front(const Variant &p_value) {
|
||||
|
||||
_p->array.insert(0, p_value);
|
||||
void Array::push_front(const Variant& p_value) {
|
||||
|
||||
_p->array.insert(0,p_value);
|
||||
}
|
||||
|
||||
Variant Array::pop_back() {
|
||||
void Array::pop_back(){
|
||||
|
||||
if (!_p->array.empty())
|
||||
_p->array.resize( _p->array.size() -1 );
|
||||
|
||||
if (!_p->array.empty()) {
|
||||
int n = _p->array.size() - 1;
|
||||
Variant ret = _p->array.get(n);
|
||||
_p->array.resize(n);
|
||||
return ret;
|
||||
}
|
||||
return Variant();
|
||||
}
|
||||
void Array::pop_front(){
|
||||
|
||||
Variant Array::pop_front() {
|
||||
|
||||
if (!_p->array.empty()) {
|
||||
Variant ret = _p->array.get(0);
|
||||
if (!_p->array.empty())
|
||||
_p->array.remove(0);
|
||||
return ret;
|
||||
}
|
||||
return Variant();
|
||||
|
||||
}
|
||||
|
||||
Array::Array(const Array &p_from) {
|
||||
|
||||
_p = NULL;
|
||||
Array::Array(const Array& p_from) {
|
||||
|
||||
_p=NULL;
|
||||
_ref(p_from);
|
||||
}
|
||||
Array::Array() {
|
||||
|
||||
_p = memnew(ArrayPrivate);
|
||||
}
|
||||
Array::Array(bool p_shared) {
|
||||
|
||||
_p = memnew( ArrayPrivate );
|
||||
_p->refcount.init();
|
||||
_p->shared=p_shared;
|
||||
}
|
||||
Array::~Array() {
|
||||
|
||||
|
||||
62
core/array.h
62
core/array.h
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,7 +26,6 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef ARRAY_H
|
||||
#define ARRAY_H
|
||||
|
||||
@ -40,58 +38,58 @@ class StringName;
|
||||
class Array {
|
||||
|
||||
mutable ArrayPrivate *_p;
|
||||
void _ref(const Array &p_from) const;
|
||||
void _ref(const Array& p_from) const;
|
||||
void _unref() const;
|
||||
|
||||
public:
|
||||
Variant &operator[](int p_idx);
|
||||
const Variant &operator[](int p_idx) const;
|
||||
|
||||
void set(int p_idx, const Variant &p_value);
|
||||
const Variant &get(int p_idx) const;
|
||||
Variant& operator[](int p_idx);
|
||||
const Variant& operator[](int p_idx) const;
|
||||
|
||||
void set(int p_idx,const Variant& p_value);
|
||||
const Variant& get(int p_idx) const;
|
||||
|
||||
int size() const;
|
||||
bool empty() const;
|
||||
void clear();
|
||||
|
||||
bool operator==(const Array &p_array) const;
|
||||
bool is_shared() const;
|
||||
|
||||
bool operator==(const Array& p_array) const;
|
||||
|
||||
uint32_t hash() const;
|
||||
void operator=(const Array &p_array);
|
||||
void operator=(const Array& p_array);
|
||||
|
||||
void push_back(const Variant &p_value);
|
||||
_FORCE_INLINE_ void append(const Variant &p_value) { push_back(p_value); } //for python compatibility
|
||||
void push_back(const Variant& p_value);
|
||||
_FORCE_INLINE_ void append(const Variant& p_value) { push_back(p_value); } //for python compatibility
|
||||
Error resize(int p_new_size);
|
||||
|
||||
void insert(int p_pos, const Variant &p_value);
|
||||
void insert(int p_pos, const Variant& p_value);
|
||||
void remove(int p_pos);
|
||||
|
||||
Variant front() const;
|
||||
Variant back() const;
|
||||
|
||||
Array &sort();
|
||||
Array &sort_custom(Object *p_obj, const StringName &p_function);
|
||||
int bsearch(const Variant &p_value, bool p_before = true);
|
||||
int bsearch_custom(const Variant &p_value, Object *p_obj, const StringName &p_function, bool p_before = true);
|
||||
Array &invert();
|
||||
void sort();
|
||||
void sort_custom(Object *p_obj,const StringName& p_function);
|
||||
void invert();
|
||||
|
||||
int find(const Variant &p_value, int p_from = 0) const;
|
||||
int rfind(const Variant &p_value, int p_from = -1) const;
|
||||
int find_last(const Variant &p_value) const;
|
||||
int count(const Variant &p_value) const;
|
||||
bool has(const Variant &p_value) const;
|
||||
int find(const Variant& p_value, int p_from=0) const;
|
||||
int rfind(const Variant& p_value, int p_from=-1) const;
|
||||
int find_last(const Variant& p_value) const;
|
||||
int count(const Variant& p_value) const;
|
||||
bool has(const Variant& p_value) const;
|
||||
|
||||
void erase(const Variant &p_value);
|
||||
void erase(const Variant& p_value);
|
||||
|
||||
void push_front(const Variant &p_value);
|
||||
Variant pop_back();
|
||||
Variant pop_front();
|
||||
void push_front(const Variant& p_value);
|
||||
void pop_back();
|
||||
void pop_front();
|
||||
|
||||
Array duplicate() const;
|
||||
|
||||
Array(const Array &p_from);
|
||||
Array();
|
||||
Array(const Array& p_from);
|
||||
Array(bool p_shared=false);
|
||||
~Array();
|
||||
|
||||
};
|
||||
|
||||
#endif // ARRAY_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,84 +26,77 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef CORE_BIND_H
|
||||
#define CORE_BIND_H
|
||||
|
||||
#include "image.h"
|
||||
#include "io/compression.h"
|
||||
#include "io/resource_loader.h"
|
||||
#include "io/resource_saver.h"
|
||||
#include "os/dir_access.h"
|
||||
#include "os/file_access.h"
|
||||
#include "os/os.h"
|
||||
#include "os/semaphore.h"
|
||||
#include "os/dir_access.h"
|
||||
#include "os/thread.h"
|
||||
#include "os/semaphore.h"
|
||||
|
||||
class _ResourceLoader : public Object {
|
||||
GDCLASS(_ResourceLoader, Object);
|
||||
|
||||
class _ResourceLoader : public Object {
|
||||
OBJ_TYPE(_ResourceLoader,Object);
|
||||
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
static _ResourceLoader *singleton;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
static _ResourceLoader *get_singleton() { return singleton; }
|
||||
Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_type_hint = "");
|
||||
RES load(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false);
|
||||
PoolVector<String> get_recognized_extensions_for_type(const String &p_type);
|
||||
Ref<ResourceInteractiveLoader> load_interactive(const String& p_path,const String& p_type_hint="");
|
||||
RES load(const String &p_path,const String& p_type_hint="", bool p_no_cache = false);
|
||||
DVector<String> get_recognized_extensions_for_type(const String& p_type);
|
||||
void set_abort_on_missing_resources(bool p_abort);
|
||||
PoolStringArray get_dependencies(const String &p_path);
|
||||
bool has(const String &p_path);
|
||||
StringArray get_dependencies(const String& p_path);
|
||||
bool has(const String& p_path);
|
||||
Ref<ResourceImportMetadata> load_import_metadata(const String& p_path);
|
||||
|
||||
_ResourceLoader();
|
||||
};
|
||||
|
||||
class _ResourceSaver : public Object {
|
||||
GDCLASS(_ResourceSaver, Object);
|
||||
class _ResourceSaver : public Object {
|
||||
OBJ_TYPE(_ResourceSaver,Object);
|
||||
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
static _ResourceSaver *singleton;
|
||||
|
||||
public:
|
||||
|
||||
enum SaverFlags {
|
||||
|
||||
FLAG_RELATIVE_PATHS = 1,
|
||||
FLAG_BUNDLE_RESOURCES = 2,
|
||||
FLAG_CHANGE_PATH = 4,
|
||||
FLAG_OMIT_EDITOR_PROPERTIES = 8,
|
||||
FLAG_SAVE_BIG_ENDIAN = 16,
|
||||
FLAG_COMPRESS = 32,
|
||||
FLAG_RELATIVE_PATHS=1,
|
||||
FLAG_BUNDLE_RESOURCES=2,
|
||||
FLAG_CHANGE_PATH=4,
|
||||
FLAG_OMIT_EDITOR_PROPERTIES=8,
|
||||
FLAG_SAVE_BIG_ENDIAN=16,
|
||||
FLAG_COMPRESS=32,
|
||||
};
|
||||
|
||||
static _ResourceSaver *get_singleton() { return singleton; }
|
||||
|
||||
Error save(const String &p_path, const RES &p_resource, uint32_t p_flags);
|
||||
PoolVector<String> get_recognized_extensions(const RES &p_resource);
|
||||
Error save(const String &p_path,const RES& p_resource, uint32_t p_flags);
|
||||
DVector<String> get_recognized_extensions(const RES& p_resource);
|
||||
|
||||
|
||||
_ResourceSaver();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(_ResourceSaver::SaverFlags);
|
||||
|
||||
class MainLoop;
|
||||
|
||||
class _OS : public Object {
|
||||
GDCLASS(_OS, Object);
|
||||
class _OS : public Object {
|
||||
OBJ_TYPE(_OS,Object);
|
||||
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
static _OS *singleton;
|
||||
|
||||
public:
|
||||
enum PowerState {
|
||||
POWERSTATE_UNKNOWN, /**< cannot determine power status */
|
||||
POWERSTATE_ON_BATTERY, /**< Not plugged in, running on the battery */
|
||||
POWERSTATE_NO_BATTERY, /**< Plugged in, no battery available */
|
||||
POWERSTATE_CHARGING, /**< Plugged in, charging battery */
|
||||
POWERSTATE_CHARGED /**< Plugged in, battery charged */
|
||||
};
|
||||
|
||||
enum Weekday {
|
||||
DAY_SUNDAY,
|
||||
@ -133,31 +125,31 @@ public:
|
||||
MONTH_DECEMBER
|
||||
};
|
||||
|
||||
Point2 get_mouse_position() const;
|
||||
void set_window_title(const String &p_title);
|
||||
Point2 get_mouse_pos() const;
|
||||
void set_window_title(const String& p_title);
|
||||
int get_mouse_button_state() const;
|
||||
|
||||
void set_clipboard(const String &p_text);
|
||||
|
||||
void set_clipboard(const String& p_text);
|
||||
String get_clipboard() const;
|
||||
|
||||
void set_video_mode(const Size2 &p_size, bool p_fullscreen, bool p_resizeable, int p_screen = 0);
|
||||
Size2 get_video_mode(int p_screen = 0) const;
|
||||
bool is_video_mode_fullscreen(int p_screen = 0) const;
|
||||
bool is_video_mode_resizable(int p_screen = 0) const;
|
||||
Array get_fullscreen_mode_list(int p_screen = 0) const;
|
||||
void set_video_mode(const Size2& p_size, bool p_fullscreen,bool p_resizeable,int p_screen=0);
|
||||
Size2 get_video_mode(int p_screen=0) const;
|
||||
bool is_video_mode_fullscreen(int p_screen=0) const;
|
||||
bool is_video_mode_resizable(int p_screen=0) const;
|
||||
Array get_fullscreen_mode_list(int p_screen=0) const;
|
||||
|
||||
|
||||
virtual int get_screen_count() const;
|
||||
virtual int get_current_screen() const;
|
||||
virtual void set_current_screen(int p_screen);
|
||||
virtual Point2 get_screen_position(int p_screen = -1) const;
|
||||
virtual Size2 get_screen_size(int p_screen = -1) const;
|
||||
virtual int get_screen_dpi(int p_screen = -1) const;
|
||||
virtual Point2 get_screen_position(int p_screen=0) const;
|
||||
virtual Size2 get_screen_size(int p_screen=0) const;
|
||||
virtual int get_screen_dpi(int p_screen=0) const;
|
||||
virtual Point2 get_window_position() const;
|
||||
virtual void set_window_position(const Point2 &p_position);
|
||||
virtual void set_window_position(const Point2& p_position);
|
||||
virtual Size2 get_window_size() const;
|
||||
virtual Size2 get_real_window_size() const;
|
||||
virtual Rect2 get_window_safe_area() const;
|
||||
virtual void set_window_size(const Size2 &p_size);
|
||||
virtual void set_window_size(const Size2& p_size);
|
||||
virtual void set_window_fullscreen(bool p_enabled);
|
||||
virtual bool is_window_fullscreen() const;
|
||||
virtual void set_window_resizable(bool p_enabled);
|
||||
@ -166,35 +158,36 @@ public:
|
||||
virtual bool is_window_minimized() const;
|
||||
virtual void set_window_maximized(bool p_enabled);
|
||||
virtual bool is_window_maximized() const;
|
||||
virtual void set_window_always_on_top(bool p_enabled);
|
||||
virtual bool is_window_always_on_top() const;
|
||||
virtual void request_attention();
|
||||
virtual void center_window();
|
||||
|
||||
virtual void set_borderless_window(bool p_borderless);
|
||||
virtual bool get_borderless_window() const;
|
||||
|
||||
virtual void set_ime_position(const Point2 &p_pos);
|
||||
|
||||
Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track);
|
||||
bool native_video_is_playing();
|
||||
void native_video_pause();
|
||||
void native_video_unpause();
|
||||
void native_video_stop();
|
||||
|
||||
void set_iterations_per_second(int p_ips);
|
||||
int get_iterations_per_second() const;
|
||||
|
||||
void set_target_fps(int p_fps);
|
||||
float get_target_fps() const;
|
||||
|
||||
void set_low_processor_usage_mode(bool p_enabled);
|
||||
bool is_in_low_processor_usage_mode() const;
|
||||
|
||||
String get_executable_path() const;
|
||||
int execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, Array p_output = Array());
|
||||
int execute(const String& p_path, const Vector<String> & p_arguments,bool p_blocking,Array p_output=Array());
|
||||
|
||||
Error kill(int p_pid);
|
||||
Error shell_open(String p_uri);
|
||||
|
||||
int get_process_id() const;
|
||||
int get_process_ID() const;
|
||||
|
||||
bool has_environment(const String &p_var) const;
|
||||
String get_environment(const String &p_var) const;
|
||||
bool has_environment(const String& p_var) const;
|
||||
String get_environment(const String& p_var) const;
|
||||
|
||||
String get_name() const;
|
||||
Vector<String> get_cmdline_args();
|
||||
@ -203,29 +196,34 @@ public:
|
||||
String get_latin_keyboard_variant() const;
|
||||
|
||||
String get_model_name() const;
|
||||
MainLoop *get_main_loop() const;
|
||||
|
||||
void dump_memory_to_file(const String &p_file);
|
||||
void dump_resources_to_file(const String &p_file);
|
||||
String get_custom_level() const;
|
||||
|
||||
float get_frames_per_second() const;
|
||||
|
||||
void dump_memory_to_file(const String& p_file);
|
||||
void dump_resources_to_file(const String& p_file);
|
||||
|
||||
bool has_virtual_keyboard() const;
|
||||
void show_virtual_keyboard(const String &p_existing_text = "");
|
||||
void show_virtual_keyboard(const String& p_existing_text="");
|
||||
void hide_virtual_keyboard();
|
||||
int get_virtual_keyboard_height();
|
||||
|
||||
void print_resources_in_use(bool p_short = false);
|
||||
void print_all_resources(const String &p_to_file);
|
||||
void print_resources_in_use(bool p_short=false);
|
||||
void print_all_resources(const String& p_to_file);
|
||||
void print_all_textures_by_size();
|
||||
void print_resources_by_type(const Vector<String> &p_types);
|
||||
void print_resources_by_type(const Vector<String>& p_types);
|
||||
|
||||
bool has_touchscreen_ui_hint() const;
|
||||
|
||||
bool is_debug_build() const;
|
||||
|
||||
String get_unique_id() const;
|
||||
String get_unique_ID() const;
|
||||
|
||||
String get_scancode_string(uint32_t p_code) const;
|
||||
bool is_scancode_unicode(uint32_t p_unicode) const;
|
||||
int find_scancode_from_string(const String &p_code) const;
|
||||
int find_scancode_from_string(const String& p_code) const;
|
||||
|
||||
|
||||
/*
|
||||
struct Date {
|
||||
@ -247,7 +245,7 @@ public:
|
||||
|
||||
void set_use_file_access_save_and_swap(bool p_enable);
|
||||
|
||||
void set_icon(const Ref<Image> &p_icon);
|
||||
void set_icon(const Image& p_icon);
|
||||
|
||||
int get_exit_code() const;
|
||||
void set_exit_code(int p_code);
|
||||
@ -273,7 +271,7 @@ public:
|
||||
|
||||
bool can_draw() const;
|
||||
|
||||
bool is_userfs_persistent() const;
|
||||
int get_frames_drawn();
|
||||
|
||||
bool is_stdout_verbose() const;
|
||||
|
||||
@ -303,9 +301,11 @@ public:
|
||||
|
||||
String get_system_dir(SystemDir p_dir) const;
|
||||
|
||||
String get_user_data_dir() const;
|
||||
|
||||
void alert(const String &p_alert, const String &p_title = "ALERT!");
|
||||
String get_data_dir() const;
|
||||
|
||||
void alert(const String& p_alert,const String& p_title="ALERT!");
|
||||
|
||||
|
||||
void set_screen_orientation(ScreenOrientation p_orientation);
|
||||
ScreenOrientation get_screen_orientation() const;
|
||||
@ -313,109 +313,94 @@ public:
|
||||
void set_keep_screen_on(bool p_enabled);
|
||||
bool is_keep_screen_on() const;
|
||||
|
||||
void set_time_scale(float p_scale);
|
||||
float get_time_scale();
|
||||
|
||||
bool is_ok_left_and_cancel_right() const;
|
||||
|
||||
Error set_thread_name(const String &p_name);
|
||||
Error set_thread_name(const String& p_name);
|
||||
|
||||
void set_use_vsync(bool p_enable);
|
||||
bool is_vsync_enabled() const;
|
||||
|
||||
PowerState get_power_state();
|
||||
int get_power_seconds_left();
|
||||
int get_power_percent_left();
|
||||
|
||||
bool has_feature(const String &p_feature) const;
|
||||
Dictionary get_engine_version() const;
|
||||
|
||||
static _OS *get_singleton() { return singleton; }
|
||||
|
||||
_OS();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(_OS::PowerState);
|
||||
VARIANT_ENUM_CAST(_OS::Weekday);
|
||||
VARIANT_ENUM_CAST(_OS::Month);
|
||||
VARIANT_ENUM_CAST(_OS::SystemDir);
|
||||
VARIANT_ENUM_CAST(_OS::ScreenOrientation);
|
||||
|
||||
|
||||
class _Geometry : public Object {
|
||||
|
||||
GDCLASS(_Geometry, Object);
|
||||
OBJ_TYPE(_Geometry, Object);
|
||||
|
||||
static _Geometry *singleton;
|
||||
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
static _Geometry *get_singleton();
|
||||
PoolVector<Plane> build_box_planes(const Vector3 &p_extents);
|
||||
PoolVector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z);
|
||||
PoolVector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z);
|
||||
Variant segment_intersects_segment_2d(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b);
|
||||
PoolVector<Vector2> get_closest_points_between_segments_2d(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2);
|
||||
PoolVector<Vector3> get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2);
|
||||
Vector2 get_closest_point_to_segment_2d(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b);
|
||||
Vector3 get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b);
|
||||
Vector2 get_closest_point_to_segment_uncapped_2d(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b);
|
||||
Vector3 get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b);
|
||||
Variant ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2);
|
||||
Variant segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2);
|
||||
bool point_is_inside_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) const;
|
||||
DVector<Plane> build_box_planes(const Vector3& p_extents);
|
||||
DVector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis=Vector3::AXIS_Z);
|
||||
DVector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis=Vector3::AXIS_Z);
|
||||
Variant segment_intersects_segment_2d(const Vector2& p_from_a,const Vector2& p_to_a,const Vector2& p_from_b,const Vector2& p_to_b);
|
||||
DVector<Vector2> get_closest_points_between_segments_2d( const Vector2& p1,const Vector2& q1, const Vector2& p2,const Vector2& q2);
|
||||
DVector<Vector3> get_closest_points_between_segments(const Vector3& p1,const Vector3& p2,const Vector3& q1,const Vector3& q2);
|
||||
Vector3 get_closest_point_to_segment(const Vector3& p_point, const Vector3& p_a,const Vector3& p_b);
|
||||
Variant ray_intersects_triangle( const Vector3& p_from, const Vector3& p_dir, const Vector3& p_v0,const Vector3& p_v1,const Vector3& p_v2);
|
||||
Variant segment_intersects_triangle( const Vector3& p_from, const Vector3& p_to, const Vector3& p_v0,const Vector3& p_v1,const Vector3& p_v2);
|
||||
bool point_is_inside_triangle(const Vector2& s, const Vector2& a, const Vector2& b, const Vector2& c) const;
|
||||
|
||||
PoolVector<Vector3> segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius);
|
||||
PoolVector<Vector3> segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius);
|
||||
PoolVector<Vector3> segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes);
|
||||
real_t segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius);
|
||||
int get_uv84_normal_bit(const Vector3 &p_vector);
|
||||
DVector<Vector3> segment_intersects_sphere( const Vector3& p_from, const Vector3& p_to, const Vector3& p_sphere_pos,real_t p_sphere_radius);
|
||||
DVector<Vector3> segment_intersects_cylinder( const Vector3& p_from, const Vector3& p_to, float p_height,float p_radius);
|
||||
DVector<Vector3> segment_intersects_convex(const Vector3& p_from, const Vector3& p_to,const Vector<Plane>& p_planes);
|
||||
real_t segment_intersects_circle(const Vector2& p_from, const Vector2& p_to, const Vector2& p_circle_pos, real_t p_circle_radius);
|
||||
int get_uv84_normal_bit(const Vector3& p_vector);
|
||||
|
||||
Vector<int> triangulate_polygon(const Vector<Vector2> &p_polygon);
|
||||
Vector<Point2> convex_hull_2d(const Vector<Point2> &p_points);
|
||||
Vector<Vector3> clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane);
|
||||
Vector<int> triangulate_polygon(const Vector<Vector2>& p_polygon);
|
||||
|
||||
Dictionary make_atlas(const Vector<Size2> &p_rects);
|
||||
Dictionary make_atlas(const Vector<Size2>& p_rects);
|
||||
|
||||
_Geometry();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class _File : public Reference {
|
||||
|
||||
GDCLASS(_File, Reference);
|
||||
OBJ_TYPE(_File,Reference);
|
||||
FileAccess *f;
|
||||
bool eswap;
|
||||
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
enum ModeFlags {
|
||||
|
||||
READ = 1,
|
||||
WRITE = 2,
|
||||
READ_WRITE = 3,
|
||||
WRITE_READ = 7,
|
||||
enum ModeFlags {
|
||||
|
||||
READ=1,
|
||||
WRITE=2,
|
||||
READ_WRITE=3,
|
||||
WRITE_READ=7,
|
||||
};
|
||||
|
||||
enum CompressionMode {
|
||||
COMPRESSION_FASTLZ = Compression::MODE_FASTLZ,
|
||||
COMPRESSION_DEFLATE = Compression::MODE_DEFLATE,
|
||||
COMPRESSION_ZSTD = Compression::MODE_ZSTD,
|
||||
COMPRESSION_GZIP = Compression::MODE_GZIP
|
||||
};
|
||||
Error open_encrypted(const String& p_path, int p_mode_flags,const Vector<uint8_t>& p_key);
|
||||
Error open_encrypted_pass(const String& p_path, int p_mode_flags,const String& p_pass);
|
||||
|
||||
Error open_encrypted(const String &p_path, int p_mode_flags, const Vector<uint8_t> &p_key);
|
||||
Error open_encrypted_pass(const String &p_path, int p_mode_flags, const String &p_pass);
|
||||
Error open_compressed(const String &p_path, int p_mode_flags, int p_compress_mode = 0);
|
||||
|
||||
Error open(const String &p_path, int p_mode_flags); ///< open a file
|
||||
Error open(const String& p_path, int p_mode_flags); ///< open a file
|
||||
void close(); ///< close a file
|
||||
bool is_open() const; ///< true when file is open
|
||||
|
||||
String get_path() const; /// returns the path for the current open file
|
||||
String get_path_absolute() const; /// returns the absolute path for the current open file
|
||||
|
||||
void seek(int64_t p_position); ///< seek to a given position
|
||||
void seek_end(int64_t p_position = 0); ///< seek from the end of file
|
||||
int64_t get_position() const; ///< get position in the file
|
||||
void seek_end(int64_t p_position=0); ///< seek from the end of file
|
||||
int64_t get_pos() const; ///< get position in the file
|
||||
int64_t get_len() const; ///< get size of the file
|
||||
|
||||
bool eof_reached() const; ///< reading passed EOF
|
||||
@ -431,11 +416,11 @@ public:
|
||||
|
||||
Variant get_var() const;
|
||||
|
||||
PoolVector<uint8_t> get_buffer(int p_length) const; ///< get an array of bytes
|
||||
DVector<uint8_t> get_buffer(int p_length) const; ///< get an array of bytes
|
||||
String get_line() const;
|
||||
String get_as_text() const;
|
||||
String get_md5(const String &p_path) const;
|
||||
String get_sha256(const String &p_path) const;
|
||||
String get_md5(const String& p_path) const;
|
||||
String get_sha256(const String& p_path) const;
|
||||
|
||||
/**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
|
||||
* It's not about the current CPU type but file formats.
|
||||
@ -456,41 +441,38 @@ public:
|
||||
void store_double(double p_dest);
|
||||
void store_real(real_t p_real);
|
||||
|
||||
void store_string(const String &p_string);
|
||||
void store_line(const String &p_string);
|
||||
void store_string(const String& p_string);
|
||||
void store_line(const String& p_string);
|
||||
|
||||
virtual void store_pascal_string(const String &p_string);
|
||||
virtual void store_pascal_string(const String& p_string);
|
||||
virtual String get_pascal_string();
|
||||
|
||||
Vector<String> get_csv_line(String delim = ",") const;
|
||||
Vector<String> get_csv_line(String delim=",") const;
|
||||
|
||||
void store_buffer(const PoolVector<uint8_t> &p_buffer); ///< store an array of bytes
|
||||
|
||||
void store_var(const Variant &p_var);
|
||||
void store_buffer(const DVector<uint8_t>& p_buffer); ///< store an array of bytes
|
||||
|
||||
bool file_exists(const String &p_name) const; ///< return true if a file exists
|
||||
void store_var(const Variant& p_var);
|
||||
|
||||
uint64_t get_modified_time(const String &p_file) const;
|
||||
bool file_exists(const String& p_name) const; ///< return true if a file exists
|
||||
|
||||
_File();
|
||||
virtual ~_File();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(_File::ModeFlags);
|
||||
VARIANT_ENUM_CAST(_File::CompressionMode);
|
||||
};
|
||||
|
||||
class _Directory : public Reference {
|
||||
|
||||
GDCLASS(_Directory, Reference);
|
||||
OBJ_TYPE(_Directory,Reference);
|
||||
DirAccess *d;
|
||||
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
Error open(const String &p_path);
|
||||
|
||||
Error list_dir_begin(bool p_skip_navigational = false, bool p_skip_hidden = false); ///< This starts dir listing
|
||||
Error open(const String& p_path);
|
||||
|
||||
bool list_dir_begin(); ///< This starts dir listing
|
||||
String get_next();
|
||||
bool current_is_dir() const;
|
||||
|
||||
@ -498,7 +480,6 @@ public:
|
||||
|
||||
int get_drive_count();
|
||||
String get_drive(int p_drive);
|
||||
int get_current_drive();
|
||||
|
||||
Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
|
||||
String get_current_dir(); ///< return current dir location
|
||||
@ -511,51 +492,48 @@ public:
|
||||
|
||||
int get_space_left();
|
||||
|
||||
Error copy(String p_from, String p_to);
|
||||
Error copy(String p_from,String p_to);
|
||||
Error rename(String p_from, String p_to);
|
||||
Error remove(String p_name);
|
||||
|
||||
|
||||
_Directory();
|
||||
virtual ~_Directory();
|
||||
|
||||
private:
|
||||
bool _list_skip_navigational;
|
||||
bool _list_skip_hidden;
|
||||
};
|
||||
|
||||
class _Marshalls : public Reference {
|
||||
|
||||
GDCLASS(_Marshalls, Reference);
|
||||
|
||||
static _Marshalls *singleton;
|
||||
OBJ_TYPE(_Marshalls,Reference);
|
||||
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
|
||||
public:
|
||||
static _Marshalls *get_singleton();
|
||||
|
||||
String variant_to_base64(const Variant &p_var);
|
||||
Variant base64_to_variant(const String &p_str);
|
||||
String variant_to_base64(const Variant& p_var);
|
||||
Variant base64_to_variant(const String& p_str);
|
||||
|
||||
String raw_to_base64(const PoolVector<uint8_t> &p_arr);
|
||||
PoolVector<uint8_t> base64_to_raw(const String &p_str);
|
||||
String raw_to_base64(const DVector<uint8_t>& p_arr);
|
||||
DVector<uint8_t> base64_to_raw(const String& p_str);
|
||||
|
||||
String utf8_to_base64(const String &p_str);
|
||||
String base64_to_utf8(const String &p_str);
|
||||
String utf8_to_base64(const String& p_str);
|
||||
String base64_to_utf8(const String& p_str);
|
||||
|
||||
_Marshalls() { singleton = this; }
|
||||
~_Marshalls() { singleton = NULL; }
|
||||
_Marshalls() {};
|
||||
};
|
||||
|
||||
|
||||
class _Mutex : public Reference {
|
||||
|
||||
GDCLASS(_Mutex, Reference);
|
||||
OBJ_TYPE(_Mutex,Reference);
|
||||
Mutex *mutex;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void lock();
|
||||
Error try_lock();
|
||||
void unlock();
|
||||
@ -566,12 +544,12 @@ public:
|
||||
|
||||
class _Semaphore : public Reference {
|
||||
|
||||
GDCLASS(_Semaphore, Reference);
|
||||
OBJ_TYPE(_Semaphore,Reference);
|
||||
Semaphore *semaphore;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
Error wait();
|
||||
Error post();
|
||||
|
||||
@ -581,9 +559,10 @@ public:
|
||||
|
||||
class _Thread : public Reference {
|
||||
|
||||
GDCLASS(_Thread, Reference);
|
||||
OBJ_TYPE(_Thread,Reference);
|
||||
|
||||
protected:
|
||||
|
||||
Variant ret;
|
||||
Variant userdata;
|
||||
volatile bool active;
|
||||
@ -592,8 +571,8 @@ protected:
|
||||
Thread *thread;
|
||||
static void _bind_methods();
|
||||
static void _start_func(void *ud);
|
||||
|
||||
public:
|
||||
|
||||
enum Priority {
|
||||
|
||||
PRIORITY_LOW,
|
||||
@ -601,7 +580,7 @@ public:
|
||||
PRIORITY_HIGH
|
||||
};
|
||||
|
||||
Error start(Object *p_instance, const StringName &p_method, const Variant &p_userdata = Variant(), int p_priority = PRIORITY_NORMAL);
|
||||
Error start(Object *p_instance,const StringName& p_method,const Variant& p_userdata=Variant(),int p_priority=PRIORITY_NORMAL);
|
||||
String get_id() const;
|
||||
bool is_active() const;
|
||||
Variant wait_to_finish();
|
||||
@ -610,128 +589,4 @@ public:
|
||||
~_Thread();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(_Thread::Priority);
|
||||
|
||||
class _ClassDB : public Object {
|
||||
|
||||
GDCLASS(_ClassDB, Object)
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
PoolStringArray get_class_list() const;
|
||||
PoolStringArray get_inheriters_from_class(const StringName &p_class) const;
|
||||
StringName get_parent_class(const StringName &p_class) const;
|
||||
bool class_exists(const StringName &p_class) const;
|
||||
bool is_parent_class(const StringName &p_class, const StringName &p_inherits) const;
|
||||
bool can_instance(const StringName &p_class) const;
|
||||
Variant instance(const StringName &p_class) const;
|
||||
|
||||
bool has_signal(StringName p_class, StringName p_signal) const;
|
||||
Dictionary get_signal(StringName p_class, StringName p_signal) const;
|
||||
Array get_signal_list(StringName p_class, bool p_no_inheritance = false) const;
|
||||
|
||||
Array get_property_list(StringName p_class, bool p_no_inheritance = false) const;
|
||||
Variant get_property(Object *p_object, const StringName &p_property) const;
|
||||
Error set_property(Object *p_object, const StringName &p_property, const Variant &p_value) const;
|
||||
|
||||
bool has_method(StringName p_class, StringName p_method, bool p_no_inheritance = false) const;
|
||||
|
||||
Array get_method_list(StringName p_class, bool p_no_inheritance = false) const;
|
||||
|
||||
PoolStringArray get_integer_constant_list(const StringName &p_class, bool p_no_inheritance = false) const;
|
||||
bool has_integer_constant(const StringName &p_class, const StringName &p_name) const;
|
||||
int get_integer_constant(const StringName &p_class, const StringName &p_name) const;
|
||||
StringName get_category(const StringName &p_node) const;
|
||||
|
||||
bool is_class_enabled(StringName p_class) const;
|
||||
|
||||
_ClassDB();
|
||||
~_ClassDB();
|
||||
};
|
||||
|
||||
class _Engine : public Object {
|
||||
GDCLASS(_Engine, Object);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static _Engine *singleton;
|
||||
|
||||
public:
|
||||
static _Engine *get_singleton() { return singleton; }
|
||||
void set_iterations_per_second(int p_ips);
|
||||
int get_iterations_per_second() const;
|
||||
|
||||
void set_target_fps(int p_fps);
|
||||
int get_target_fps() const;
|
||||
|
||||
float get_frames_per_second() const;
|
||||
|
||||
int get_frames_drawn();
|
||||
|
||||
void set_time_scale(float p_scale);
|
||||
float get_time_scale();
|
||||
|
||||
MainLoop *get_main_loop() const;
|
||||
|
||||
Dictionary get_version_info() const;
|
||||
|
||||
bool is_in_physics_frame() const;
|
||||
|
||||
bool has_singleton(const String &p_name) const;
|
||||
Object *get_singleton_object(const String &p_name) const;
|
||||
|
||||
void set_editor_hint(bool p_enabled);
|
||||
bool is_editor_hint() const;
|
||||
|
||||
_Engine();
|
||||
};
|
||||
|
||||
class _JSON;
|
||||
|
||||
class JSONParseResult : public Reference {
|
||||
GDCLASS(JSONParseResult, Reference)
|
||||
|
||||
friend class _JSON;
|
||||
|
||||
Error error;
|
||||
String error_string;
|
||||
int error_line;
|
||||
|
||||
Variant result;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_error(Error p_error);
|
||||
Error get_error() const;
|
||||
|
||||
void set_error_string(const String &p_error_string);
|
||||
String get_error_string() const;
|
||||
|
||||
void set_error_line(int p_error_line);
|
||||
int get_error_line() const;
|
||||
|
||||
void set_result(const Variant &p_result);
|
||||
Variant get_result() const;
|
||||
};
|
||||
|
||||
class _JSON : public Object {
|
||||
GDCLASS(_JSON, Object)
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static _JSON *singleton;
|
||||
|
||||
public:
|
||||
static _JSON *get_singleton() { return singleton; }
|
||||
|
||||
String print(const Variant &p_value, const String &p_indent = "", bool p_sort_keys = false);
|
||||
Ref<JSONParseResult> parse(const String &p_json);
|
||||
|
||||
_JSON();
|
||||
};
|
||||
|
||||
#endif // CORE_BIND_H
|
||||
|
||||
1415
core/class_db.cpp
1415
core/class_db.cpp
File diff suppressed because it is too large
Load Diff
400
core/class_db.h
400
core/class_db.h
@ -1,400 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* class_db.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef CLASS_DB_H
|
||||
#define CLASS_DB_H
|
||||
|
||||
#include "method_bind.h"
|
||||
#include "object.h"
|
||||
#include "print_string.h"
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
#define DEFVAL(m_defval) (m_defval)
|
||||
|
||||
//#define SIMPLE_METHODDEF
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
|
||||
struct MethodDefinition {
|
||||
|
||||
StringName name;
|
||||
Vector<StringName> args;
|
||||
MethodDefinition() {}
|
||||
MethodDefinition(const char *p_name) :
|
||||
name(p_name) {}
|
||||
MethodDefinition(const StringName &p_name) :
|
||||
name(p_name) {}
|
||||
};
|
||||
|
||||
MethodDefinition D_METHOD(const char *p_name);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11, const char *p_arg12);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11, const char *p_arg12, const char *p_arg13);
|
||||
|
||||
#else
|
||||
|
||||
//#define NO_VARIADIC_MACROS
|
||||
|
||||
#ifdef NO_VARIADIC_MACROS
|
||||
|
||||
static _FORCE_INLINE_ const char *D_METHOD(const char *m_name, ...) {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// When DEBUG_METHODS_ENABLED is set this will let the engine know
|
||||
// the argument names for easier debugging.
|
||||
#define D_METHOD(m_c, ...) m_c
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
class ClassDB {
|
||||
public:
|
||||
enum APIType {
|
||||
API_CORE,
|
||||
API_EDITOR,
|
||||
API_NONE
|
||||
};
|
||||
|
||||
public:
|
||||
struct PropertySetGet {
|
||||
|
||||
int index;
|
||||
StringName setter;
|
||||
StringName getter;
|
||||
MethodBind *_setptr;
|
||||
MethodBind *_getptr;
|
||||
Variant::Type type;
|
||||
};
|
||||
|
||||
struct ClassInfo {
|
||||
|
||||
APIType api;
|
||||
ClassInfo *inherits_ptr;
|
||||
HashMap<StringName, MethodBind *, StringNameHasher> method_map;
|
||||
HashMap<StringName, int, StringNameHasher> constant_map;
|
||||
HashMap<StringName, MethodInfo, StringNameHasher> signal_map;
|
||||
List<PropertyInfo> property_list;
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
HashMap<StringName, List<StringName> > enum_map;
|
||||
List<StringName> constant_order;
|
||||
List<StringName> method_order;
|
||||
Set<StringName> methods_in_properties;
|
||||
List<MethodInfo> virtual_methods;
|
||||
StringName category;
|
||||
#endif
|
||||
HashMap<StringName, PropertySetGet, StringNameHasher> property_setget;
|
||||
|
||||
StringName inherits;
|
||||
StringName name;
|
||||
bool disabled;
|
||||
bool exposed;
|
||||
Object *(*creation_func)();
|
||||
ClassInfo();
|
||||
~ClassInfo();
|
||||
};
|
||||
|
||||
template <class T>
|
||||
static Object *creator() {
|
||||
return memnew(T);
|
||||
}
|
||||
|
||||
static RWLock *lock;
|
||||
static HashMap<StringName, ClassInfo, StringNameHasher> classes;
|
||||
static HashMap<StringName, StringName, StringNameHasher> resource_base_extensions;
|
||||
static HashMap<StringName, StringName, StringNameHasher> compat_classes;
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount);
|
||||
#else
|
||||
static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const char *method_name, const Variant **p_defs, int p_defcount);
|
||||
#endif
|
||||
|
||||
static APIType current_api;
|
||||
|
||||
static void _add_class2(const StringName &p_class, const StringName &p_inherits);
|
||||
|
||||
public:
|
||||
// DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!!
|
||||
template <class T>
|
||||
static void _add_class() {
|
||||
|
||||
_add_class2(T::get_class_static(), T::get_parent_class_static());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void register_class() {
|
||||
|
||||
GLOBAL_LOCK_FUNCTION;
|
||||
T::initialize_class();
|
||||
ClassInfo *t = classes.getptr(T::get_class_static());
|
||||
ERR_FAIL_COND(!t);
|
||||
t->creation_func = &creator<T>;
|
||||
t->exposed = true;
|
||||
T::register_custom_data_to_otdb();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void register_virtual_class() {
|
||||
|
||||
GLOBAL_LOCK_FUNCTION;
|
||||
T::initialize_class();
|
||||
ClassInfo *t = classes.getptr(T::get_class_static());
|
||||
ERR_FAIL_COND(!t);
|
||||
t->exposed = true;
|
||||
//nothing
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static Object *_create_ptr_func() {
|
||||
|
||||
return T::create();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void register_custom_instance_class() {
|
||||
|
||||
GLOBAL_LOCK_FUNCTION;
|
||||
T::initialize_class();
|
||||
ClassInfo *t = classes.getptr(T::get_class_static());
|
||||
ERR_FAIL_COND(!t);
|
||||
t->creation_func = &_create_ptr_func<T>;
|
||||
t->exposed = true;
|
||||
T::register_custom_data_to_otdb();
|
||||
}
|
||||
|
||||
static void get_class_list(List<StringName> *p_classes);
|
||||
static void get_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes);
|
||||
static StringName get_parent_class_nocheck(const StringName &p_class);
|
||||
static StringName get_parent_class(const StringName &p_class);
|
||||
static bool class_exists(const StringName &p_class);
|
||||
static bool is_parent_class(const StringName &p_class, const StringName &p_inherits);
|
||||
static bool can_instance(const StringName &p_class);
|
||||
static Object *instance(const StringName &p_class);
|
||||
static APIType get_api_type(const StringName &p_class);
|
||||
|
||||
static uint64_t get_api_hash(APIType p_api);
|
||||
|
||||
template <class N, class M>
|
||||
static MethodBind *bind_method(N p_method_name, M p_method) {
|
||||
|
||||
MethodBind *bind = create_method_bind(p_method);
|
||||
|
||||
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, NULL, 0); //use static function, much smaller binary usage
|
||||
}
|
||||
|
||||
template <class N, class M>
|
||||
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1) {
|
||||
|
||||
MethodBind *bind = create_method_bind(p_method);
|
||||
const Variant *ptr[1] = { &p_def1 };
|
||||
|
||||
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 1);
|
||||
}
|
||||
|
||||
template <class N, class M>
|
||||
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2) {
|
||||
|
||||
MethodBind *bind = create_method_bind(p_method);
|
||||
const Variant *ptr[2] = { &p_def1, &p_def2 };
|
||||
|
||||
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 2);
|
||||
}
|
||||
|
||||
template <class N, class M>
|
||||
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3) {
|
||||
|
||||
MethodBind *bind = create_method_bind(p_method);
|
||||
const Variant *ptr[3] = { &p_def1, &p_def2, &p_def3 };
|
||||
|
||||
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 3);
|
||||
}
|
||||
|
||||
template <class N, class M>
|
||||
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4) {
|
||||
|
||||
MethodBind *bind = create_method_bind(p_method);
|
||||
const Variant *ptr[4] = { &p_def1, &p_def2, &p_def3, &p_def4 };
|
||||
|
||||
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 4);
|
||||
}
|
||||
|
||||
template <class N, class M>
|
||||
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5) {
|
||||
|
||||
MethodBind *bind = create_method_bind(p_method);
|
||||
const Variant *ptr[5] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5 };
|
||||
|
||||
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 5);
|
||||
}
|
||||
|
||||
template <class N, class M>
|
||||
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6) {
|
||||
|
||||
MethodBind *bind = create_method_bind(p_method);
|
||||
const Variant *ptr[6] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6 };
|
||||
|
||||
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 6);
|
||||
}
|
||||
|
||||
template <class M>
|
||||
static MethodBind *bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const Vector<Variant> &p_default_args = Vector<Variant>()) {
|
||||
|
||||
GLOBAL_LOCK_FUNCTION;
|
||||
|
||||
MethodBind *bind = create_vararg_method_bind(p_method, p_info);
|
||||
ERR_FAIL_COND_V(!bind, NULL);
|
||||
|
||||
bind->set_name(p_name);
|
||||
bind->set_default_arguments(p_default_args);
|
||||
|
||||
String instance_type = bind->get_instance_class();
|
||||
|
||||
ClassInfo *type = classes.getptr(instance_type);
|
||||
if (!type) {
|
||||
memdelete(bind);
|
||||
ERR_FAIL_COND_V(!type, NULL);
|
||||
}
|
||||
|
||||
if (type->method_map.has(p_name)) {
|
||||
memdelete(bind);
|
||||
// overloading not supported
|
||||
ERR_EXPLAIN("Method already bound: " + instance_type + "::" + p_name);
|
||||
ERR_FAIL_V(NULL);
|
||||
}
|
||||
type->method_map[p_name] = bind;
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
// FIXME: <reduz> set_return_type is no longer in MethodBind, so I guess it should be moved to vararg method bind
|
||||
//bind->set_return_type("Variant");
|
||||
type->method_order.push_back(p_name);
|
||||
#endif
|
||||
|
||||
return bind;
|
||||
}
|
||||
|
||||
static void add_signal(StringName p_class, const MethodInfo &p_signal);
|
||||
static bool has_signal(StringName p_class, StringName p_signal);
|
||||
static bool get_signal(StringName p_class, StringName p_signal, MethodInfo *r_signal);
|
||||
static void get_signal_list(StringName p_class, List<MethodInfo> *p_signals, bool p_no_inheritance = false);
|
||||
|
||||
static void add_property_group(StringName p_class, const String &p_name, const String &p_prefix = "");
|
||||
static void add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
|
||||
static void get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance = false, const Object *p_validator = NULL);
|
||||
static bool set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid = NULL);
|
||||
static bool get_property(Object *p_object, const StringName &p_property, Variant &r_value);
|
||||
static bool has_property(const StringName &p_class, const StringName &p_property, bool p_no_inheritance = false);
|
||||
static int get_property_index(const StringName &p_class, const StringName &p_property, bool *r_is_valid = NULL);
|
||||
static Variant::Type get_property_type(const StringName &p_class, const StringName &p_property, bool *r_is_valid = NULL);
|
||||
static StringName get_property_setter(StringName p_class, const StringName p_property);
|
||||
static StringName get_property_getter(StringName p_class, const StringName p_property);
|
||||
|
||||
static bool has_method(StringName p_class, StringName p_method, bool p_no_inheritance = false);
|
||||
static void set_method_flags(StringName p_class, StringName p_method, int p_flags);
|
||||
|
||||
static void get_method_list(StringName p_class, List<MethodInfo> *p_methods, bool p_no_inheritance = false, bool p_exclude_from_properties = false);
|
||||
static MethodBind *get_method(StringName p_class, StringName p_name);
|
||||
|
||||
static void add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual = true);
|
||||
static void get_virtual_methods(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance = false);
|
||||
|
||||
static void bind_integer_constant(const StringName &p_class, const StringName &p_enum, const StringName &p_name, int p_constant);
|
||||
static void get_integer_constant_list(const StringName &p_class, List<String> *p_constants, bool p_no_inheritance = false);
|
||||
static int get_integer_constant(const StringName &p_class, const StringName &p_name, bool *p_success = NULL);
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
static StringName get_integer_constant_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false);
|
||||
static void get_enum_list(const StringName &p_class, List<StringName> *p_enums, bool p_no_inheritance = false);
|
||||
static void get_enum_constants(const StringName &p_class, const StringName &p_enum, List<StringName> *p_constants, bool p_no_inheritance = false);
|
||||
#endif
|
||||
|
||||
static StringName get_category(const StringName &p_node);
|
||||
|
||||
static void set_class_enabled(StringName p_class, bool p_enable);
|
||||
static bool is_class_enabled(StringName p_class);
|
||||
|
||||
static bool is_class_exposed(StringName p_class);
|
||||
|
||||
static void add_resource_base_extension(const StringName &p_extension, const StringName &p_class);
|
||||
static void get_resource_base_extensions(List<String> *p_extensions);
|
||||
static void get_extensions_for_type(const StringName &p_class, List<String> *p_extensions);
|
||||
|
||||
static void add_compatibility_class(const StringName &p_class, const StringName &p_fallback);
|
||||
static void init();
|
||||
|
||||
static void set_current_api(APIType p_api);
|
||||
static void cleanup();
|
||||
};
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
|
||||
#define BIND_CONSTANT(m_constant) \
|
||||
ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
|
||||
|
||||
#define BIND_ENUM_CONSTANT(m_constant) \
|
||||
ClassDB::bind_integer_constant(get_class_static(), __constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant);
|
||||
|
||||
#else
|
||||
|
||||
#define BIND_CONSTANT(m_constant) \
|
||||
ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
|
||||
|
||||
#define BIND_ENUM_CONSTANT(m_constant) \
|
||||
ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
#define BIND_VMETHOD(m_method) \
|
||||
ClassDB::add_virtual_method(get_class_static(), m_method);
|
||||
|
||||
#else
|
||||
|
||||
#define BIND_VMETHOD(m_method)
|
||||
|
||||
#endif
|
||||
|
||||
#endif // CLASS_DB_H
|
||||
436
core/color.cpp
436
core/color.cpp
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,95 +26,83 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "color.h"
|
||||
|
||||
#include "color_names.inc"
|
||||
#include "map.h"
|
||||
#include "math_funcs.h"
|
||||
#include "print_string.h"
|
||||
#include "map.h"
|
||||
#include "color_names.inc"
|
||||
|
||||
uint32_t Color::to_argb32() const {
|
||||
uint32_t Color::to_ARGB32() const {
|
||||
|
||||
uint32_t c = (uint8_t)(a * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(r * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(g * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(b * 255);
|
||||
uint32_t c=(uint8_t)(a*255);
|
||||
c<<=8;
|
||||
c|=(uint8_t)(r*255);
|
||||
c<<=8;
|
||||
c|=(uint8_t)(g*255);
|
||||
c<<=8;
|
||||
c|=(uint8_t)(b*255);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint32_t Color::to_abgr32() const {
|
||||
uint32_t c = (uint8_t)(a * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(b * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(g * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(r * 255);
|
||||
uint32_t Color::to_32() const {
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint32_t Color::to_rgba32() const {
|
||||
|
||||
uint32_t c = (uint8_t)(r * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(g * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(b * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(a * 255);
|
||||
uint32_t c=(uint8_t)(a*255);
|
||||
c<<=8;
|
||||
c|=(uint8_t)(r*255);
|
||||
c<<=8;
|
||||
c|=(uint8_t)(g*255);
|
||||
c<<=8;
|
||||
c|=(uint8_t)(b*255);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
float Color::get_h() const {
|
||||
|
||||
float min = MIN(r, g);
|
||||
min = MIN(min, b);
|
||||
float max = MAX(r, g);
|
||||
max = MAX(max, b);
|
||||
float min = MIN( r, g );
|
||||
min = MIN( min, b );
|
||||
float max = MAX( r, g );
|
||||
max = MAX( max, b );
|
||||
|
||||
float delta = max - min;
|
||||
|
||||
if (delta == 0)
|
||||
if( delta == 0 )
|
||||
return 0;
|
||||
|
||||
float h;
|
||||
if (r == max)
|
||||
h = (g - b) / delta; // between yellow & magenta
|
||||
else if (g == max)
|
||||
h = 2 + (b - r) / delta; // between cyan & yellow
|
||||
if( r == max )
|
||||
h = ( g - b ) / delta; // between yellow & magenta
|
||||
else if( g == max )
|
||||
h = 2 + ( b - r ) / delta; // between cyan & yellow
|
||||
else
|
||||
h = 4 + (r - g) / delta; // between magenta & cyan
|
||||
h = 4 + ( r - g ) / delta; // between magenta & cyan
|
||||
|
||||
h /= 6.0;
|
||||
if (h < 0)
|
||||
h += 1.0;
|
||||
h/=6.0;
|
||||
if (h<0)
|
||||
h+=1.0;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
float Color::get_s() const {
|
||||
|
||||
float min = MIN(r, g);
|
||||
min = MIN(min, b);
|
||||
float max = MAX(r, g);
|
||||
max = MAX(max, b);
|
||||
|
||||
float min = MIN( r, g );
|
||||
min = MIN( min, b );
|
||||
float max = MAX( r, g );
|
||||
max = MAX( max, b );
|
||||
|
||||
float delta = max - min;
|
||||
|
||||
return (max != 0) ? (delta / max) : 0;
|
||||
return (max!=0) ? (delta / max) : 0;
|
||||
|
||||
}
|
||||
|
||||
float Color::get_v() const {
|
||||
|
||||
float max = MAX(r, g);
|
||||
max = MAX(max, b);
|
||||
float max = MAX( r, g );
|
||||
max = MAX( max, b );
|
||||
return max;
|
||||
}
|
||||
|
||||
@ -123,24 +110,24 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
|
||||
|
||||
int i;
|
||||
float f, p, q, t;
|
||||
a = p_alpha;
|
||||
a=p_alpha;
|
||||
|
||||
if (p_s == 0) {
|
||||
if( p_s == 0 ) {
|
||||
// acp_hromatic (grey)
|
||||
r = g = b = p_v;
|
||||
return;
|
||||
}
|
||||
|
||||
p_h *= 6.0;
|
||||
p_h = Math::fmod(p_h, 6);
|
||||
i = Math::floor(p_h);
|
||||
p_h *=6.0;
|
||||
p_h = Math::fmod(p_h,6);
|
||||
i = Math::floor( p_h );
|
||||
|
||||
f = p_h - i;
|
||||
p = p_v * (1 - p_s);
|
||||
q = p_v * (1 - p_s * f);
|
||||
t = p_v * (1 - p_s * (1 - f));
|
||||
p = p_v * ( 1 - p_s );
|
||||
q = p_v * ( 1 - p_s * f );
|
||||
t = p_v * ( 1 - p_s * ( 1 - f ) );
|
||||
|
||||
switch (i) {
|
||||
switch( i ) {
|
||||
case 0: // Red is the dominant color
|
||||
r = p_v;
|
||||
g = t;
|
||||
@ -176,174 +163,170 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
|
||||
|
||||
void Color::invert() {
|
||||
|
||||
r = 1.0 - r;
|
||||
g = 1.0 - g;
|
||||
b = 1.0 - b;
|
||||
r=1.0-r;
|
||||
g=1.0-g;
|
||||
b=1.0-b;
|
||||
}
|
||||
void Color::contrast() {
|
||||
|
||||
r = Math::fmod(r + 0.5, 1.0);
|
||||
g = Math::fmod(g + 0.5, 1.0);
|
||||
b = Math::fmod(b + 0.5, 1.0);
|
||||
r=Math::fmod(r+0.5,1.0);
|
||||
g=Math::fmod(g+0.5,1.0);
|
||||
b=Math::fmod(b+0.5,1.0);
|
||||
}
|
||||
|
||||
Color Color::hex(uint32_t p_hex) {
|
||||
|
||||
float a = (p_hex & 0xFF) / 255.0;
|
||||
p_hex >>= 8;
|
||||
float b = (p_hex & 0xFF) / 255.0;
|
||||
p_hex >>= 8;
|
||||
float g = (p_hex & 0xFF) / 255.0;
|
||||
p_hex >>= 8;
|
||||
float r = (p_hex & 0xFF) / 255.0;
|
||||
float a = (p_hex&0xFF)/255.0;
|
||||
p_hex>>=8;
|
||||
float b = (p_hex&0xFF)/255.0;
|
||||
p_hex>>=8;
|
||||
float g = (p_hex&0xFF)/255.0;
|
||||
p_hex>>=8;
|
||||
float r = (p_hex&0xFF)/255.0;
|
||||
|
||||
return Color(r, g, b, a);
|
||||
return Color(r,g,b,a);
|
||||
}
|
||||
|
||||
static float _parse_col(const String &p_str, int p_ofs) {
|
||||
static float _parse_col(const String& p_str, int p_ofs) {
|
||||
|
||||
int ig = 0;
|
||||
int ig=0;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for(int i=0;i<2;i++) {
|
||||
|
||||
int c = p_str[i + p_ofs];
|
||||
int v = 0;
|
||||
int c=p_str[i+p_ofs];
|
||||
int v=0;
|
||||
|
||||
if (c >= '0' && c <= '9') {
|
||||
v = c - '0';
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
v = c - 'a';
|
||||
v += 10;
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
v = c - 'A';
|
||||
v += 10;
|
||||
if (c>='0' && c<='9') {
|
||||
v=c-'0';
|
||||
} else if (c>='a' && c<='f') {
|
||||
v=c-'a';
|
||||
v+=10;
|
||||
} else if (c>='A' && c<='F') {
|
||||
v=c-'A';
|
||||
v+=10;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
ig += v * 16;
|
||||
if (i==0)
|
||||
ig+=v*16;
|
||||
else
|
||||
ig += v;
|
||||
ig+=v;
|
||||
|
||||
}
|
||||
|
||||
return ig;
|
||||
|
||||
}
|
||||
|
||||
Color Color::inverted() const {
|
||||
|
||||
Color c = *this;
|
||||
Color c=*this;
|
||||
c.invert();
|
||||
return c;
|
||||
}
|
||||
|
||||
Color Color::contrasted() const {
|
||||
|
||||
Color c = *this;
|
||||
Color c=*this;
|
||||
c.contrast();
|
||||
return c;
|
||||
}
|
||||
|
||||
Color Color::html(const String &p_color) {
|
||||
|
||||
Color Color::html(const String& p_color) {
|
||||
|
||||
String color = p_color;
|
||||
if (color.length() == 0)
|
||||
if (color.length()==0)
|
||||
return Color();
|
||||
if (color[0] == '#')
|
||||
color = color.substr(1, color.length() - 1);
|
||||
if (color.length() == 3 || color.length() == 4) {
|
||||
String exp_color;
|
||||
for (int i = 0; i < color.length(); i++) {
|
||||
exp_color += color[i];
|
||||
exp_color += color[i];
|
||||
}
|
||||
color = exp_color;
|
||||
}
|
||||
if (color[0]=='#')
|
||||
color=color.substr(1,color.length()-1);
|
||||
|
||||
bool alpha = false;
|
||||
bool alpha=false;
|
||||
|
||||
if (color.length() == 8) {
|
||||
alpha = true;
|
||||
} else if (color.length() == 6) {
|
||||
alpha = false;
|
||||
if (color.length()==8) {
|
||||
alpha=true;
|
||||
} else if (color.length()==6) {
|
||||
alpha=false;
|
||||
} else {
|
||||
ERR_EXPLAIN("Invalid Color Code: " + p_color);
|
||||
ERR_EXPLAIN("Invalid Color Code: "+p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
|
||||
int a = 255;
|
||||
int a=255;
|
||||
if (alpha) {
|
||||
a = _parse_col(color, 0);
|
||||
if (a < 0) {
|
||||
ERR_EXPLAIN("Invalid Color Code: " + p_color);
|
||||
a=_parse_col(color,0);
|
||||
if (a<0) {
|
||||
ERR_EXPLAIN("Invalid Color Code: "+p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
}
|
||||
|
||||
int from = alpha ? 2 : 0;
|
||||
int from=alpha?2:0;
|
||||
|
||||
int r = _parse_col(color, from + 0);
|
||||
if (r < 0) {
|
||||
ERR_EXPLAIN("Invalid Color Code: " + p_color);
|
||||
int r=_parse_col(color,from+0);
|
||||
if (r<0) {
|
||||
ERR_EXPLAIN("Invalid Color Code: "+p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
int g = _parse_col(color, from + 2);
|
||||
if (g < 0) {
|
||||
ERR_EXPLAIN("Invalid Color Code: " + p_color);
|
||||
int g=_parse_col(color,from+2);
|
||||
if (g<0) {
|
||||
ERR_EXPLAIN("Invalid Color Code: "+p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
int b = _parse_col(color, from + 4);
|
||||
if (b < 0) {
|
||||
ERR_EXPLAIN("Invalid Color Code: " + p_color);
|
||||
int b=_parse_col(color,from+4);
|
||||
if (b<0) {
|
||||
ERR_EXPLAIN("Invalid Color Code: "+p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
|
||||
return Color(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
|
||||
return Color(r/255.0,g/255.0,b/255.0,a/255.0);
|
||||
}
|
||||
|
||||
bool Color::html_is_valid(const String &p_color) {
|
||||
bool Color::html_is_valid(const String& p_color) {
|
||||
|
||||
String color = p_color;
|
||||
|
||||
if (color.length() == 0)
|
||||
if (color.length()==0)
|
||||
return false;
|
||||
if (color[0] == '#')
|
||||
color = color.substr(1, color.length() - 1);
|
||||
if (color[0]=='#')
|
||||
color=color.substr(1,color.length()-1);
|
||||
|
||||
bool alpha = false;
|
||||
bool alpha=false;
|
||||
|
||||
if (color.length() == 8) {
|
||||
alpha = true;
|
||||
} else if (color.length() == 6) {
|
||||
alpha = false;
|
||||
if (color.length()==8) {
|
||||
alpha=true;
|
||||
} else if (color.length()==6) {
|
||||
alpha=false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
int a = 255;
|
||||
int a=255;
|
||||
if (alpha) {
|
||||
a = _parse_col(color, 0);
|
||||
if (a < 0) {
|
||||
a=_parse_col(color,0);
|
||||
if (a<0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int from = alpha ? 2 : 0;
|
||||
int from=alpha?2:0;
|
||||
|
||||
int r = _parse_col(color, from + 0);
|
||||
if (r < 0) {
|
||||
int r=_parse_col(color,from+0);
|
||||
if (r<0) {
|
||||
return false;
|
||||
}
|
||||
int g = _parse_col(color, from + 2);
|
||||
if (g < 0) {
|
||||
int g=_parse_col(color,from+2);
|
||||
if (g<0) {
|
||||
return false;
|
||||
}
|
||||
int b = _parse_col(color, from + 4);
|
||||
if (b < 0) {
|
||||
int b=_parse_col(color,from+4);
|
||||
if (b<0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
Color Color::named(const String &p_name) {
|
||||
@ -356,12 +339,12 @@ Color Color::named(const String &p_name) {
|
||||
name = name.replace("'", "");
|
||||
name = name.replace(".", "");
|
||||
name = name.to_lower();
|
||||
|
||||
const Map<String, Color>::Element *color = _named_colors.find(name);
|
||||
if (color) {
|
||||
|
||||
const Map<String, Color>::Element* color = _named_colors.find(name);
|
||||
if(color) {
|
||||
return color->value();
|
||||
} else {
|
||||
ERR_EXPLAIN("Invalid Color Name: " + p_name);
|
||||
ERR_EXPLAIN("Invalid Color Name: "+p_name);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
}
|
||||
@ -369,161 +352,48 @@ Color Color::named(const String &p_name) {
|
||||
String _to_hex(float p_val) {
|
||||
|
||||
int v = p_val * 255;
|
||||
v = CLAMP(v, 0, 255);
|
||||
v = CLAMP(v,0,255);
|
||||
String ret;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for(int i=0;i<2;i++) {
|
||||
|
||||
CharType c[2] = { 0, 0 };
|
||||
int lv = v & 0xF;
|
||||
if (lv < 10)
|
||||
c[0] = '0' + lv;
|
||||
CharType c[2]={0,0};
|
||||
int lv = v&0xF;
|
||||
if (lv<10)
|
||||
c[0]='0'+lv;
|
||||
else
|
||||
c[0] = 'a' + lv - 10;
|
||||
c[0]='a'+lv-10;
|
||||
|
||||
v >>= 4;
|
||||
String cs = (const CharType *)c;
|
||||
v>>=4;
|
||||
String cs=(const CharType*)c;
|
||||
ret = cs + ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
String Color::to_html(bool p_alpha) const {
|
||||
|
||||
String txt;
|
||||
txt += _to_hex(r);
|
||||
txt += _to_hex(g);
|
||||
txt += _to_hex(b);
|
||||
txt+=_to_hex(r);
|
||||
txt+=_to_hex(g);
|
||||
txt+=_to_hex(b);
|
||||
if (p_alpha)
|
||||
txt = _to_hex(a) + txt;
|
||||
txt=_to_hex(a)+txt;
|
||||
return txt;
|
||||
|
||||
}
|
||||
|
||||
|
||||
float Color::gray() const {
|
||||
|
||||
return (r + g + b) / 3.0;
|
||||
return (r+g+b)/3.0;
|
||||
}
|
||||
|
||||
Color::operator String() const {
|
||||
|
||||
return rtos(r) + ", " + rtos(g) + ", " + rtos(b) + ", " + rtos(a);
|
||||
return rtos(r)+", "+rtos(g)+", "+rtos(b)+", "+rtos(a);
|
||||
}
|
||||
|
||||
Color Color::operator+(const Color &p_color) const {
|
||||
|
||||
return Color(
|
||||
r + p_color.r,
|
||||
g + p_color.g,
|
||||
b + p_color.b,
|
||||
a + p_color.a);
|
||||
}
|
||||
|
||||
void Color::operator+=(const Color &p_color) {
|
||||
|
||||
r = r + p_color.r;
|
||||
g = g + p_color.g;
|
||||
b = b + p_color.b;
|
||||
a = a + p_color.a;
|
||||
}
|
||||
|
||||
Color Color::operator-(const Color &p_color) const {
|
||||
|
||||
return Color(
|
||||
r - p_color.r,
|
||||
g - p_color.g,
|
||||
b - p_color.b,
|
||||
a - p_color.a);
|
||||
}
|
||||
|
||||
void Color::operator-=(const Color &p_color) {
|
||||
|
||||
r = r - p_color.r;
|
||||
g = g - p_color.g;
|
||||
b = b - p_color.b;
|
||||
a = a - p_color.a;
|
||||
}
|
||||
|
||||
Color Color::operator*(const Color &p_color) const {
|
||||
|
||||
return Color(
|
||||
r * p_color.r,
|
||||
g * p_color.g,
|
||||
b * p_color.b,
|
||||
a * p_color.a);
|
||||
}
|
||||
|
||||
Color Color::operator*(const real_t &rvalue) const {
|
||||
|
||||
return Color(
|
||||
r * rvalue,
|
||||
g * rvalue,
|
||||
b * rvalue,
|
||||
a * rvalue);
|
||||
}
|
||||
|
||||
void Color::operator*=(const Color &p_color) {
|
||||
|
||||
r = r * p_color.r;
|
||||
g = g * p_color.g;
|
||||
b = b * p_color.b;
|
||||
a = a * p_color.a;
|
||||
}
|
||||
|
||||
void Color::operator*=(const real_t &rvalue) {
|
||||
|
||||
r = r * rvalue;
|
||||
g = g * rvalue;
|
||||
b = b * rvalue;
|
||||
a = a * rvalue;
|
||||
}
|
||||
|
||||
Color Color::operator/(const Color &p_color) const {
|
||||
|
||||
return Color(
|
||||
r / p_color.r,
|
||||
g / p_color.g,
|
||||
b / p_color.b,
|
||||
a / p_color.a);
|
||||
}
|
||||
|
||||
Color Color::operator/(const real_t &rvalue) const {
|
||||
|
||||
return Color(
|
||||
r / rvalue,
|
||||
g / rvalue,
|
||||
b / rvalue,
|
||||
a / rvalue);
|
||||
}
|
||||
|
||||
void Color::operator/=(const Color &p_color) {
|
||||
|
||||
r = r / p_color.r;
|
||||
g = g / p_color.g;
|
||||
b = b / p_color.b;
|
||||
a = a / p_color.a;
|
||||
}
|
||||
|
||||
void Color::operator/=(const real_t &rvalue) {
|
||||
|
||||
if (rvalue == 0) {
|
||||
r = 1.0;
|
||||
g = 1.0;
|
||||
b = 1.0;
|
||||
a = 1.0;
|
||||
} else {
|
||||
r = r / rvalue;
|
||||
g = g / rvalue;
|
||||
b = b / rvalue;
|
||||
a = a / rvalue;
|
||||
}
|
||||
};
|
||||
|
||||
Color Color::operator-() const {
|
||||
|
||||
return Color(
|
||||
1.0 - r,
|
||||
1.0 - g,
|
||||
1.0 - b,
|
||||
1.0 - a);
|
||||
}
|
||||
|
||||
172
core/color.h
172
core/color.h
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,12 +26,11 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef COLOR_H
|
||||
#define COLOR_H
|
||||
|
||||
#include "math_funcs.h"
|
||||
#include "ustring.h"
|
||||
#include "math_funcs.h"
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
@ -49,122 +47,53 @@ struct Color {
|
||||
float components[4];
|
||||
};
|
||||
|
||||
bool operator==(const Color &p_color) const { return (r == p_color.r && g == p_color.g && b == p_color.b && a == p_color.a); }
|
||||
bool operator!=(const Color &p_color) const { return (r != p_color.r || g != p_color.g || b != p_color.b || a != p_color.a); }
|
||||
bool operator==(const Color &p_color) const { return (r==p_color.r && g==p_color.g && b==p_color.b && a==p_color.a ); }
|
||||
bool operator!=(const Color &p_color) const { return (r!=p_color.r || g!=p_color.g || b!=p_color.b || a!=p_color.a ); }
|
||||
|
||||
uint32_t to_rgba32() const;
|
||||
uint32_t to_argb32() const;
|
||||
uint32_t to_abgr32() const;
|
||||
uint32_t to_32() const;
|
||||
uint32_t to_ARGB32() const;
|
||||
float gray() const;
|
||||
float get_h() const;
|
||||
float get_s() const;
|
||||
float get_v() const;
|
||||
void set_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0);
|
||||
void set_hsv(float p_h, float p_s, float p_v, float p_alpha=1.0);
|
||||
|
||||
_FORCE_INLINE_ float &operator[](int idx) {
|
||||
_FORCE_INLINE_ float& operator[](int idx) {
|
||||
return components[idx];
|
||||
}
|
||||
_FORCE_INLINE_ const float &operator[](int idx) const {
|
||||
_FORCE_INLINE_ const float& operator[](int idx) const {
|
||||
return components[idx];
|
||||
}
|
||||
|
||||
Color operator+(const Color &p_color) const;
|
||||
void operator+=(const Color &p_color);
|
||||
|
||||
Color operator-() const;
|
||||
Color operator-(const Color &p_color) const;
|
||||
void operator-=(const Color &p_color);
|
||||
|
||||
Color operator*(const Color &p_color) const;
|
||||
Color operator*(const real_t &rvalue) const;
|
||||
void operator*=(const Color &p_color);
|
||||
void operator*=(const real_t &rvalue);
|
||||
|
||||
Color operator/(const Color &p_color) const;
|
||||
Color operator/(const real_t &rvalue) const;
|
||||
void operator/=(const Color &p_color);
|
||||
void operator/=(const real_t &rvalue);
|
||||
|
||||
void invert();
|
||||
void contrast();
|
||||
Color inverted() const;
|
||||
Color contrasted() const;
|
||||
|
||||
_FORCE_INLINE_ Color linear_interpolate(const Color &p_b, float p_t) const {
|
||||
_FORCE_INLINE_ Color linear_interpolate(const Color& p_b, float p_t) const {
|
||||
|
||||
Color res = *this;
|
||||
Color res=*this;
|
||||
|
||||
res.r += (p_t * (p_b.r - r));
|
||||
res.g += (p_t * (p_b.g - g));
|
||||
res.b += (p_t * (p_b.b - b));
|
||||
res.a += (p_t * (p_b.a - a));
|
||||
res.r+= (p_t * (p_b.r-r));
|
||||
res.g+= (p_t * (p_b.g-g));
|
||||
res.b+= (p_t * (p_b.b-b));
|
||||
res.a+= (p_t * (p_b.a-a));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ Color darkened(float p_amount) const {
|
||||
_FORCE_INLINE_ Color blend(const Color& p_over) const {
|
||||
|
||||
Color res = *this;
|
||||
res.r = res.r * (1.0f - p_amount);
|
||||
res.g = res.g * (1.0f - p_amount);
|
||||
res.b = res.b * (1.0f - p_amount);
|
||||
return res;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ Color lightened(float p_amount) const {
|
||||
|
||||
Color res = *this;
|
||||
res.r = res.r + (1.0f - res.r) * p_amount;
|
||||
res.g = res.g + (1.0f - res.g) * p_amount;
|
||||
res.b = res.b + (1.0f - res.b) * p_amount;
|
||||
return res;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ uint32_t to_rgbe9995() const {
|
||||
|
||||
const float pow2to9 = 512.0f;
|
||||
const float B = 15.0f;
|
||||
//const float Emax = 31.0f;
|
||||
const float N = 9.0f;
|
||||
|
||||
float sharedexp = 65408.000f; //(( pow2to9 - 1.0f)/ pow2to9)*powf( 2.0f, 31.0f - 15.0f);
|
||||
|
||||
float cRed = MAX(0.0f, MIN(sharedexp, r));
|
||||
float cGreen = MAX(0.0f, MIN(sharedexp, g));
|
||||
float cBlue = MAX(0.0f, MIN(sharedexp, b));
|
||||
|
||||
float cMax = MAX(cRed, MAX(cGreen, cBlue));
|
||||
|
||||
// expp = MAX(-B - 1, log2(maxc)) + 1 + B
|
||||
|
||||
float expp = MAX(-B - 1.0f, floor(Math::log(cMax) / Math_LN2)) + 1.0f + B;
|
||||
|
||||
float sMax = (float)floor((cMax / Math::pow(2.0f, expp - B - N)) + 0.5f);
|
||||
|
||||
float exps = expp + 1.0f;
|
||||
|
||||
if (0.0 <= sMax && sMax < pow2to9) {
|
||||
exps = expp;
|
||||
}
|
||||
|
||||
float sRed = Math::floor((cRed / pow(2.0f, exps - B - N)) + 0.5f);
|
||||
float sGreen = Math::floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
|
||||
float sBlue = Math::floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
|
||||
|
||||
return (uint32_t(Math::fast_ftoi(sRed)) & 0x1FF) | ((uint32_t(Math::fast_ftoi(sGreen)) & 0x1FF) << 9) | ((uint32_t(Math::fast_ftoi(sBlue)) & 0x1FF) << 18) | ((uint32_t(Math::fast_ftoi(exps)) & 0x1F) << 27);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ Color blend(const Color &p_over) const {
|
||||
|
||||
Color res;
|
||||
float sa = 1.0 - p_over.a;
|
||||
res.a = a * sa + p_over.a;
|
||||
if (res.a == 0) {
|
||||
return Color(0, 0, 0, 0);
|
||||
res.a = a*sa+p_over.a;
|
||||
if (res.a==0) {
|
||||
return Color(0,0,0,0);
|
||||
} else {
|
||||
res.r = (r * a * sa + p_over.r * p_over.a) / res.a;
|
||||
res.g = (g * a * sa + p_over.g * p_over.a) / res.a;
|
||||
res.b = (b * a * sa + p_over.b * p_over.a) / res.a;
|
||||
res.r = (r*a*sa + p_over.r * p_over.a)/res.a;
|
||||
res.g = (g*a*sa + p_over.g * p_over.a)/res.a;
|
||||
res.b = (b*a*sa + p_over.b * p_over.a)/res.a;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -172,61 +101,48 @@ struct Color {
|
||||
_FORCE_INLINE_ Color to_linear() const {
|
||||
|
||||
return Color(
|
||||
r < 0.04045 ? r * (1.0 / 12.92) : Math::pow((r + 0.055) * (1.0 / (1 + 0.055)), 2.4),
|
||||
g < 0.04045 ? g * (1.0 / 12.92) : Math::pow((g + 0.055) * (1.0 / (1 + 0.055)), 2.4),
|
||||
b < 0.04045 ? b * (1.0 / 12.92) : Math::pow((b + 0.055) * (1.0 / (1 + 0.055)), 2.4),
|
||||
a);
|
||||
}
|
||||
_FORCE_INLINE_ Color to_srgb() const {
|
||||
|
||||
return Color(
|
||||
r < 0.0031308 ? 12.92 * r : (1.0 + 0.055) * Math::pow(r, 1.0f / 2.4f) - 0.055,
|
||||
g < 0.0031308 ? 12.92 * g : (1.0 + 0.055) * Math::pow(g, 1.0f / 2.4f) - 0.055,
|
||||
b < 0.0031308 ? 12.92 * b : (1.0 + 0.055) * Math::pow(b, 1.0f / 2.4f) - 0.055, a);
|
||||
r<0.04045 ? r * (1.0 / 12.92) : Math::pow((r + 0.055) * (1.0 / (1 + 0.055)), 2.4),
|
||||
g<0.04045 ? g * (1.0 / 12.92) : Math::pow((g + 0.055) * (1.0 / (1 + 0.055)), 2.4),
|
||||
b<0.04045 ? b * (1.0 / 12.92) : Math::pow((b + 0.055) * (1.0 / (1 + 0.055)), 2.4),
|
||||
a
|
||||
);
|
||||
}
|
||||
|
||||
static Color hex(uint32_t p_hex);
|
||||
static Color html(const String &p_color);
|
||||
static bool html_is_valid(const String &p_color);
|
||||
static Color named(const String &p_name);
|
||||
String to_html(bool p_alpha = true) const;
|
||||
static Color html(const String& p_color);
|
||||
static bool html_is_valid(const String& p_color);
|
||||
static Color named(const String& p_name);
|
||||
String to_html(bool p_alpha=true) const;
|
||||
|
||||
_FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys
|
||||
_FORCE_INLINE_ bool operator<(const Color& p_color) const; //used in set keys
|
||||
operator String() const;
|
||||
|
||||
/**
|
||||
* No construct parameters, r=0, g=0, b=0. a=255
|
||||
*/
|
||||
_FORCE_INLINE_ Color() {
|
||||
r = 0;
|
||||
g = 0;
|
||||
b = 0;
|
||||
a = 1.0;
|
||||
r=0; g=0; b=0; a=1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* RGB / RGBA construct parameters. Alpha is optional, but defaults to 1.0
|
||||
*/
|
||||
_FORCE_INLINE_ Color(float p_r, float p_g, float p_b, float p_a = 1.0) {
|
||||
r = p_r;
|
||||
g = p_g;
|
||||
b = p_b;
|
||||
a = p_a;
|
||||
}
|
||||
_FORCE_INLINE_ Color(float p_r,float p_g,float p_b,float p_a=1.0) { r=p_r; g=p_g; b=p_b; a=p_a; }
|
||||
};
|
||||
|
||||
bool Color::operator<(const Color &p_color) const {
|
||||
bool Color::operator<(const Color& p_color) const {
|
||||
|
||||
if (r == p_color.r) {
|
||||
if (g == p_color.g) {
|
||||
if (b == p_color.b) {
|
||||
return (a < p_color.a);
|
||||
if (r==p_color.r) {
|
||||
if (g==p_color.g) {
|
||||
if(b==p_color.b) {
|
||||
return (a<p_color.a);
|
||||
} else
|
||||
return (b < p_color.b);
|
||||
return (b<p_color.b);
|
||||
} else
|
||||
return g < p_color.g;
|
||||
return g<p_color.g;
|
||||
} else
|
||||
return r < p_color.r;
|
||||
return r<p_color.r;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
// Names from https://en.wikipedia.org/wiki/List_of_colors (through https://raw.githubusercontent.com/SuperUserNameMan/color_to_name/616a7cddafefda91478b7bc26167de97fb5badb1/godot_version.gd), slightly edited and normalized
|
||||
#include "map.h"
|
||||
|
||||
static Map<String, Color> _named_colors;
|
||||
static void _populate_named_colors() {
|
||||
if(!_named_colors.empty()) return;
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,9 +26,7 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "command_queue_mt.h"
|
||||
|
||||
#include "os/os.h"
|
||||
|
||||
void CommandQueueMT::lock() {
|
||||
@ -50,24 +47,22 @@ void CommandQueueMT::wait_for_flush() {
|
||||
OS::get_singleton()->delay_usec(1000);
|
||||
}
|
||||
|
||||
CommandQueueMT::SyncSemaphore *CommandQueueMT::_alloc_sync_sem() {
|
||||
CommandQueueMT::SyncSemaphore* CommandQueueMT::_alloc_sync_sem() {
|
||||
|
||||
int idx = -1;
|
||||
int idx=-1;
|
||||
|
||||
while (true) {
|
||||
while(true) {
|
||||
|
||||
lock();
|
||||
for (int i = 0; i < SYNC_SEMAPHORES; i++) {
|
||||
for(int i=0;i<SYNC_SEMAPHORES;i++) {
|
||||
|
||||
if (!sync_sems[i].in_use) {
|
||||
sync_sems[i].in_use = true;
|
||||
idx = i;
|
||||
sync_sems[i].in_use=true;
|
||||
idx=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
|
||||
if (idx == -1) {
|
||||
if (idx==-1) {
|
||||
wait_for_flush();
|
||||
} else {
|
||||
break;
|
||||
@ -77,54 +72,36 @@ CommandQueueMT::SyncSemaphore *CommandQueueMT::_alloc_sync_sem() {
|
||||
return &sync_sems[idx];
|
||||
}
|
||||
|
||||
bool CommandQueueMT::dealloc_one() {
|
||||
tryagain:
|
||||
if (dealloc_ptr == write_ptr) {
|
||||
// The queue is empty
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t size = *(uint32_t *)&command_mem[dealloc_ptr];
|
||||
CommandQueueMT::CommandQueueMT(bool p_sync){
|
||||
|
||||
if (size == 0) {
|
||||
// End of command buffer wrap down
|
||||
dealloc_ptr = 0;
|
||||
goto tryagain;
|
||||
}
|
||||
|
||||
if (size & 1) {
|
||||
// Still used, nothing can be deallocated
|
||||
return false;
|
||||
}
|
||||
|
||||
dealloc_ptr += (size >> 1) + sizeof(uint32_t);
|
||||
return true;
|
||||
}
|
||||
|
||||
CommandQueueMT::CommandQueueMT(bool p_sync) {
|
||||
|
||||
read_ptr = 0;
|
||||
write_ptr = 0;
|
||||
read_ptr=0;
|
||||
write_ptr=0;
|
||||
mutex = Mutex::create();
|
||||
|
||||
for (int i = 0; i < SYNC_SEMAPHORES; i++) {
|
||||
for(int i=0;i<SYNC_SEMAPHORES;i++) {
|
||||
|
||||
sync_sems[i].sem=Semaphore::create();
|
||||
sync_sems[i].in_use=false;
|
||||
|
||||
|
||||
sync_sems[i].sem = Semaphore::create();
|
||||
sync_sems[i].in_use = false;
|
||||
}
|
||||
if (p_sync)
|
||||
sync = Semaphore::create();
|
||||
else
|
||||
sync = NULL;
|
||||
sync=NULL;
|
||||
}
|
||||
|
||||
|
||||
CommandQueueMT::~CommandQueueMT() {
|
||||
|
||||
if (sync)
|
||||
memdelete(sync);
|
||||
memdelete(mutex);
|
||||
for (int i = 0; i < SYNC_SEMAPHORES; i++) {
|
||||
for(int i=0;i<SYNC_SEMAPHORES;i++) {
|
||||
|
||||
memdelete(sync_sems[i].sem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,15 +26,222 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "compressed_translation.h"
|
||||
|
||||
#include "pair.h"
|
||||
#include <string.h>
|
||||
|
||||
extern "C" {
|
||||
#include "thirdparty/misc/smaz.h"
|
||||
/////////// SMAZ /////////////
|
||||
|
||||
/*
|
||||
Copyright (c) 2006-2009, Salvatore Sanfilippo
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Smaz nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
/* Our compression codebook, used for compression */
|
||||
static const char *Smaz_cb[241] = {
|
||||
"\002s,\266", "\003had\232\002leW", "\003on \216", "", "\001yS",
|
||||
"\002ma\255\002li\227", "\003or \260", "", "\002ll\230\003s t\277",
|
||||
"\004fromg\002mel", "", "\003its\332", "\001z\333", "\003ingF", "\001>\336",
|
||||
"\001 \000\003 (\002nc\344", "\002nd=\003 on\312",
|
||||
"\002ne\213\003hat\276\003re q", "", "\002ngT\003herz\004have\306\003s o\225",
|
||||
"", "\003ionk\003s a\254\002ly\352", "\003hisL\003 inN\003 be\252", "",
|
||||
"\003 fo\325\003 of \003 ha\311", "", "\002of\005",
|
||||
"\003 co\241\002no\267\003 ma\370", "", "", "\003 cl\356\003enta\003 an7",
|
||||
"\002ns\300\001\"e", "\003n t\217\002ntP\003s, \205",
|
||||
"\002pe\320\003 we\351\002om\223", "\002on\037", "", "\002y G", "\003 wa\271",
|
||||
"\003 re\321\002or*", "", "\002=\"\251\002ot\337", "\003forD\002ou[",
|
||||
"\003 toR", "\003 th\r", "\003 it\366",
|
||||
"\003but\261\002ra\202\003 wi\363\002</\361", "\003 wh\237", "\002 4",
|
||||
"\003nd ?", "\002re!", "", "\003ng c", "",
|
||||
"\003ly \307\003ass\323\001a\004\002rir", "", "", "", "\002se_", "\003of \"",
|
||||
"\003div\364\002ros\003ere\240", "", "\002ta\310\001bZ\002si\324", "",
|
||||
"\003and\a\002rs\335", "\002rt\362", "\002teE", "\003ati\316", "\002so\263",
|
||||
"\002th\021", "\002tiJ\001c\034\003allp", "\003ate\345", "\002ss\246",
|
||||
"\002stM", "", "\002><\346", "\002to\024", "\003arew", "\001d\030",
|
||||
"\002tr\303", "", "\001\n1\003 a \222", "\003f tv\002veo", "\002un\340", "",
|
||||
"\003e o\242", "\002a \243\002wa\326\001e\002", "\002ur\226\003e a\274",
|
||||
"\002us\244\003\n\r\n\247", "\002ut\304\003e c\373", "\002we\221", "", "",
|
||||
"\002wh\302", "\001f,", "", "", "", "\003d t\206", "", "", "\003th \343",
|
||||
"\001g;", "", "", "\001\r9\003e s\265", "\003e t\234", "", "\003to Y",
|
||||
"\003e\r\n\236", "\002d \036\001h\022", "", "\001,Q", "\002 a\031", "\002 b^",
|
||||
"\002\r\n\025\002 cI", "\002 d\245", "\002 e\253", "\002 fh\001i\b\002e \v",
|
||||
"", "\002 hU\001-\314", "\002 i8", "", "", "\002 l\315", "\002 m{",
|
||||
"\002f :\002 n\354", "\002 o\035", "\002 p}\001.n\003\r\n\r\250", "",
|
||||
"\002 r\275", "\002 s>", "\002 t\016", "", "\002g \235\005which+\003whi\367",
|
||||
"\002 w5", "\001/\305", "\003as \214", "\003at \207", "", "\003who\331", "",
|
||||
"\001l\026\002h \212", "", "\002, $", "", "\004withV", "", "", "", "\001m-", "",
|
||||
"", "\002ac\357", "\002ad\350", "\003TheH", "", "", "\004this\233\001n\t",
|
||||
"", "\002. y", "", "\002alX\003e, \365", "\003tio\215\002be\\",
|
||||
"\002an\032\003ver\347", "", "\004that0\003tha\313\001o\006", "\003was2",
|
||||
"\002arO", "\002as.", "\002at'\003the\001\004they\200\005there\322\005theird",
|
||||
"\002ce\210", "\004were]", "", "\002ch\231\002l \264\001p<", "", "",
|
||||
"\003one\256", "", "\003he \023\002dej", "\003ter\270", "\002cou", "",
|
||||
"\002by\177\002di\201\002eax", "", "\002ec\327", "\002edB", "\002ee\353", "",
|
||||
"", "\001r\f\002n )", "", "", "", "\002el\262", "", "\003in i\002en3", "",
|
||||
"\002o `\001s\n", "", "\002er\033", "\003is t\002es6", "", "\002ge\371",
|
||||
"\004.com\375", "\002fo\334\003our\330", "\003ch \301\001t\003", "\002hab", "",
|
||||
"\003men\374", "", "\002he\020", "", "", "\001u&", "\002hif", "",
|
||||
"\003not\204\002ic\203", "\003ed @\002id\355", "", "", "\002ho\273",
|
||||
"\002r K\001vm", "", "", "", "\003t t\257\002il\360", "\002im\342",
|
||||
"\003en \317\002in\017", "\002io\220", "\002s \027\001wA", "", "\003er |",
|
||||
"\003es ~\002is%", "\002it/", "", "\002iv\272", "",
|
||||
"\002t #\ahttp://C\001x\372", "\002la\211", "\001<\341", "\003, a\224"
|
||||
};
|
||||
|
||||
/* Reverse compression codebook, used for decompression */
|
||||
static const char *Smaz_rcb[254] = {
|
||||
" ", "the", "e", "t", "a", "of", "o", "and", "i", "n", "s", "e ", "r", " th",
|
||||
" t", "in", "he", "th", "h", "he ", "to", "\r\n", "l", "s ", "d", " a", "an",
|
||||
"er", "c", " o", "d ", "on", " of", "re", "of ", "t ", ", ", "is", "u", "at",
|
||||
" ", "n ", "or", "which", "f", "m", "as", "it", "that", "\n", "was", "en",
|
||||
" ", " w", "es", " an", " i", "\r", "f ", "g", "p", "nd", " s", "nd ", "ed ",
|
||||
"w", "ed", "http://", "for", "te", "ing", "y ", "The", " c", "ti", "r ", "his",
|
||||
"st", " in", "ar", "nt", ",", " to", "y", "ng", " h", "with", "le", "al", "to ",
|
||||
"b", "ou", "be", "were", " b", "se", "o ", "ent", "ha", "ng ", "their", "\"",
|
||||
"hi", "from", " f", "in ", "de", "ion", "me", "v", ".", "ve", "all", "re ",
|
||||
"ri", "ro", "is ", "co", "f t", "are", "ea", ". ", "her", " m", "er ", " p",
|
||||
"es ", "by", "they", "di", "ra", "ic", "not", "s, ", "d t", "at ", "ce", "la",
|
||||
"h ", "ne", "as ", "tio", "on ", "n t", "io", "we", " a ", "om", ", a", "s o",
|
||||
"ur", "li", "ll", "ch", "had", "this", "e t", "g ", "e\r\n", " wh", "ere",
|
||||
" co", "e o", "a ", "us", " d", "ss", "\n\r\n", "\r\n\r", "=\"", " be", " e",
|
||||
"s a", "ma", "one", "t t", "or ", "but", "el", "so", "l ", "e s", "s,", "no",
|
||||
"ter", " wa", "iv", "ho", "e a", " r", "hat", "s t", "ns", "ch ", "wh", "tr",
|
||||
"ut", "/", "have", "ly ", "ta", " ha", " on", "tha", "-", " l", "ati", "en ",
|
||||
"pe", " re", "there", "ass", "si", " fo", "wa", "ec", "our", "who", "its", "z",
|
||||
"fo", "rs", ">", "ot", "un", "<", "im", "th ", "nc", "ate", "><", "ver", "ad",
|
||||
" we", "ly", "ee", " n", "id", " cl", "ac", "il", "</", "rt", " wi", "div",
|
||||
"e, ", " it", "whi", " ma", "ge", "x", "e c", "men", ".com"
|
||||
};
|
||||
|
||||
static int smaz_compress(const char *in, int inlen, char *out, int outlen) {
|
||||
unsigned int h1,h2,h3=0;
|
||||
int verblen = 0, _outlen = outlen;
|
||||
char verb[256], *_out = out;
|
||||
|
||||
while(inlen) {
|
||||
int j = 7, needed;
|
||||
char *flush = NULL;
|
||||
const char *slot;
|
||||
|
||||
h1 = h2 = in[0]<<3;
|
||||
if (inlen > 1) h2 += in[1];
|
||||
if (inlen > 2) h3 = h2^in[2];
|
||||
if (j > inlen) j = inlen;
|
||||
|
||||
/* Try to lookup substrings into the hash table, starting from the
|
||||
* longer to the shorter substrings */
|
||||
for (; j > 0; j--) {
|
||||
switch(j) {
|
||||
case 1: slot = Smaz_cb[h1%241]; break;
|
||||
case 2: slot = Smaz_cb[h2%241]; break;
|
||||
default: slot = Smaz_cb[h3%241]; break;
|
||||
}
|
||||
while(slot[0]) {
|
||||
if (slot[0] == j && memcmp(slot+1,in,j) == 0) {
|
||||
/* Match found in the hash table,
|
||||
* prepare a verbatim bytes flush if needed */
|
||||
if (verblen) {
|
||||
needed = (verblen == 1) ? 2 : 2+verblen;
|
||||
flush = out;
|
||||
out += needed;
|
||||
outlen -= needed;
|
||||
}
|
||||
/* Emit the byte */
|
||||
if (outlen <= 0) return _outlen+1;
|
||||
out[0] = slot[slot[0]+1];
|
||||
out++;
|
||||
outlen--;
|
||||
inlen -= j;
|
||||
in += j;
|
||||
goto out;
|
||||
} else {
|
||||
slot += slot[0]+2;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Match not found - add the byte to the verbatim buffer */
|
||||
verb[verblen] = in[0];
|
||||
verblen++;
|
||||
inlen--;
|
||||
in++;
|
||||
out:
|
||||
/* Prepare a flush if we reached the flush length limit, and there
|
||||
* is not already a pending flush operation. */
|
||||
if (!flush && (verblen == 256 || (verblen > 0 && inlen == 0))) {
|
||||
needed = (verblen == 1) ? 2 : 2+verblen;
|
||||
flush = out;
|
||||
out += needed;
|
||||
outlen -= needed;
|
||||
if (outlen < 0) return _outlen+1;
|
||||
}
|
||||
/* Perform a verbatim flush if needed */
|
||||
if (flush) {
|
||||
if (verblen == 1) {
|
||||
flush[0] = (signed char)254;
|
||||
flush[1] = verb[0];
|
||||
} else {
|
||||
flush[0] = (signed char)255;
|
||||
flush[1] = (signed char)(verblen-1);
|
||||
memcpy(flush+2,verb,verblen);
|
||||
}
|
||||
flush = NULL;
|
||||
verblen = 0;
|
||||
}
|
||||
}
|
||||
return out-_out;
|
||||
}
|
||||
|
||||
static int smaz_decompress(const char *in, int inlen, char *out, int outlen) {
|
||||
unsigned char *c = (unsigned char*) in;
|
||||
char *_out = out;
|
||||
int _outlen = outlen;
|
||||
|
||||
while(inlen) {
|
||||
if (*c == 254) {
|
||||
/* Verbatim byte */
|
||||
if (outlen < 1) return _outlen+1;
|
||||
*out = *(c+1);
|
||||
out++;
|
||||
outlen--;
|
||||
c += 2;
|
||||
inlen -= 2;
|
||||
} else if (*c == 255) {
|
||||
/* Verbatim string */
|
||||
int len = (*(c+1))+1;
|
||||
if (outlen < len) return _outlen+1;
|
||||
memcpy(out,c+2,len);
|
||||
out += len;
|
||||
outlen -= len;
|
||||
c += 2+len;
|
||||
inlen -= 2+len;
|
||||
} else {
|
||||
/* Codebook entry */
|
||||
const char *s = Smaz_rcb[*c];
|
||||
int len = strlen(s);
|
||||
|
||||
if (outlen < len) return _outlen+1;
|
||||
memcpy(out,s,len);
|
||||
out += len;
|
||||
outlen -= len;
|
||||
c++;
|
||||
inlen--;
|
||||
}
|
||||
}
|
||||
return out-_out;
|
||||
}
|
||||
|
||||
|
||||
/////////// END OF SMAZ /////////////
|
||||
|
||||
struct _PHashTranslationCmp {
|
||||
|
||||
int orig_len;
|
||||
@ -48,267 +254,281 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) {
|
||||
List<StringName> keys;
|
||||
p_from->get_message_list(&keys);
|
||||
|
||||
int size = Math::larger_prime(keys.size());
|
||||
int size=Math::larger_prime(keys.size());
|
||||
|
||||
print_line("compressing keys: " + itos(keys.size()));
|
||||
Vector<Vector<Pair<int, CharString> > > buckets;
|
||||
Vector<Map<uint32_t, int> > table;
|
||||
Vector<uint32_t> hfunc_table;
|
||||
Vector<_PHashTranslationCmp> compressed;
|
||||
|
||||
print_line("compressing keys: "+itos(keys.size()));
|
||||
Vector< Vector< Pair<int,CharString> > > buckets;
|
||||
Vector< Map< uint32_t, int > > table;
|
||||
Vector< uint32_t > hfunc_table;
|
||||
Vector< _PHashTranslationCmp > compressed;
|
||||
|
||||
table.resize(size);
|
||||
hfunc_table.resize(size);
|
||||
buckets.resize(size);
|
||||
compressed.resize(keys.size());
|
||||
|
||||
int idx = 0;
|
||||
int total_compression_size = 0;
|
||||
int total_string_size = 0;
|
||||
int idx=0;
|
||||
int total_compression_size=0;
|
||||
int total_string_size=0;
|
||||
|
||||
for (List<StringName>::Element *E = keys.front(); E; E = E->next()) {
|
||||
for(List<StringName>::Element *E=keys.front();E;E=E->next()) {
|
||||
|
||||
//hash string
|
||||
CharString cs = E->get().operator String().utf8();
|
||||
uint32_t h = hash(0, cs.get_data());
|
||||
Pair<int, CharString> p;
|
||||
p.first = idx;
|
||||
p.second = cs;
|
||||
uint32_t h = hash(0,cs.get_data());
|
||||
Pair<int,CharString> p;
|
||||
p.first=idx;
|
||||
p.second=cs;
|
||||
buckets[h % size].push_back(p);
|
||||
|
||||
//compress string
|
||||
CharString src_s = p_from->get_message(E->get()).operator String().utf8();
|
||||
_PHashTranslationCmp ps;
|
||||
ps.orig_len = src_s.size();
|
||||
ps.offset = total_compression_size;
|
||||
ps.orig_len=src_s.size();
|
||||
ps.offset=total_compression_size;
|
||||
|
||||
if (ps.orig_len != 0) {
|
||||
if (ps.orig_len!=0) {
|
||||
CharString dst_s;
|
||||
dst_s.resize(src_s.size());
|
||||
int ret = smaz_compress(src_s.get_data(), src_s.size(), &dst_s[0], src_s.size());
|
||||
if (ret >= src_s.size()) {
|
||||
int ret = smaz_compress(src_s.get_data(),src_s.size(),&dst_s[0],src_s.size());
|
||||
if (ret>=src_s.size()) {
|
||||
//if compressed is larger than original, just use original
|
||||
ps.orig_len = src_s.size();
|
||||
ps.compressed = src_s;
|
||||
ps.orig_len=src_s.size();
|
||||
ps.compressed=src_s;
|
||||
} else {
|
||||
dst_s.resize(ret);
|
||||
//ps.orig_len=;
|
||||
ps.compressed = dst_s;
|
||||
ps.compressed=dst_s;
|
||||
}
|
||||
} else {
|
||||
ps.orig_len = 1;
|
||||
ps.orig_len=1;
|
||||
ps.compressed.resize(1);
|
||||
ps.compressed[0] = 0;
|
||||
ps.compressed[0]=0;
|
||||
}
|
||||
|
||||
compressed[idx] = ps;
|
||||
total_compression_size += ps.compressed.size();
|
||||
total_string_size += src_s.size();
|
||||
|
||||
compressed[idx]=ps;
|
||||
total_compression_size+=ps.compressed.size();
|
||||
total_string_size+=src_s.size();
|
||||
idx++;
|
||||
}
|
||||
|
||||
int bucket_table_size = 0;
|
||||
print_line("total compressed string size: " + itos(total_compression_size) + " (" + itos(total_string_size) + " uncompressed).");
|
||||
int bucket_table_size=0;
|
||||
print_line("total compressed string size: "+itos(total_compression_size)+" ("+itos(total_string_size)+" uncompressed).");
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
for(int i=0;i<size;i++) {
|
||||
|
||||
Vector<Pair<int, CharString> > &b = buckets[i];
|
||||
Map<uint32_t, int> &t = table[i];
|
||||
Vector< Pair<int,CharString> > &b = buckets[i];
|
||||
Map< uint32_t, int > &t=table[i];
|
||||
|
||||
if (b.size() == 0)
|
||||
if (b.size()==0)
|
||||
continue;
|
||||
|
||||
//print_line("bucket: "+itos(i)+" - elements: "+itos(b.size()));
|
||||
|
||||
int d = 1;
|
||||
int item = 0;
|
||||
int item =0;
|
||||
|
||||
while (item < b.size()) {
|
||||
while(item < b.size()) {
|
||||
|
||||
uint32_t slot = hash(d, b[item].second.get_data());
|
||||
uint32_t slot = hash(d,b[item].second.get_data());
|
||||
if (t.has(slot)) {
|
||||
|
||||
item = 0;
|
||||
item=0;
|
||||
d++;
|
||||
t.clear();
|
||||
} else {
|
||||
t[slot] = b[item].first;
|
||||
t[slot]=b[item].first;
|
||||
item++;
|
||||
}
|
||||
}
|
||||
|
||||
hfunc_table[i] = d;
|
||||
bucket_table_size += 2 + b.size() * 4;
|
||||
hfunc_table[i]=d;
|
||||
bucket_table_size+=2+b.size()*4;
|
||||
|
||||
}
|
||||
|
||||
print_line("bucket table size: " + itos(bucket_table_size * 4));
|
||||
print_line("hash table size: " + itos(size * 4));
|
||||
|
||||
print_line("bucket table size: "+itos(bucket_table_size*4));
|
||||
print_line("hash table size: "+itos(size*4));
|
||||
|
||||
hash_table.resize(size);
|
||||
bucket_table.resize(bucket_table_size);
|
||||
|
||||
PoolVector<int>::Write htwb = hash_table.write();
|
||||
PoolVector<int>::Write btwb = bucket_table.write();
|
||||
DVector<int>::Write htwb = hash_table.write();
|
||||
DVector<int>::Write btwb = bucket_table.write();
|
||||
|
||||
uint32_t *htw = (uint32_t *)&htwb[0];
|
||||
uint32_t *btw = (uint32_t *)&btwb[0];
|
||||
uint32_t *htw = (uint32_t*)&htwb[0];
|
||||
uint32_t *btw = (uint32_t*)&btwb[0];
|
||||
|
||||
int btindex = 0;
|
||||
int collisions = 0;
|
||||
int btindex=0;
|
||||
int collisions=0;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
for(int i=0;i<size;i++) {
|
||||
|
||||
Map<uint32_t, int> &t = table[i];
|
||||
if (t.size() == 0) {
|
||||
htw[i] = 0xFFFFFFFF; //nothing
|
||||
Map< uint32_t, int > &t=table[i];
|
||||
if (t.size()==0) {
|
||||
htw[i]=0xFFFFFFFF; //nothing
|
||||
continue;
|
||||
} else if (t.size() > 1) {
|
||||
collisions += t.size() - 1;
|
||||
} else if (t.size()>1) {
|
||||
collisions+=t.size()-1;
|
||||
}
|
||||
|
||||
htw[i] = btindex;
|
||||
btw[btindex++] = t.size();
|
||||
btw[btindex++] = hfunc_table[i];
|
||||
htw[i]=btindex;
|
||||
btw[btindex++]=t.size();
|
||||
btw[btindex++]=hfunc_table[i];
|
||||
|
||||
for (Map<uint32_t, int>::Element *E = t.front(); E; E = E->next()) {
|
||||
for( Map< uint32_t, int >::Element *E=t.front();E;E=E->next()) {
|
||||
|
||||
btw[btindex++] = E->key();
|
||||
btw[btindex++] = compressed[E->get()].offset;
|
||||
btw[btindex++] = compressed[E->get()].compressed.size();
|
||||
btw[btindex++] = compressed[E->get()].orig_len;
|
||||
btw[btindex++]=E->key();
|
||||
btw[btindex++]=compressed[E->get()].offset;
|
||||
btw[btindex++]=compressed[E->get()].compressed.size();
|
||||
btw[btindex++]=compressed[E->get()].orig_len;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
print_line("total collisions: " + itos(collisions));
|
||||
print_line("total collisions: "+itos(collisions));
|
||||
|
||||
strings.resize(total_compression_size);
|
||||
PoolVector<uint8_t>::Write cw = strings.write();
|
||||
DVector<uint8_t>::Write cw = strings.write();
|
||||
|
||||
for (int i = 0; i < compressed.size(); i++) {
|
||||
memcpy(&cw[compressed[i].offset], compressed[i].compressed.get_data(), compressed[i].compressed.size());
|
||||
for(int i=0;i<compressed.size();i++) {
|
||||
memcpy(&cw[compressed[i].offset],compressed[i].compressed.get_data(),compressed[i].compressed.size());
|
||||
}
|
||||
|
||||
ERR_FAIL_COND(btindex != bucket_table_size);
|
||||
|
||||
ERR_FAIL_COND(btindex!=bucket_table_size);
|
||||
set_locale(p_from->get_locale());
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
bool PHashTranslation::_set(const StringName &p_name, const Variant &p_value) {
|
||||
bool PHashTranslation::_set(const StringName& p_name, const Variant& p_value) {
|
||||
|
||||
String name = p_name.operator String();
|
||||
if (name == "hash_table") {
|
||||
hash_table = p_value;
|
||||
if (name=="hash_table") {
|
||||
hash_table=p_value;
|
||||
//print_line("translation: loaded hash table of size: "+itos(hash_table.size()));
|
||||
} else if (name == "bucket_table") {
|
||||
bucket_table = p_value;
|
||||
} else if (name=="bucket_table") {
|
||||
bucket_table=p_value;
|
||||
//print_line("translation: loaded bucket table of size: "+itos(bucket_table.size()));
|
||||
} else if (name == "strings") {
|
||||
strings = p_value;
|
||||
} else if (name=="strings") {
|
||||
strings=p_value;
|
||||
//print_line("translation: loaded string table of size: "+itos(strings.size()));
|
||||
} else if (name == "load_from") {
|
||||
} else if (name=="load_from") {
|
||||
//print_line("generating");
|
||||
generate(p_value);
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool PHashTranslation::_get(const StringName &p_name, Variant &r_ret) const {
|
||||
bool PHashTranslation::_get(const StringName& p_name,Variant &r_ret) const{
|
||||
|
||||
String name = p_name.operator String();
|
||||
if (name == "hash_table")
|
||||
r_ret = hash_table;
|
||||
else if (name == "bucket_table")
|
||||
r_ret = bucket_table;
|
||||
else if (name == "strings")
|
||||
r_ret = strings;
|
||||
if (name=="hash_table")
|
||||
r_ret=hash_table;
|
||||
else if (name=="bucket_table")
|
||||
r_ret=bucket_table;
|
||||
else if (name=="strings")
|
||||
r_ret=strings;
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
StringName PHashTranslation::get_message(const StringName &p_src_text) const {
|
||||
StringName PHashTranslation::get_message(const StringName& p_src_text) const {
|
||||
|
||||
int htsize = hash_table.size();
|
||||
|
||||
if (htsize == 0)
|
||||
if (htsize==0)
|
||||
return StringName();
|
||||
|
||||
CharString str = p_src_text.operator String().utf8();
|
||||
uint32_t h = hash(0, str.get_data());
|
||||
uint32_t h = hash(0,str.get_data());
|
||||
|
||||
PoolVector<int>::Read htr = hash_table.read();
|
||||
const uint32_t *htptr = (const uint32_t *)&htr[0];
|
||||
PoolVector<int>::Read btr = bucket_table.read();
|
||||
const uint32_t *btptr = (const uint32_t *)&btr[0];
|
||||
PoolVector<uint8_t>::Read sr = strings.read();
|
||||
const char *sptr = (const char *)&sr[0];
|
||||
|
||||
uint32_t p = htptr[h % htsize];
|
||||
DVector<int>::Read htr = hash_table.read();
|
||||
const uint32_t *htptr = (const uint32_t*)&htr[0];
|
||||
DVector<int>::Read btr = bucket_table.read();
|
||||
const uint32_t *btptr = (const uint32_t*)&btr[0];
|
||||
DVector<uint8_t>::Read sr = strings.read();
|
||||
const char *sptr= (const char*)&sr[0];
|
||||
|
||||
uint32_t p = htptr[ h % htsize];
|
||||
|
||||
//print_line("String: "+p_src_text.operator String());
|
||||
//print_line("Hash: "+itos(p));
|
||||
|
||||
if (p == 0xFFFFFFFF) {
|
||||
//print_line("GETMSG: Nothing!");
|
||||
if (p==0xFFFFFFFF) {
|
||||
// print_line("GETMSG: Nothing!");
|
||||
return StringName(); //nothing
|
||||
}
|
||||
|
||||
const Bucket &bucket = *(const Bucket *)&btptr[p];
|
||||
const Bucket &bucket = *(const Bucket*)&btptr[p];
|
||||
|
||||
h = hash(bucket.func, str.get_data());
|
||||
h = hash(bucket.func,str.get_data());
|
||||
|
||||
int idx = -1;
|
||||
int idx=-1;
|
||||
|
||||
for (int i = 0; i < bucket.size; i++) {
|
||||
for(int i=0;i<bucket.size;i++) {
|
||||
|
||||
if (bucket.elem[i].key == h) {
|
||||
if (bucket.elem[i].key==h) {
|
||||
|
||||
idx = i;
|
||||
idx=i;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//print_line("bucket pos: "+itos(idx));
|
||||
if (idx == -1) {
|
||||
//print_line("GETMSG: Not in Bucket!");
|
||||
if (idx==-1) {
|
||||
// print_line("GETMSG: Not in Bucket!");
|
||||
return StringName();
|
||||
}
|
||||
|
||||
if (bucket.elem[idx].comp_size == bucket.elem[idx].uncomp_size) {
|
||||
|
||||
String rstr;
|
||||
rstr.parse_utf8(&sptr[bucket.elem[idx].str_offset], bucket.elem[idx].uncomp_size);
|
||||
//print_line("Uncompressed, size: "+itos(bucket.elem[idx].comp_size));
|
||||
//print_line("Return: "+rstr);
|
||||
rstr.parse_utf8(&sptr[ bucket.elem[idx].str_offset ], bucket.elem[idx].uncomp_size );
|
||||
// print_line("Uncompressed, size: "+itos(bucket.elem[idx].comp_size));
|
||||
// print_line("Return: "+rstr);
|
||||
|
||||
return rstr;
|
||||
} else {
|
||||
|
||||
CharString uncomp;
|
||||
uncomp.resize(bucket.elem[idx].uncomp_size + 1);
|
||||
smaz_decompress(&sptr[bucket.elem[idx].str_offset], bucket.elem[idx].comp_size, uncomp.ptrw(), bucket.elem[idx].uncomp_size);
|
||||
uncomp.resize( bucket.elem[idx].uncomp_size+1 );
|
||||
smaz_decompress(&sptr[ bucket.elem[idx].str_offset ], bucket.elem[idx].comp_size,uncomp.ptr(),bucket.elem[idx].uncomp_size );
|
||||
String rstr;
|
||||
rstr.parse_utf8(uncomp.get_data());
|
||||
//print_line("Compressed, size: "+itos(bucket.elem[idx].comp_size));
|
||||
//print_line("Return: "+rstr);
|
||||
// print_line("Compressed, size: "+itos(bucket.elem[idx].comp_size));
|
||||
// print_line("Return: "+rstr);
|
||||
return rstr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PHashTranslation::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
|
||||
p_list->push_back(PropertyInfo(Variant::POOL_INT_ARRAY, "hash_table"));
|
||||
p_list->push_back(PropertyInfo(Variant::POOL_INT_ARRAY, "bucket_table"));
|
||||
p_list->push_back(PropertyInfo(Variant::POOL_BYTE_ARRAY, "strings"));
|
||||
p_list->push_back(PropertyInfo(Variant::OBJECT, "load_from", PROPERTY_HINT_RESOURCE_TYPE, "Translation", PROPERTY_USAGE_EDITOR));
|
||||
void PHashTranslation::_get_property_list( List<PropertyInfo> *p_list) const{
|
||||
|
||||
p_list->push_back( PropertyInfo(Variant::INT_ARRAY, "hash_table"));
|
||||
p_list->push_back( PropertyInfo(Variant::INT_ARRAY, "bucket_table"));
|
||||
p_list->push_back( PropertyInfo(Variant::RAW_ARRAY, "strings"));
|
||||
p_list->push_back( PropertyInfo(Variant::OBJECT, "load_from",PROPERTY_HINT_RESOURCE_TYPE,"Translation",PROPERTY_USAGE_EDITOR));
|
||||
|
||||
}
|
||||
void PHashTranslation::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("generate", "from"), &PHashTranslation::generate);
|
||||
ObjectTypeDB::bind_method(_MD("generate","from:Translation"),&PHashTranslation::generate);
|
||||
}
|
||||
|
||||
PHashTranslation::PHashTranslation() {
|
||||
PHashTranslation::PHashTranslation()
|
||||
{
|
||||
}
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,7 +26,6 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef COMPRESSED_TRANSLATION_H
|
||||
#define COMPRESSED_TRANSLATION_H
|
||||
|
||||
@ -35,17 +33,19 @@
|
||||
|
||||
class PHashTranslation : public Translation {
|
||||
|
||||
GDCLASS(PHashTranslation, Translation);
|
||||
OBJ_TYPE(PHashTranslation,Translation);
|
||||
|
||||
|
||||
//this translation uses a sort of modified perfect hash algorithm
|
||||
//it requires hashing strings twice and then does a binary search,
|
||||
//it requieres hashing strings twice and then does a binary search,
|
||||
//so it's slower, but at the same time it has an extreemly high chance
|
||||
//of catching untranslated strings
|
||||
|
||||
//load/store friendly types
|
||||
PoolVector<int> hash_table;
|
||||
PoolVector<int> bucket_table;
|
||||
PoolVector<uint8_t> strings;
|
||||
DVector<int> hash_table;
|
||||
DVector<int> bucket_table;
|
||||
DVector<uint8_t> strings;
|
||||
|
||||
|
||||
struct Bucket {
|
||||
|
||||
@ -63,11 +63,11 @@ class PHashTranslation : public Translation {
|
||||
Elem elem[1];
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ uint32_t hash(uint32_t d, const char *p_str) const {
|
||||
_FORCE_INLINE_ uint32_t hash( uint32_t d, const char *p_str ) const {
|
||||
|
||||
if (d == 0)
|
||||
d = 0x1000193;
|
||||
while (*p_str) {
|
||||
if (d==0)
|
||||
d=0x1000193;
|
||||
while(*p_str) {
|
||||
|
||||
d = (d * 0x1000193) ^ uint32_t(*p_str);
|
||||
p_str++;
|
||||
@ -75,15 +75,16 @@ class PHashTranslation : public Translation {
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
bool _set(const StringName& p_name, const Variant& p_value);
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const;
|
||||
void _get_property_list( List<PropertyInfo> *p_list) const;
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual StringName get_message(const StringName &p_src_text) const; //overridable for other implementations
|
||||
|
||||
virtual StringName get_message(const StringName& p_src_text) const; //overridable for other implementations
|
||||
void generate(const Ref<Translation> &p_from);
|
||||
|
||||
PHashTranslation();
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,48 +26,23 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core_string_names.h"
|
||||
|
||||
CoreStringNames *CoreStringNames::singleton = NULL;
|
||||
CoreStringNames* CoreStringNames::singleton=NULL;
|
||||
|
||||
CoreStringNames::CoreStringNames() {
|
||||
|
||||
_free=StaticCString::create("free");
|
||||
changed=StaticCString::create("changed");
|
||||
_meta=StaticCString::create("__meta__");
|
||||
_script=StaticCString::create("script/script");
|
||||
script_changed=StaticCString::create("script_changed");
|
||||
___pdcdata=StaticCString::create("___pdcdata");
|
||||
__getvar=StaticCString::create("__getvar");
|
||||
_iter_init=StaticCString::create("_iter_init");
|
||||
_iter_next=StaticCString::create("_iter_next");
|
||||
_iter_get=StaticCString::create("_iter_get");
|
||||
get_rid=StaticCString::create("get_rid");
|
||||
|
||||
CoreStringNames::CoreStringNames() :
|
||||
_free(StaticCString::create("free")),
|
||||
changed(StaticCString::create("changed")),
|
||||
_meta(StaticCString::create("__meta__")),
|
||||
_script(StaticCString::create("script")),
|
||||
script_changed(StaticCString::create("script_changed")),
|
||||
___pdcdata(StaticCString::create("___pdcdata")),
|
||||
__getvar(StaticCString::create("__getvar")),
|
||||
_iter_init(StaticCString::create("_iter_init")),
|
||||
_iter_next(StaticCString::create("_iter_next")),
|
||||
_iter_get(StaticCString::create("_iter_get")),
|
||||
get_rid(StaticCString::create("get_rid")),
|
||||
#ifdef TOOLS_ENABLED
|
||||
_sections_unfolded(StaticCString::create("_sections_unfolded")),
|
||||
#endif
|
||||
_custom_features(StaticCString::create("_custom_features")) {
|
||||
|
||||
x = StaticCString::create("x");
|
||||
y = StaticCString::create("y");
|
||||
z = StaticCString::create("z");
|
||||
w = StaticCString::create("w");
|
||||
r = StaticCString::create("r");
|
||||
g = StaticCString::create("g");
|
||||
b = StaticCString::create("b");
|
||||
a = StaticCString::create("a");
|
||||
position = StaticCString::create("position");
|
||||
size = StaticCString::create("size");
|
||||
end = StaticCString::create("end");
|
||||
basis = StaticCString::create("basis");
|
||||
origin = StaticCString::create("origin");
|
||||
normal = StaticCString::create("normal");
|
||||
d = StaticCString::create("d");
|
||||
h = StaticCString::create("h");
|
||||
s = StaticCString::create("s");
|
||||
v = StaticCString::create("v");
|
||||
r8 = StaticCString::create("r8");
|
||||
g8 = StaticCString::create("g8");
|
||||
b8 = StaticCString::create("b8");
|
||||
a8 = StaticCString::create("a8");
|
||||
}
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,7 +26,6 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef CORE_STRING_NAMES_H
|
||||
#define CORE_STRING_NAMES_H
|
||||
|
||||
@ -35,21 +33,18 @@
|
||||
|
||||
class CoreStringNames {
|
||||
|
||||
friend void register_core_types();
|
||||
friend void unregister_core_types();
|
||||
friend void register_core_types();
|
||||
friend void unregister_core_types();
|
||||
|
||||
static CoreStringNames* singleton;
|
||||
|
||||
static void create() { singleton = memnew(CoreStringNames); }
|
||||
static void free() {
|
||||
memdelete(singleton);
|
||||
singleton = NULL;
|
||||
}
|
||||
static void free() { memdelete( singleton); singleton=NULL; }
|
||||
|
||||
CoreStringNames();
|
||||
|
||||
public:
|
||||
_FORCE_INLINE_ static CoreStringNames *get_singleton() { return singleton; }
|
||||
_FORCE_INLINE_ static CoreStringNames* get_singleton() { return singleton; }
|
||||
|
||||
static CoreStringNames *singleton;
|
||||
|
||||
StringName _free;
|
||||
StringName changed;
|
||||
@ -62,33 +57,7 @@ public:
|
||||
StringName _iter_next;
|
||||
StringName _iter_get;
|
||||
StringName get_rid;
|
||||
#ifdef TOOLS_ENABLED
|
||||
StringName _sections_unfolded;
|
||||
#endif
|
||||
StringName _custom_features;
|
||||
|
||||
StringName x;
|
||||
StringName y;
|
||||
StringName z;
|
||||
StringName w;
|
||||
StringName r;
|
||||
StringName g;
|
||||
StringName b;
|
||||
StringName a;
|
||||
StringName position;
|
||||
StringName size;
|
||||
StringName end;
|
||||
StringName basis;
|
||||
StringName origin;
|
||||
StringName normal;
|
||||
StringName d;
|
||||
StringName h;
|
||||
StringName s;
|
||||
StringName v;
|
||||
StringName r8;
|
||||
StringName g8;
|
||||
StringName b8;
|
||||
StringName a8;
|
||||
};
|
||||
|
||||
#endif // SCENE_STRING_NAMES_H
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,223 +26,237 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "dictionary.h"
|
||||
|
||||
#include "ordered_hash_map.h"
|
||||
#include "safe_refcount.h"
|
||||
#include "variant.h"
|
||||
#include "io/json.h"
|
||||
|
||||
struct _DictionaryVariantHash {
|
||||
|
||||
static _FORCE_INLINE_ uint32_t hash(const Variant &p_variant) { return p_variant.hash(); }
|
||||
};
|
||||
|
||||
|
||||
struct DictionaryPrivate {
|
||||
|
||||
SafeRefCount refcount;
|
||||
OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> variant_map;
|
||||
HashMap<Variant,Variant,_DictionaryVariantHash> variant_map;
|
||||
bool shared;
|
||||
|
||||
};
|
||||
|
||||
void Dictionary::get_key_list(List<Variant> *p_keys) const {
|
||||
|
||||
if (_p->variant_map.empty())
|
||||
void Dictionary::get_key_list( List<Variant> *p_keys) const {
|
||||
|
||||
_p->variant_map.get_key_list(p_keys);
|
||||
}
|
||||
|
||||
void Dictionary::_copy_on_write() const {
|
||||
|
||||
//make a copy of what we have
|
||||
if (_p->shared)
|
||||
return;
|
||||
|
||||
for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
|
||||
p_keys->push_back(E.key());
|
||||
}
|
||||
DictionaryPrivate *p = memnew(DictionaryPrivate);
|
||||
p->shared=_p->shared;
|
||||
p->variant_map=_p->variant_map;
|
||||
p->refcount.init();
|
||||
_unref();
|
||||
_p=p;
|
||||
}
|
||||
|
||||
Variant &Dictionary::operator[](const Variant &p_key) {
|
||||
Variant& Dictionary::operator[](const Variant& p_key) {
|
||||
|
||||
_copy_on_write();
|
||||
|
||||
return _p->variant_map[p_key];
|
||||
}
|
||||
|
||||
const Variant &Dictionary::operator[](const Variant &p_key) const {
|
||||
const Variant& Dictionary::operator[](const Variant& p_key) const {
|
||||
|
||||
return _p->variant_map[p_key];
|
||||
|
||||
}
|
||||
const Variant *Dictionary::getptr(const Variant &p_key) const {
|
||||
const Variant* Dictionary::getptr(const Variant& p_key) const {
|
||||
|
||||
OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
|
||||
return _p->variant_map.getptr(p_key);
|
||||
}
|
||||
Variant* Dictionary::getptr(const Variant& p_key) {
|
||||
|
||||
if (!E)
|
||||
return NULL;
|
||||
return &E.get();
|
||||
_copy_on_write();
|
||||
return _p->variant_map.getptr(p_key);
|
||||
}
|
||||
|
||||
Variant *Dictionary::getptr(const Variant &p_key) {
|
||||
Variant Dictionary::get_valid(const Variant& p_key) const {
|
||||
|
||||
OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.find(p_key);
|
||||
|
||||
if (!E)
|
||||
return NULL;
|
||||
return &E.get();
|
||||
}
|
||||
|
||||
Variant Dictionary::get_valid(const Variant &p_key) const {
|
||||
|
||||
OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
|
||||
|
||||
if (!E)
|
||||
const Variant *v = getptr(p_key);
|
||||
if (!v)
|
||||
return Variant();
|
||||
return E.get();
|
||||
return *v;
|
||||
}
|
||||
|
||||
|
||||
int Dictionary::size() const {
|
||||
|
||||
return _p->variant_map.size();
|
||||
|
||||
}
|
||||
bool Dictionary::empty() const {
|
||||
|
||||
return !_p->variant_map.size();
|
||||
}
|
||||
|
||||
bool Dictionary::has(const Variant &p_key) const {
|
||||
bool Dictionary::has(const Variant& p_key) const {
|
||||
|
||||
return _p->variant_map.has(p_key);
|
||||
}
|
||||
|
||||
bool Dictionary::has_all(const Array &p_keys) const {
|
||||
for (int i = 0; i < p_keys.size(); i++) {
|
||||
if (!has(p_keys[i])) {
|
||||
bool Dictionary::has_all(const Array& p_keys) const {
|
||||
for (int i=0;i<p_keys.size();i++) {
|
||||
if( !has(p_keys[i]) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Dictionary::erase(const Variant &p_key) {
|
||||
|
||||
void Dictionary::erase(const Variant& p_key) {
|
||||
_copy_on_write();
|
||||
_p->variant_map.erase(p_key);
|
||||
}
|
||||
|
||||
bool Dictionary::erase_checked(const Variant &p_key) {
|
||||
bool Dictionary::operator==(const Dictionary& p_dictionary) const {
|
||||
|
||||
return _p->variant_map.erase(p_key);
|
||||
return _p==p_dictionary._p;
|
||||
}
|
||||
|
||||
bool Dictionary::operator==(const Dictionary &p_dictionary) const {
|
||||
|
||||
return _p == p_dictionary._p;
|
||||
}
|
||||
|
||||
void Dictionary::_ref(const Dictionary &p_from) const {
|
||||
void Dictionary::_ref(const Dictionary& p_from) const {
|
||||
|
||||
//make a copy first (thread safe)
|
||||
if (!p_from._p->refcount.ref())
|
||||
return; // couldn't copy
|
||||
|
||||
//if this is the same, unreference the other one
|
||||
if (p_from._p == _p) {
|
||||
if (p_from._p==_p) {
|
||||
_p->refcount.unref();
|
||||
return;
|
||||
}
|
||||
if (_p)
|
||||
_unref();
|
||||
_p = p_from._p;
|
||||
_p=p_from._p;
|
||||
|
||||
}
|
||||
|
||||
void Dictionary::clear() {
|
||||
|
||||
_copy_on_write();
|
||||
_p->variant_map.clear();
|
||||
}
|
||||
|
||||
bool Dictionary::is_shared() const {
|
||||
|
||||
return _p->shared;
|
||||
}
|
||||
|
||||
|
||||
void Dictionary::_unref() const {
|
||||
|
||||
ERR_FAIL_COND(!_p);
|
||||
if (_p->refcount.unref()) {
|
||||
memdelete(_p);
|
||||
}
|
||||
_p = NULL;
|
||||
_p=NULL;
|
||||
|
||||
}
|
||||
uint32_t Dictionary::hash() const {
|
||||
|
||||
uint32_t h = hash_djb2_one_32(Variant::DICTIONARY);
|
||||
uint32_t h=hash_djb2_one_32(Variant::DICTIONARY);
|
||||
|
||||
List<Variant> keys;
|
||||
get_key_list(&keys);
|
||||
|
||||
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
|
||||
for (List<Variant>::Element *E=keys.front();E;E=E->next()) {
|
||||
|
||||
h = hash_djb2_one_32( E->get().hash(), h);
|
||||
h = hash_djb2_one_32( operator[](E->get()).hash(), h);
|
||||
|
||||
h = hash_djb2_one_32(E->get().hash(), h);
|
||||
h = hash_djb2_one_32(operator[](E->get()).hash(), h);
|
||||
}
|
||||
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
Array Dictionary::keys() const {
|
||||
|
||||
Array varr;
|
||||
varr.resize(size());
|
||||
if (_p->variant_map.empty())
|
||||
return varr;
|
||||
|
||||
int i = 0;
|
||||
for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
|
||||
varr[i] = E.key();
|
||||
i++;
|
||||
Array karr;
|
||||
karr.resize(size());
|
||||
const Variant *K=NULL;
|
||||
int idx=0;
|
||||
while((K=next(K))) {
|
||||
karr[idx++]=(*K);
|
||||
}
|
||||
return karr;
|
||||
|
||||
return varr;
|
||||
}
|
||||
|
||||
Array Dictionary::values() const {
|
||||
|
||||
Array varr;
|
||||
varr.resize(size());
|
||||
if (_p->variant_map.empty())
|
||||
return varr;
|
||||
|
||||
int i = 0;
|
||||
for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
|
||||
varr[i] = E.get();
|
||||
i++;
|
||||
const Variant *key=NULL;
|
||||
int i=0;
|
||||
while((key=next(key))){
|
||||
varr[i++] = _p->variant_map[*key];
|
||||
}
|
||||
|
||||
return varr;
|
||||
}
|
||||
|
||||
const Variant *Dictionary::next(const Variant *p_key) const {
|
||||
const Variant* Dictionary::next(const Variant* p_key) const {
|
||||
|
||||
if (p_key == NULL) {
|
||||
// caller wants to get the first element
|
||||
if (_p->variant_map.front())
|
||||
return &_p->variant_map.front().key();
|
||||
return NULL;
|
||||
}
|
||||
OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.find(*p_key);
|
||||
|
||||
if (E && E.next())
|
||||
return &E.next().key();
|
||||
return NULL;
|
||||
return _p->variant_map.next(p_key);
|
||||
}
|
||||
|
||||
Dictionary Dictionary::duplicate() const {
|
||||
|
||||
Dictionary n;
|
||||
Error Dictionary::parse_json(const String& p_json) {
|
||||
|
||||
List<Variant> keys;
|
||||
get_key_list(&keys);
|
||||
|
||||
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
|
||||
n[E->get()] = operator[](E->get());
|
||||
String errstr;
|
||||
int errline=0;
|
||||
if (p_json != ""){
|
||||
Error err = JSON::parse(p_json,*this,errstr,errline);
|
||||
if (err!=OK) {
|
||||
ERR_EXPLAIN("Error parsing JSON: "+errstr+" at line: "+itos(errline));
|
||||
ERR_FAIL_COND_V(err!=OK,err);
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
return OK;
|
||||
}
|
||||
|
||||
void Dictionary::operator=(const Dictionary &p_dictionary) {
|
||||
String Dictionary::to_json() const {
|
||||
|
||||
return JSON::print(*this);
|
||||
}
|
||||
|
||||
|
||||
void Dictionary::operator=(const Dictionary& p_dictionary) {
|
||||
|
||||
_ref(p_dictionary);
|
||||
}
|
||||
|
||||
Dictionary::Dictionary(const Dictionary &p_from) {
|
||||
_p = NULL;
|
||||
|
||||
|
||||
Dictionary::Dictionary(const Dictionary& p_from) {
|
||||
_p=NULL;
|
||||
_ref(p_from);
|
||||
}
|
||||
|
||||
Dictionary::Dictionary() {
|
||||
|
||||
_p = memnew(DictionaryPrivate);
|
||||
Dictionary::Dictionary(bool p_shared) {
|
||||
|
||||
_p=memnew( DictionaryPrivate );
|
||||
_p->refcount.init();
|
||||
_p->shared=p_shared;
|
||||
|
||||
}
|
||||
Dictionary::~Dictionary() {
|
||||
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,59 +26,65 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef DICTIONARY_H
|
||||
#define DICTIONARY_H
|
||||
|
||||
#include "array.h"
|
||||
|
||||
#include "list.h"
|
||||
#include "array.h"
|
||||
#include "ustring.h"
|
||||
class Variant;
|
||||
|
||||
|
||||
struct DictionaryPrivate;
|
||||
|
||||
|
||||
class Dictionary {
|
||||
|
||||
mutable DictionaryPrivate *_p;
|
||||
|
||||
void _ref(const Dictionary &p_from) const;
|
||||
void _copy_on_write() const;
|
||||
void _ref(const Dictionary& p_from) const;
|
||||
void _unref() const;
|
||||
|
||||
public:
|
||||
void get_key_list(List<Variant> *p_keys) const;
|
||||
|
||||
Variant &operator[](const Variant &p_key);
|
||||
const Variant &operator[](const Variant &p_key) const;
|
||||
void get_key_list( List<Variant> *p_keys) const;
|
||||
|
||||
const Variant *getptr(const Variant &p_key) const;
|
||||
Variant *getptr(const Variant &p_key);
|
||||
Variant& operator[](const Variant& p_key);
|
||||
const Variant& operator[](const Variant& p_key) const;
|
||||
|
||||
Variant get_valid(const Variant &p_key) const;
|
||||
const Variant* getptr(const Variant& p_key) const;
|
||||
Variant* getptr(const Variant& p_key);
|
||||
|
||||
Variant get_valid(const Variant& p_key) const;
|
||||
|
||||
int size() const;
|
||||
bool empty() const;
|
||||
void clear();
|
||||
|
||||
bool has(const Variant &p_key) const;
|
||||
bool has_all(const Array &p_keys) const;
|
||||
|
||||
void erase(const Variant &p_key);
|
||||
bool erase_checked(const Variant &p_key);
|
||||
Error parse_json(const String& p_json);
|
||||
String to_json() const;
|
||||
|
||||
bool operator==(const Dictionary &p_dictionary) const;
|
||||
bool is_shared() const;
|
||||
|
||||
bool has(const Variant& p_key) const;
|
||||
bool has_all(const Array& p_keys) const;
|
||||
|
||||
void erase(const Variant& p_key);
|
||||
|
||||
bool operator==(const Dictionary& p_dictionary) const;
|
||||
|
||||
uint32_t hash() const;
|
||||
void operator=(const Dictionary &p_dictionary);
|
||||
void operator=(const Dictionary& p_dictionary);
|
||||
|
||||
const Variant *next(const Variant *p_key = NULL) const;
|
||||
const Variant* next(const Variant* p_key=NULL) const;
|
||||
|
||||
Array keys() const;
|
||||
Array values() const;
|
||||
|
||||
Dictionary duplicate() const;
|
||||
|
||||
Dictionary(const Dictionary &p_from);
|
||||
Dictionary();
|
||||
Dictionary(const Dictionary& p_from);
|
||||
Dictionary(bool p_shared=false);
|
||||
~Dictionary();
|
||||
};
|
||||
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,45 +26,7 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "dvector.h"
|
||||
|
||||
Mutex *dvector_lock = NULL;
|
||||
Mutex* dvector_lock=NULL;
|
||||
|
||||
PoolAllocator *MemoryPool::memory_pool = NULL;
|
||||
uint8_t *MemoryPool::pool_memory = NULL;
|
||||
size_t *MemoryPool::pool_size = NULL;
|
||||
|
||||
MemoryPool::Alloc *MemoryPool::allocs = NULL;
|
||||
MemoryPool::Alloc *MemoryPool::free_list = NULL;
|
||||
uint32_t MemoryPool::alloc_count = 0;
|
||||
uint32_t MemoryPool::allocs_used = 0;
|
||||
Mutex *MemoryPool::alloc_mutex = NULL;
|
||||
|
||||
size_t MemoryPool::total_memory = 0;
|
||||
size_t MemoryPool::max_memory = 0;
|
||||
|
||||
void MemoryPool::setup(uint32_t p_max_allocs) {
|
||||
|
||||
allocs = memnew_arr(Alloc, p_max_allocs);
|
||||
alloc_count = p_max_allocs;
|
||||
allocs_used = 0;
|
||||
|
||||
for (uint32_t i = 0; i < alloc_count - 1; i++) {
|
||||
|
||||
allocs[i].free_list = &allocs[i + 1];
|
||||
}
|
||||
|
||||
free_list = &allocs[0];
|
||||
|
||||
alloc_mutex = Mutex::create();
|
||||
}
|
||||
|
||||
void MemoryPool::cleanup() {
|
||||
|
||||
memdelete_arr(allocs);
|
||||
memdelete(alloc_mutex);
|
||||
|
||||
ERR_EXPLAINC("There are still MemoryPool allocs in use at exit!");
|
||||
ERR_FAIL_COND(allocs_used > 0);
|
||||
}
|
||||
|
||||
643
core/dvector.h
643
core/dvector.h
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,432 +26,260 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef DVECTOR_H
|
||||
#define DVECTOR_H
|
||||
|
||||
#include "os/copymem.h"
|
||||
#include "os/memory.h"
|
||||
#include "os/rw_lock.h"
|
||||
#include "pool_allocator.h"
|
||||
#include "safe_refcount.h"
|
||||
#include "ustring.h"
|
||||
|
||||
struct MemoryPool {
|
||||
|
||||
//avoid accessing these directly, must be public for template access
|
||||
|
||||
static PoolAllocator *memory_pool;
|
||||
static uint8_t *pool_memory;
|
||||
static size_t *pool_size;
|
||||
|
||||
struct Alloc {
|
||||
|
||||
SafeRefCount refcount;
|
||||
uint32_t lock;
|
||||
void *mem;
|
||||
PoolAllocator::ID pool_id;
|
||||
size_t size;
|
||||
|
||||
Alloc *free_list;
|
||||
|
||||
Alloc() {
|
||||
mem = NULL;
|
||||
lock = 0;
|
||||
pool_id = POOL_ALLOCATOR_INVALID_ID;
|
||||
size = 0;
|
||||
free_list = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
static Alloc *allocs;
|
||||
static Alloc *free_list;
|
||||
static uint32_t alloc_count;
|
||||
static uint32_t allocs_used;
|
||||
static Mutex *alloc_mutex;
|
||||
static size_t total_memory;
|
||||
static size_t max_memory;
|
||||
|
||||
static void setup(uint32_t p_max_allocs = (1 << 16));
|
||||
static void cleanup();
|
||||
};
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
class PoolVector {
|
||||
|
||||
MemoryPool::Alloc *alloc;
|
||||
extern Mutex* dvector_lock;
|
||||
|
||||
void _copy_on_write() {
|
||||
template<class T>
|
||||
class DVector {
|
||||
|
||||
if (!alloc)
|
||||
mutable MID mem;
|
||||
|
||||
|
||||
void copy_on_write() {
|
||||
|
||||
if (!mem.is_valid())
|
||||
return;
|
||||
|
||||
// ERR_FAIL_COND(alloc->lock>0); should not be illegal to lock this for copy on write, as it's a copy on write after all
|
||||
if (dvector_lock)
|
||||
dvector_lock->lock();
|
||||
|
||||
// Refcount should not be zero, otherwise it's a misuse of COW
|
||||
if (alloc->refcount.get() == 1)
|
||||
return; //nothing to do
|
||||
MID_Lock lock( mem );
|
||||
|
||||
//must allocate something
|
||||
|
||||
MemoryPool::alloc_mutex->lock();
|
||||
if (MemoryPool::allocs_used == MemoryPool::alloc_count) {
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
ERR_EXPLAINC("All memory pool allocations are in use, can't COW.");
|
||||
ERR_FAIL();
|
||||
if ( *(int*)lock.data() == 1 ) {
|
||||
// one reference, means no refcount changes
|
||||
if (dvector_lock)
|
||||
dvector_lock->unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
MemoryPool::Alloc *old_alloc = alloc;
|
||||
MID new_mem= dynalloc( mem.get_size() );
|
||||
|
||||
//take one from the free list
|
||||
alloc = MemoryPool::free_list;
|
||||
MemoryPool::free_list = alloc->free_list;
|
||||
//increment the used counter
|
||||
MemoryPool::allocs_used++;
|
||||
if (!new_mem.is_valid()) {
|
||||
|
||||
//copy the alloc data
|
||||
alloc->size = old_alloc->size;
|
||||
alloc->refcount.init();
|
||||
alloc->pool_id = POOL_ALLOCATOR_INVALID_ID;
|
||||
alloc->lock = 0;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
MemoryPool::total_memory += alloc->size;
|
||||
if (MemoryPool::total_memory > MemoryPool::max_memory) {
|
||||
MemoryPool::max_memory = MemoryPool::total_memory;
|
||||
}
|
||||
#endif
|
||||
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
|
||||
if (MemoryPool::memory_pool) {
|
||||
|
||||
} else {
|
||||
alloc->mem = memalloc(alloc->size);
|
||||
if (dvector_lock)
|
||||
dvector_lock->unlock();
|
||||
ERR_FAIL_COND( new_mem.is_valid() ); // out of memory
|
||||
}
|
||||
|
||||
{
|
||||
Write w;
|
||||
w._ref(alloc);
|
||||
Read r;
|
||||
r._ref(old_alloc);
|
||||
MID_Lock dst_lock( new_mem );
|
||||
|
||||
int cur_elements = alloc->size / sizeof(T);
|
||||
T *dst = (T *)w.ptr();
|
||||
const T *src = (const T *)r.ptr();
|
||||
for (int i = 0; i < cur_elements; i++) {
|
||||
memnew_placement(&dst[i], T(src[i]));
|
||||
}
|
||||
int *rc = (int*)dst_lock.data();
|
||||
|
||||
*rc=1;
|
||||
|
||||
T * dst = (T*)(rc + 1 );
|
||||
|
||||
T * src =(T*) ((int*)lock.data() + 1 );
|
||||
|
||||
int count = (mem.get_size() - sizeof(int)) / sizeof(T);
|
||||
|
||||
for (int i=0;i<count;i++) {
|
||||
|
||||
memnew_placement( &dst[i], T(src[i]) );
|
||||
}
|
||||
|
||||
if (old_alloc->refcount.unref() == true) {
|
||||
//this should never happen but..
|
||||
(*(int*)lock.data())--;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
MemoryPool::alloc_mutex->lock();
|
||||
MemoryPool::total_memory -= old_alloc->size;
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
#endif
|
||||
// unlock all
|
||||
dst_lock=MID_Lock();
|
||||
lock=MID_Lock();
|
||||
|
||||
{
|
||||
Write w;
|
||||
w._ref(old_alloc);
|
||||
mem=new_mem;
|
||||
|
||||
int cur_elements = old_alloc->size / sizeof(T);
|
||||
T *elems = (T *)w.ptr();
|
||||
for (int i = 0; i < cur_elements; i++) {
|
||||
elems[i].~T();
|
||||
}
|
||||
}
|
||||
if (dvector_lock)
|
||||
dvector_lock->unlock();
|
||||
|
||||
if (MemoryPool::memory_pool) {
|
||||
//resize memory pool
|
||||
//if none, create
|
||||
//if some resize
|
||||
} else {
|
||||
|
||||
memfree(old_alloc->mem);
|
||||
old_alloc->mem = NULL;
|
||||
old_alloc->size = 0;
|
||||
|
||||
MemoryPool::alloc_mutex->lock();
|
||||
old_alloc->free_list = MemoryPool::free_list;
|
||||
MemoryPool::free_list = old_alloc;
|
||||
MemoryPool::allocs_used--;
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _reference(const PoolVector &p_dvector) {
|
||||
void reference( const DVector& p_dvector ) {
|
||||
|
||||
if (alloc == p_dvector.alloc)
|
||||
return;
|
||||
unreference();
|
||||
|
||||
_unreference();
|
||||
if (dvector_lock)
|
||||
dvector_lock->lock();
|
||||
|
||||
if (!p_dvector.alloc) {
|
||||
if (!p_dvector.mem.is_valid()) {
|
||||
|
||||
if (dvector_lock)
|
||||
dvector_lock->unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_dvector.alloc->refcount.ref()) {
|
||||
alloc = p_dvector.alloc;
|
||||
}
|
||||
MID_Lock lock(p_dvector.mem);
|
||||
|
||||
int * rc = (int*)lock.data();
|
||||
(*rc)++;
|
||||
|
||||
lock = MID_Lock();
|
||||
mem=p_dvector.mem;
|
||||
|
||||
if (dvector_lock)
|
||||
dvector_lock->unlock();
|
||||
|
||||
}
|
||||
|
||||
void _unreference() {
|
||||
|
||||
if (!alloc)
|
||||
return;
|
||||
void unreference() {
|
||||
|
||||
if (alloc->refcount.unref() == false) {
|
||||
alloc = NULL;
|
||||
if (dvector_lock)
|
||||
dvector_lock->lock();
|
||||
|
||||
if (!mem.is_valid()) {
|
||||
|
||||
if (dvector_lock)
|
||||
dvector_lock->unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
//must be disposed!
|
||||
MID_Lock lock(mem);
|
||||
|
||||
{
|
||||
int cur_elements = alloc->size / sizeof(T);
|
||||
int * rc = (int*)lock.data();
|
||||
(*rc)--;
|
||||
|
||||
// Don't use write() here because it could otherwise provoke COW,
|
||||
// which is not desirable here because we are destroying the last reference anyways
|
||||
Write w;
|
||||
// Reference to still prevent other threads from touching the alloc
|
||||
w._ref(alloc);
|
||||
if (*rc==0) {
|
||||
// no one else using it, destruct
|
||||
|
||||
for (int i = 0; i < cur_elements; i++) {
|
||||
T * t= (T*)(rc+1);
|
||||
int count = (mem.get_size() - sizeof(int)) / sizeof(T);
|
||||
|
||||
w[i].~T();
|
||||
for (int i=0;i<count;i++) {
|
||||
|
||||
t[i].~T();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
MemoryPool::alloc_mutex->lock();
|
||||
MemoryPool::total_memory -= alloc->size;
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
#endif
|
||||
|
||||
if (MemoryPool::memory_pool) {
|
||||
//resize memory pool
|
||||
//if none, create
|
||||
//if some resize
|
||||
} else {
|
||||
lock = MID_Lock();
|
||||
|
||||
memfree(alloc->mem);
|
||||
alloc->mem = NULL;
|
||||
alloc->size = 0;
|
||||
mem = MID ();
|
||||
|
||||
MemoryPool::alloc_mutex->lock();
|
||||
alloc->free_list = MemoryPool::free_list;
|
||||
MemoryPool::free_list = alloc;
|
||||
MemoryPool::allocs_used--;
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
}
|
||||
if (dvector_lock)
|
||||
dvector_lock->unlock();
|
||||
|
||||
alloc = NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
class Access {
|
||||
friend class PoolVector;
|
||||
|
||||
protected:
|
||||
MemoryPool::Alloc *alloc;
|
||||
T *mem;
|
||||
|
||||
_FORCE_INLINE_ void _ref(MemoryPool::Alloc *p_alloc) {
|
||||
alloc = p_alloc;
|
||||
if (alloc) {
|
||||
if (atomic_increment(&alloc->lock) == 1) {
|
||||
if (MemoryPool::memory_pool) {
|
||||
//lock it and get mem
|
||||
}
|
||||
}
|
||||
|
||||
mem = (T *)alloc->mem;
|
||||
}
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void _unref() {
|
||||
|
||||
if (alloc) {
|
||||
if (atomic_decrement(&alloc->lock) == 0) {
|
||||
if (MemoryPool::memory_pool) {
|
||||
//put mem back
|
||||
}
|
||||
}
|
||||
|
||||
mem = NULL;
|
||||
alloc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Access() {
|
||||
alloc = NULL;
|
||||
mem = NULL;
|
||||
}
|
||||
|
||||
class Read {
|
||||
friend class DVector;
|
||||
MID_Lock lock;
|
||||
const T * mem;
|
||||
public:
|
||||
virtual ~Access() {
|
||||
_unref();
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ const T& operator[](int p_index) const { return mem[p_index]; }
|
||||
_FORCE_INLINE_ const T *ptr() const { return mem; }
|
||||
|
||||
Read() { mem=NULL; }
|
||||
};
|
||||
|
||||
class Read : public Access {
|
||||
class Write {
|
||||
friend class DVector;
|
||||
MID_Lock lock;
|
||||
T * mem;
|
||||
public:
|
||||
_FORCE_INLINE_ const T &operator[](int p_index) const { return this->mem[p_index]; }
|
||||
_FORCE_INLINE_ const T *ptr() const { return this->mem; }
|
||||
|
||||
void operator=(const Read &p_read) {
|
||||
if (this->alloc == p_read.alloc)
|
||||
return;
|
||||
this->_unref();
|
||||
this->_ref(p_read.alloc);
|
||||
}
|
||||
_FORCE_INLINE_ T& operator[](int p_index) { return mem[p_index]; }
|
||||
_FORCE_INLINE_ T *ptr() { return mem; }
|
||||
|
||||
Read(const Read &p_read) {
|
||||
this->_ref(p_read.alloc);
|
||||
}
|
||||
|
||||
Read() {}
|
||||
Write() { mem=NULL; }
|
||||
};
|
||||
|
||||
class Write : public Access {
|
||||
public:
|
||||
_FORCE_INLINE_ T &operator[](int p_index) const { return this->mem[p_index]; }
|
||||
_FORCE_INLINE_ T *ptr() const { return this->mem; }
|
||||
|
||||
void operator=(const Write &p_read) {
|
||||
if (this->alloc == p_read.alloc)
|
||||
return;
|
||||
this->_unref();
|
||||
this->_ref(p_read.alloc);
|
||||
}
|
||||
|
||||
Write(const Write &p_read) {
|
||||
this->_ref(p_read.alloc);
|
||||
}
|
||||
|
||||
Write() {}
|
||||
};
|
||||
|
||||
Read read() const {
|
||||
|
||||
Read r;
|
||||
if (alloc) {
|
||||
r._ref(alloc);
|
||||
if (mem.is_valid()) {
|
||||
r.lock = MID_Lock( mem );
|
||||
r.mem = (const T*)((int*)r.lock.data()+1);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
Write write() {
|
||||
|
||||
Write w;
|
||||
if (alloc) {
|
||||
_copy_on_write(); //make sure there is only one being acessed
|
||||
w._ref(alloc);
|
||||
if (mem.is_valid()) {
|
||||
copy_on_write();
|
||||
w.lock = MID_Lock( mem );
|
||||
w.mem = (T*)((int*)w.lock.data()+1);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
template <class MC>
|
||||
void fill_with(const MC &p_mc) {
|
||||
template<class MC>
|
||||
void fill_with(const MC& p_mc) {
|
||||
|
||||
int c = p_mc.size();
|
||||
|
||||
int c=p_mc.size();
|
||||
resize(c);
|
||||
Write w = write();
|
||||
int idx = 0;
|
||||
for (const typename MC::Element *E = p_mc.front(); E; E = E->next()) {
|
||||
Write w=write();
|
||||
int idx=0;
|
||||
for(const typename MC::Element *E=p_mc.front();E;E=E->next()) {
|
||||
|
||||
w[idx++] = E->get();
|
||||
w[idx++]=E->get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void remove(int p_index) {
|
||||
|
||||
int s = size();
|
||||
ERR_FAIL_INDEX(p_index, s);
|
||||
Write w = write();
|
||||
for (int i = p_index; i < s - 1; i++) {
|
||||
for (int i=p_index; i<s-1; i++) {
|
||||
|
||||
w[i] = w[i + 1];
|
||||
w[i]=w[i+1];
|
||||
};
|
||||
w = Write();
|
||||
resize(s - 1);
|
||||
resize(s-1);
|
||||
}
|
||||
|
||||
inline int size() const;
|
||||
T get(int p_index) const;
|
||||
void set(int p_index, const T &p_val);
|
||||
void push_back(const T &p_val);
|
||||
void append(const T &p_val) { push_back(p_val); }
|
||||
void append_array(const PoolVector<T> &p_arr) {
|
||||
void set(int p_index, const T& p_val);
|
||||
void push_back(const T& p_val);
|
||||
void append(const T& p_val) { push_back(p_val); }
|
||||
void append_array(const DVector<T>& p_arr) {
|
||||
int ds = p_arr.size();
|
||||
if (ds == 0)
|
||||
if (ds==0)
|
||||
return;
|
||||
int bs = size();
|
||||
resize(bs + ds);
|
||||
resize( bs + ds);
|
||||
Write w = write();
|
||||
Read r = p_arr.read();
|
||||
for (int i = 0; i < ds; i++)
|
||||
w[bs + i] = r[i];
|
||||
for(int i=0;i<ds;i++)
|
||||
w[bs+i]=r[i];
|
||||
}
|
||||
|
||||
PoolVector<T> subarray(int p_from, int p_to) {
|
||||
|
||||
if (p_from < 0) {
|
||||
p_from = size() + p_from;
|
||||
}
|
||||
if (p_to < 0) {
|
||||
p_to = size() + p_to;
|
||||
}
|
||||
Error insert(int p_pos,const T& p_val) {
|
||||
|
||||
CRASH_BAD_INDEX(p_from, size());
|
||||
CRASH_BAD_INDEX(p_to, size());
|
||||
|
||||
PoolVector<T> slice;
|
||||
int span = 1 + p_to - p_from;
|
||||
slice.resize(span);
|
||||
Read r = read();
|
||||
Write w = slice.write();
|
||||
for (int i = 0; i < span; ++i) {
|
||||
w[i] = r[p_from + i];
|
||||
}
|
||||
|
||||
return slice;
|
||||
}
|
||||
|
||||
Error insert(int p_pos, const T &p_val) {
|
||||
|
||||
int s = size();
|
||||
ERR_FAIL_INDEX_V(p_pos, s + 1, ERR_INVALID_PARAMETER);
|
||||
resize(s + 1);
|
||||
int s=size();
|
||||
ERR_FAIL_INDEX_V(p_pos,s+1,ERR_INVALID_PARAMETER);
|
||||
resize(s+1);
|
||||
{
|
||||
Write w = write();
|
||||
for (int i = s; i > p_pos; i--)
|
||||
w[i] = w[i - 1];
|
||||
w[p_pos] = p_val;
|
||||
for (int i=s;i>p_pos;i--)
|
||||
w[i]=w[i-1];
|
||||
w[p_pos]=p_val;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
String join(String delimiter) {
|
||||
String rs = "";
|
||||
int s = size();
|
||||
Read r = read();
|
||||
for (int i = 0; i < s; i++) {
|
||||
rs += r[i] + delimiter;
|
||||
}
|
||||
rs.erase(rs.length() - delimiter.length(), delimiter.length());
|
||||
return rs;
|
||||
}
|
||||
|
||||
bool is_locked() const { return alloc && alloc->lock > 0; }
|
||||
bool is_locked() const { return mem.is_locked(); }
|
||||
|
||||
inline const T operator[](int p_index) const;
|
||||
|
||||
@ -460,183 +287,155 @@ public:
|
||||
|
||||
void invert();
|
||||
|
||||
void operator=(const PoolVector &p_dvector) { _reference(p_dvector); }
|
||||
PoolVector() { alloc = NULL; }
|
||||
PoolVector(const PoolVector &p_dvector) {
|
||||
alloc = NULL;
|
||||
_reference(p_dvector);
|
||||
}
|
||||
~PoolVector() { _unreference(); }
|
||||
void operator=(const DVector& p_dvector) { reference(p_dvector); }
|
||||
DVector() {}
|
||||
DVector(const DVector& p_dvector) { reference(p_dvector); }
|
||||
~DVector() { unreference(); }
|
||||
|
||||
};
|
||||
|
||||
template <class T>
|
||||
int PoolVector<T>::size() const {
|
||||
template<class T>
|
||||
int DVector<T>::size() const {
|
||||
|
||||
return alloc ? alloc->size / sizeof(T) : 0;
|
||||
return mem.is_valid() ? ((mem.get_size() - sizeof(int)) / sizeof(T) ) : 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T PoolVector<T>::get(int p_index) const {
|
||||
template<class T>
|
||||
T DVector<T>::get(int p_index) const {
|
||||
|
||||
return operator[](p_index);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void PoolVector<T>::set(int p_index, const T &p_val) {
|
||||
template<class T>
|
||||
void DVector<T>::set(int p_index, const T& p_val) {
|
||||
|
||||
if (p_index < 0 || p_index >= size()) {
|
||||
ERR_FAIL_COND(p_index < 0 || p_index >= size());
|
||||
if (p_index<0 || p_index>=size()) {
|
||||
ERR_FAIL_COND(p_index<0 || p_index>=size());
|
||||
}
|
||||
|
||||
Write w = write();
|
||||
w[p_index] = p_val;
|
||||
w[p_index]=p_val;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void PoolVector<T>::push_back(const T &p_val) {
|
||||
template<class T>
|
||||
void DVector<T>::push_back(const T& p_val) {
|
||||
|
||||
resize(size() + 1);
|
||||
set(size() - 1, p_val);
|
||||
resize( size() + 1 );
|
||||
set( size() -1, p_val );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const T PoolVector<T>::operator[](int p_index) const {
|
||||
template<class T>
|
||||
const T DVector<T>::operator[](int p_index) const {
|
||||
|
||||
CRASH_BAD_INDEX(p_index, size());
|
||||
if (p_index<0 || p_index>=size()) {
|
||||
T& aux=*((T*)0); //nullreturn
|
||||
ERR_FAIL_COND_V(p_index<0 || p_index>=size(),aux);
|
||||
}
|
||||
|
||||
Read r = read();
|
||||
|
||||
return r[p_index];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
Error PoolVector<T>::resize(int p_size) {
|
||||
|
||||
if (alloc == NULL) {
|
||||
template<class T>
|
||||
Error DVector<T>::resize(int p_size) {
|
||||
|
||||
if (p_size == 0)
|
||||
return OK; //nothing to do here
|
||||
if (dvector_lock)
|
||||
dvector_lock->lock();
|
||||
|
||||
//must allocate something
|
||||
MemoryPool::alloc_mutex->lock();
|
||||
if (MemoryPool::allocs_used == MemoryPool::alloc_count) {
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
ERR_EXPLAINC("All memory pool allocations are in use.");
|
||||
ERR_FAIL_V(ERR_OUT_OF_MEMORY);
|
||||
}
|
||||
bool same = p_size==size();
|
||||
|
||||
//take one from the free list
|
||||
alloc = MemoryPool::free_list;
|
||||
MemoryPool::free_list = alloc->free_list;
|
||||
//increment the used counter
|
||||
MemoryPool::allocs_used++;
|
||||
if (dvector_lock)
|
||||
dvector_lock->unlock();
|
||||
// no further locking is necesary because we are supposed to own the only copy of this (using copy on write)
|
||||
|
||||
//cleanup the alloc
|
||||
alloc->size = 0;
|
||||
alloc->refcount.init();
|
||||
alloc->pool_id = POOL_ALLOCATOR_INVALID_ID;
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
if (same)
|
||||
return OK;
|
||||
|
||||
} else {
|
||||
if (p_size == 0 ) {
|
||||
|
||||
ERR_FAIL_COND_V(alloc->lock > 0, ERR_LOCKED); //can't resize if locked!
|
||||
}
|
||||
|
||||
size_t new_size = sizeof(T) * p_size;
|
||||
|
||||
if (alloc->size == new_size)
|
||||
return OK; //nothing to do
|
||||
|
||||
if (p_size == 0) {
|
||||
_unreference();
|
||||
unreference();
|
||||
return OK;
|
||||
}
|
||||
|
||||
_copy_on_write(); // make it unique
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
MemoryPool::alloc_mutex->lock();
|
||||
MemoryPool::total_memory -= alloc->size;
|
||||
MemoryPool::total_memory += new_size;
|
||||
if (MemoryPool::total_memory > MemoryPool::max_memory) {
|
||||
MemoryPool::max_memory = MemoryPool::total_memory;
|
||||
}
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
#endif
|
||||
copy_on_write(); // make it unique
|
||||
|
||||
int cur_elements = alloc->size / sizeof(T);
|
||||
ERR_FAIL_COND_V( mem.is_locked(), ERR_LOCKED ); // if after copy on write, memory is locked, fail.
|
||||
|
||||
if (p_size > cur_elements) {
|
||||
if (p_size > size() ) {
|
||||
|
||||
int oldsize=size();
|
||||
|
||||
MID_Lock lock;
|
||||
|
||||
if (oldsize==0) {
|
||||
|
||||
mem = dynalloc( p_size * sizeof(T) + sizeof(int) );
|
||||
lock=MID_Lock(mem);
|
||||
int *rc = ((int*)lock.data());
|
||||
*rc=1;
|
||||
|
||||
if (MemoryPool::memory_pool) {
|
||||
//resize memory pool
|
||||
//if none, create
|
||||
//if some resize
|
||||
} else {
|
||||
|
||||
if (alloc->size == 0) {
|
||||
alloc->mem = memalloc(new_size);
|
||||
} else {
|
||||
alloc->mem = memrealloc(alloc->mem, new_size);
|
||||
if (dynrealloc( mem, p_size * sizeof(T) + sizeof(int) )!=OK ) {
|
||||
|
||||
ERR_FAIL_V(ERR_OUT_OF_MEMORY); // out of memory
|
||||
}
|
||||
|
||||
lock=MID_Lock(mem);
|
||||
}
|
||||
|
||||
alloc->size = new_size;
|
||||
|
||||
Write w = write();
|
||||
|
||||
for (int i = cur_elements; i < p_size; i++) {
|
||||
|
||||
memnew_placement(&w[i], T);
|
||||
T *t = (T*)((int*)lock.data() + 1);
|
||||
|
||||
for (int i=oldsize;i<p_size;i++) {
|
||||
|
||||
memnew_placement(&t[i], T );
|
||||
}
|
||||
|
||||
lock = MID_Lock(); // clear
|
||||
} else {
|
||||
|
||||
{
|
||||
Write w = write();
|
||||
for (int i = p_size; i < cur_elements; i++) {
|
||||
int oldsize=size();
|
||||
|
||||
w[i].~T();
|
||||
}
|
||||
MID_Lock lock(mem);
|
||||
|
||||
|
||||
T *t = (T*)((int*)lock.data() + 1);
|
||||
|
||||
for (int i=p_size;i<oldsize;i++) {
|
||||
|
||||
t[i].~T();
|
||||
}
|
||||
|
||||
if (MemoryPool::memory_pool) {
|
||||
//resize memory pool
|
||||
//if none, create
|
||||
//if some resize
|
||||
} else {
|
||||
lock = MID_Lock(); // clear
|
||||
|
||||
if (new_size == 0) {
|
||||
memfree(alloc->mem);
|
||||
alloc->mem = NULL;
|
||||
alloc->size = 0;
|
||||
if (dynrealloc( mem, p_size * sizeof(T) + sizeof(int) )!=OK ) {
|
||||
|
||||
MemoryPool::alloc_mutex->lock();
|
||||
alloc->free_list = MemoryPool::free_list;
|
||||
MemoryPool::free_list = alloc;
|
||||
MemoryPool::allocs_used--;
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
|
||||
} else {
|
||||
alloc->mem = memrealloc(alloc->mem, new_size);
|
||||
alloc->size = new_size;
|
||||
}
|
||||
ERR_FAIL_V(ERR_OUT_OF_MEMORY); // wtf error
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void PoolVector<T>::invert() {
|
||||
template<class T>
|
||||
void DVector<T>::invert() {
|
||||
T temp;
|
||||
Write w = write();
|
||||
int s = size();
|
||||
int half_s = s / 2;
|
||||
int half_s = s/2;
|
||||
|
||||
for (int i = 0; i < half_s; i++) {
|
||||
for(int i=0;i<half_s;i++) {
|
||||
temp = w[i];
|
||||
w[i] = w[s - i - 1];
|
||||
w[s - i - 1] = temp;
|
||||
w[i] = w[s-i-1];
|
||||
w[s-i-1] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
151
core/engine.cpp
151
core/engine.cpp
@ -1,151 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* engine.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "engine.h"
|
||||
|
||||
#include "version.h"
|
||||
#include "version_hash.gen.h"
|
||||
|
||||
void Engine::set_iterations_per_second(int p_ips) {
|
||||
|
||||
ips = p_ips;
|
||||
}
|
||||
int Engine::get_iterations_per_second() const {
|
||||
|
||||
return ips;
|
||||
}
|
||||
|
||||
void Engine::set_target_fps(int p_fps) {
|
||||
_target_fps = p_fps > 0 ? p_fps : 0;
|
||||
}
|
||||
|
||||
float Engine::get_target_fps() const {
|
||||
return _target_fps;
|
||||
}
|
||||
|
||||
uint64_t Engine::get_frames_drawn() {
|
||||
|
||||
return frames_drawn;
|
||||
}
|
||||
|
||||
void Engine::set_frame_delay(uint32_t p_msec) {
|
||||
|
||||
_frame_delay = p_msec;
|
||||
}
|
||||
|
||||
uint32_t Engine::get_frame_delay() const {
|
||||
|
||||
return _frame_delay;
|
||||
}
|
||||
|
||||
void Engine::set_time_scale(float p_scale) {
|
||||
|
||||
_time_scale = p_scale;
|
||||
}
|
||||
|
||||
float Engine::get_time_scale() const {
|
||||
|
||||
return _time_scale;
|
||||
}
|
||||
|
||||
Dictionary Engine::get_version_info() const {
|
||||
|
||||
Dictionary dict;
|
||||
dict["major"] = VERSION_MAJOR;
|
||||
dict["minor"] = VERSION_MINOR;
|
||||
#ifdef VERSION_PATCH
|
||||
dict["patch"] = VERSION_PATCH;
|
||||
#else
|
||||
dict["patch"] = 0;
|
||||
#endif
|
||||
dict["status"] = VERSION_STATUS;
|
||||
dict["build"] = VERSION_BUILD;
|
||||
dict["year"] = VERSION_YEAR;
|
||||
|
||||
String hash = VERSION_HASH;
|
||||
dict["hash"] = hash.length() == 0 ? String("unknown") : hash;
|
||||
|
||||
String stringver = String(dict["major"]) + "." + String(dict["minor"]);
|
||||
if ((int)dict["patch"] != 0)
|
||||
stringver += "." + String(dict["patch"]);
|
||||
stringver += "-" + String(dict["status"]) + " (" + String(dict["build"]) + ")";
|
||||
dict["string"] = stringver;
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
void Engine::add_singleton(const Singleton &p_singleton) {
|
||||
|
||||
singletons.push_back(p_singleton);
|
||||
singleton_ptrs[p_singleton.name] = p_singleton.ptr;
|
||||
}
|
||||
|
||||
Object *Engine::get_singleton_object(const String &p_name) const {
|
||||
|
||||
const Map<StringName, Object *>::Element *E = singleton_ptrs.find(p_name);
|
||||
ERR_EXPLAIN("Failed to retrieve non-existent singleton '" + p_name + "'");
|
||||
ERR_FAIL_COND_V(!E, NULL);
|
||||
return E->get();
|
||||
};
|
||||
|
||||
bool Engine::has_singleton(const String &p_name) const {
|
||||
|
||||
return singleton_ptrs.has(p_name);
|
||||
};
|
||||
|
||||
void Engine::get_singletons(List<Singleton> *p_singletons) {
|
||||
|
||||
for (List<Singleton>::Element *E = singletons.front(); E; E = E->next())
|
||||
p_singletons->push_back(E->get());
|
||||
}
|
||||
|
||||
Engine *Engine::singleton = NULL;
|
||||
|
||||
Engine *Engine::get_singleton() {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
Engine::Engine() {
|
||||
|
||||
singleton = this;
|
||||
frames_drawn = 0;
|
||||
ips = 60;
|
||||
_frame_delay = 0;
|
||||
_fps = 1;
|
||||
_target_fps = 0;
|
||||
_time_scale = 1.0;
|
||||
_pixel_snap = false;
|
||||
_physics_frames = 0;
|
||||
_idle_frames = 0;
|
||||
_in_physics = false;
|
||||
_frame_ticks = 0;
|
||||
_frame_step = 0;
|
||||
editor_hint = false;
|
||||
}
|
||||
121
core/engine.h
121
core/engine.h
@ -1,121 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* engine.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef ENGINE_H
|
||||
#define ENGINE_H
|
||||
|
||||
#include "list.h"
|
||||
#include "os/main_loop.h"
|
||||
#include "ustring.h"
|
||||
#include "vector.h"
|
||||
|
||||
class Engine {
|
||||
|
||||
public:
|
||||
struct Singleton {
|
||||
StringName name;
|
||||
Object *ptr;
|
||||
Singleton(const StringName &p_name = StringName(), Object *p_ptr = NULL) :
|
||||
name(p_name),
|
||||
ptr(p_ptr) {
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
friend class Main;
|
||||
|
||||
uint64_t frames_drawn;
|
||||
uint32_t _frame_delay;
|
||||
uint64_t _frame_ticks;
|
||||
float _frame_step;
|
||||
|
||||
int ips;
|
||||
float _fps;
|
||||
int _target_fps;
|
||||
float _time_scale;
|
||||
bool _pixel_snap;
|
||||
uint64_t _physics_frames;
|
||||
|
||||
uint64_t _idle_frames;
|
||||
bool _in_physics;
|
||||
|
||||
List<Singleton> singletons;
|
||||
Map<StringName, Object *> singleton_ptrs;
|
||||
|
||||
bool editor_hint;
|
||||
|
||||
static Engine *singleton;
|
||||
|
||||
public:
|
||||
static Engine *get_singleton();
|
||||
|
||||
virtual void set_iterations_per_second(int p_ips);
|
||||
virtual int get_iterations_per_second() const;
|
||||
|
||||
virtual void set_target_fps(int p_fps);
|
||||
virtual float get_target_fps() const;
|
||||
|
||||
virtual float get_frames_per_second() const { return _fps; }
|
||||
|
||||
uint64_t get_frames_drawn();
|
||||
|
||||
uint64_t get_physics_frames() const { return _physics_frames; }
|
||||
uint64_t get_idle_frames() const { return _idle_frames; }
|
||||
bool is_in_physics_frame() const { return _in_physics; }
|
||||
uint64_t get_idle_frame_ticks() const { return _frame_ticks; }
|
||||
float get_idle_frame_step() const { return _frame_step; }
|
||||
|
||||
void set_time_scale(float p_scale);
|
||||
float get_time_scale() const;
|
||||
|
||||
void set_frame_delay(uint32_t p_msec);
|
||||
uint32_t get_frame_delay() const;
|
||||
|
||||
void add_singleton(const Singleton &p_singleton);
|
||||
void get_singletons(List<Singleton> *p_singletons);
|
||||
bool has_singleton(const String &p_name) const;
|
||||
Object *get_singleton_object(const String &p_name) const;
|
||||
|
||||
_FORCE_INLINE_ bool get_use_pixel_snap() const { return _pixel_snap; }
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
_FORCE_INLINE_ void set_editor_hint(bool p_enabled) { editor_hint = p_enabled; }
|
||||
_FORCE_INLINE_ bool is_editor_hint() const { return editor_hint; }
|
||||
#else
|
||||
_FORCE_INLINE_ void set_editor_hint(bool p_enabled) {}
|
||||
_FORCE_INLINE_ bool is_editor_hint() const { return false; }
|
||||
#endif
|
||||
|
||||
Dictionary get_version_info() const;
|
||||
|
||||
Engine();
|
||||
};
|
||||
|
||||
#endif // ENGINE_H
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,7 +26,6 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef ERROR_LIST_H
|
||||
#define ERROR_LIST_H
|
||||
|
||||
@ -42,14 +40,14 @@ enum Error {
|
||||
OK,
|
||||
FAILED, ///< Generic fail error
|
||||
ERR_UNAVAILABLE, ///< What is requested is unsupported/unavailable
|
||||
ERR_UNCONFIGURED, ///< The object being used hasn't been properly set up yet
|
||||
ERR_UNCONFIGURED, ///< The object being used hasnt been properly set up yet
|
||||
ERR_UNAUTHORIZED, ///< Missing credentials for requested resource
|
||||
ERR_PARAMETER_RANGE_ERROR, ///< Parameter given out of range (5)
|
||||
ERR_OUT_OF_MEMORY, ///< Out of memory
|
||||
ERR_FILE_NOT_FOUND,
|
||||
ERR_FILE_BAD_DRIVE,
|
||||
ERR_FILE_BAD_PATH,
|
||||
ERR_FILE_NO_PERMISSION, // (10)
|
||||
ERR_FILE_NO_PERMISSION, // (10)
|
||||
ERR_FILE_ALREADY_IN_USE,
|
||||
ERR_FILE_CANT_OPEN,
|
||||
ERR_FILE_CANT_WRITE,
|
||||
@ -59,15 +57,15 @@ enum Error {
|
||||
ERR_FILE_MISSING_DEPENDENCIES,
|
||||
ERR_FILE_EOF,
|
||||
ERR_CANT_OPEN, ///< Can't open a resource/socket/file
|
||||
ERR_CANT_CREATE, // (20)
|
||||
ERR_QUERY_FAILED,
|
||||
ERR_CANT_CREATE, // (20)
|
||||
ERROR_QUERY_FAILED,
|
||||
ERR_ALREADY_IN_USE,
|
||||
ERR_LOCKED, ///< resource is locked
|
||||
ERR_TIMEOUT,
|
||||
ERR_CANT_CONNECT, // (25)
|
||||
ERR_LOCKED, ///< resource is locked
|
||||
ERR_TIMEOUT,
|
||||
ERR_CANT_CONNECT, // (25)
|
||||
ERR_CANT_RESOLVE,
|
||||
ERR_CONNECTION_ERROR,
|
||||
ERR_CANT_ACQUIRE_RESOURCE,
|
||||
ERR_CANT_AQUIRE_RESOURCE,
|
||||
ERR_CANT_FORK,
|
||||
ERR_INVALID_DATA, ///< Data passed is invalid (30)
|
||||
ERR_INVALID_PARAMETER, ///< Parameter passed is invalid
|
||||
@ -76,18 +74,23 @@ enum Error {
|
||||
ERR_DATABASE_CANT_READ, ///< database is full
|
||||
ERR_DATABASE_CANT_WRITE, ///< database is full (35)
|
||||
ERR_COMPILATION_FAILED,
|
||||
ERR_METHOD_NOT_FOUND,
|
||||
ERR_LINK_FAILED,
|
||||
ERR_METHOD_NOT_FOUND,
|
||||
ERR_LINK_FAILED,
|
||||
ERR_SCRIPT_FAILED,
|
||||
ERR_CYCLIC_LINK, // (40)
|
||||
ERR_CYCLIC_LINK, // (40)
|
||||
ERR_INVALID_DECLARATION,
|
||||
ERR_DUPLICATE_SYMBOL,
|
||||
ERR_PARSE_ERROR,
|
||||
ERR_BUSY,
|
||||
ERR_SKIP, // (45)
|
||||
ERR_SKIP, // (45)
|
||||
ERR_HELP, ///< user requested help!!
|
||||
ERR_BUG, ///< a bug in the software certainly happened, due to a double check failing or unexpected behavior.
|
||||
ERR_PRINTER_ON_FIRE, /// the parallel port printer is engulfed in flames
|
||||
ERR_OMFG_THIS_IS_VERY_VERY_BAD, ///< shit happens, has never been used, though
|
||||
ERR_WTF = ERR_OMFG_THIS_IS_VERY_VERY_BAD ///< short version of the above
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,17 +26,15 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "error_macros.h"
|
||||
|
||||
#include "io/logger.h"
|
||||
#include "os/os.h"
|
||||
|
||||
bool _err_error_exists = false;
|
||||
|
||||
static ErrorHandlerList *error_handler_list = NULL;
|
||||
bool _err_error_exists=false;
|
||||
|
||||
void _err_set_last_error(const char *p_err) {
|
||||
static ErrorHandlerList *error_handler_list=NULL;
|
||||
|
||||
void _err_set_last_error(const char* p_err) {
|
||||
|
||||
OS::get_singleton()->set_last_error(p_err);
|
||||
}
|
||||
@ -50,8 +47,8 @@ void _err_clear_last_error() {
|
||||
void add_error_handler(ErrorHandlerList *p_handler) {
|
||||
|
||||
_global_lock();
|
||||
p_handler->next = error_handler_list;
|
||||
error_handler_list = p_handler;
|
||||
p_handler->next=error_handler_list;
|
||||
error_handler_list=p_handler;
|
||||
_global_unlock();
|
||||
}
|
||||
|
||||
@ -62,46 +59,44 @@ void remove_error_handler(ErrorHandlerList *p_handler) {
|
||||
ErrorHandlerList *prev = NULL;
|
||||
ErrorHandlerList *l = error_handler_list;
|
||||
|
||||
while (l) {
|
||||
while(l) {
|
||||
|
||||
if (l == p_handler) {
|
||||
if (l==p_handler) {
|
||||
|
||||
if (prev)
|
||||
prev->next = l->next;
|
||||
prev->next=l->next;
|
||||
else
|
||||
error_handler_list = l->next;
|
||||
error_handler_list=l->next;
|
||||
break;
|
||||
}
|
||||
prev = l;
|
||||
l = l->next;
|
||||
prev=l;
|
||||
l=l->next;
|
||||
|
||||
}
|
||||
|
||||
_global_unlock();
|
||||
|
||||
}
|
||||
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type) {
|
||||
void _err_print_error(const char* p_function, const char* p_file,int p_line,const char *p_error,ErrorHandlerType p_type) {
|
||||
|
||||
OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, _err_error_exists ? OS::get_singleton()->get_last_error() : "", (Logger::ErrorType)p_type);
|
||||
|
||||
|
||||
OS::get_singleton()->print_error(p_function,p_file,p_line,p_error,_err_error_exists?OS::get_singleton()->get_last_error():"",(OS::ErrorType)p_type);
|
||||
|
||||
_global_lock();
|
||||
ErrorHandlerList *l = error_handler_list;
|
||||
while (l) {
|
||||
while(l) {
|
||||
|
||||
l->errfunc(l->userdata, p_function, p_file, p_line, p_error, _err_error_exists ? OS::get_singleton()->get_last_error() : "", p_type);
|
||||
l = l->next;
|
||||
l->errfunc(l->userdata,p_function,p_file,p_line,p_error,_err_error_exists?OS::get_singleton()->get_last_error():"",p_type);
|
||||
l=l->next;
|
||||
}
|
||||
|
||||
_global_unlock();
|
||||
|
||||
if (_err_error_exists) {
|
||||
OS::get_singleton()->clear_last_error();
|
||||
_err_error_exists = false;
|
||||
_err_error_exists=false;
|
||||
}
|
||||
}
|
||||
|
||||
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, bool fatal) {
|
||||
|
||||
String fstr(fatal ? "FATAL: " : "");
|
||||
String err(fstr + "Index " + p_index_str + "=" + itos(p_index) + " out of size (" + p_size_str + "=" + itos(p_size) + ")");
|
||||
_err_print_error(p_function, p_file, p_line, err.utf8().get_data());
|
||||
}
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,13 +26,12 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef ERROR_MACROS_H
|
||||
#define ERROR_MACROS_H
|
||||
|
||||
#include "typedefs.h"
|
||||
|
||||
/**
|
||||
* Error macros. Unlike exceptions and asserts, these macros try to maintain consistency and stability
|
||||
* Error macros. Unlike exceptions and asserts, these macros try to mantain consistency and stability
|
||||
* inside the code. It is recommended to always return processable data, so in case of an error, the
|
||||
* engine can stay working well.
|
||||
* In most cases, bugs and/or invalid data are not fatal and should never allow a perfectly running application
|
||||
@ -51,12 +49,11 @@
|
||||
enum ErrorHandlerType {
|
||||
ERR_HANDLER_ERROR,
|
||||
ERR_HANDLER_WARNING,
|
||||
ERR_HANDLER_SCRIPT,
|
||||
ERR_HANDLER_SHADER,
|
||||
ERR_HANDLER_SCRIPT
|
||||
};
|
||||
|
||||
typedef void (*ErrorHandlerFunc)(void *, const char *, const char *, int p_line, const char *, const char *, ErrorHandlerType p_type);
|
||||
void _err_set_last_error(const char *p_err);
|
||||
typedef void (*ErrorHandlerFunc)(void*,const char*,const char*,int p_line,const char *, const char *,ErrorHandlerType p_type);
|
||||
void _err_set_last_error(const char* p_err);
|
||||
void _err_clear_last_error();
|
||||
|
||||
struct ErrorHandlerList {
|
||||
@ -64,27 +61,22 @@ struct ErrorHandlerList {
|
||||
ErrorHandlerFunc errfunc;
|
||||
void *userdata;
|
||||
|
||||
ErrorHandlerList *next;
|
||||
ErrorHandlerList*next;
|
||||
|
||||
ErrorHandlerList() {
|
||||
errfunc = 0;
|
||||
next = 0;
|
||||
userdata = 0;
|
||||
}
|
||||
ErrorHandlerList() { errfunc=0; next=0; userdata=0; }
|
||||
};
|
||||
|
||||
void add_error_handler(ErrorHandlerList *p_handler);
|
||||
void remove_error_handler(ErrorHandlerList *p_handler);
|
||||
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
|
||||
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, bool fatal = false);
|
||||
void _err_print_error(const char* p_function,const char* p_file,int p_line,const char *p_error,ErrorHandlerType p_type=ERR_HANDLER_ERROR);
|
||||
|
||||
#ifndef _STR
|
||||
#define _STR(m_x) #m_x
|
||||
#define _MKSTR(m_x) _STR(m_x)
|
||||
#endif
|
||||
|
||||
#define _FNL __FILE__ ":"
|
||||
#define _FNL __FILE__":"
|
||||
|
||||
/** An index has failed if m_index<0 or m_index >=m_size, the function exists */
|
||||
|
||||
@ -93,21 +85,13 @@ extern bool _err_error_exists;
|
||||
#ifdef DEBUG_ENABLED
|
||||
/** Print a warning string.
|
||||
*/
|
||||
#define ERR_EXPLAINC(m_reason) \
|
||||
{ \
|
||||
_err_set_last_error(m_reason); \
|
||||
_err_error_exists = true; \
|
||||
}
|
||||
#define ERR_EXPLAIN(m_string) \
|
||||
{ \
|
||||
_err_set_last_error(String(m_string).utf8().get_data()); \
|
||||
_err_error_exists = true; \
|
||||
}
|
||||
#define ERR_EXPLAINC(m_reason) {_err_set_last_error(m_reason); _err_error_exists=true;}
|
||||
#define ERR_EXPLAIN(m_string) {_err_set_last_error(String(m_string).utf8().get_data()); _err_error_exists=true;}
|
||||
|
||||
#else
|
||||
|
||||
#define ERR_EXPLAIN(m_text)
|
||||
#define ERR_EXPLAINC(m_text)
|
||||
#define ERR_EXPLAIN( m_text )
|
||||
#define ERR_EXPLAINC( m_text )
|
||||
|
||||
#endif
|
||||
|
||||
@ -118,98 +102,49 @@ extern bool _err_error_exists;
|
||||
#define FUNCTION_STR __FUNCTION__
|
||||
#endif
|
||||
|
||||
// Don't use this directly; instead, use any of the CRASH_* macros
|
||||
#ifdef _MSC_VER
|
||||
#define GENERATE_TRAP \
|
||||
__debugbreak(); \
|
||||
/* Avoid warning about control paths */ \
|
||||
for (;;) { \
|
||||
}
|
||||
#else
|
||||
#define GENERATE_TRAP __builtin_trap();
|
||||
#endif
|
||||
|
||||
// (*): See https://stackoverflow.com/questions/257418/do-while-0-what-is-it-good-for
|
||||
|
||||
#define ERR_FAIL_INDEX(m_index, m_size) \
|
||||
do { \
|
||||
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
|
||||
return; \
|
||||
} else \
|
||||
_err_error_exists = false; \
|
||||
} while (0); // (*)
|
||||
#define ERR_FAIL_INDEX(m_index,m_size) \
|
||||
do {if ((m_index)<0 || (m_index)>=(m_size)) { \
|
||||
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Index " _STR(m_index)" out of size (" _STR(m_size)")."); \
|
||||
return; \
|
||||
} else _err_error_exists=false; } while(0); \
|
||||
|
||||
/** An index has failed if m_index<0 or m_index >=m_size, the function exists.
|
||||
* This function returns an error value, if returning Error, please select the most
|
||||
* appropriate error condition from error_macros.h
|
||||
*/
|
||||
* This function returns an error value, if returning Error, please select the most
|
||||
* appropriate error condition from error_macros.h
|
||||
*/
|
||||
|
||||
#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \
|
||||
do { \
|
||||
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
_err_error_exists = false; \
|
||||
} while (0); // (*)
|
||||
#define ERR_FAIL_INDEX_V(m_index,m_size,m_retval) \
|
||||
do {if ((m_index)<0 || (m_index)>=(m_size)) { \
|
||||
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Index " _STR(m_index)" out of size (" _STR(m_size)")."); \
|
||||
return m_retval; \
|
||||
} else _err_error_exists=false;} while (0);
|
||||
|
||||
/** Use this one if there is no sensible fallback, that is, the error is unrecoverable.
|
||||
* We'll return a null reference and try to keep running.
|
||||
*/
|
||||
#define CRASH_BAD_INDEX(m_index, m_size) \
|
||||
do { \
|
||||
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), true); \
|
||||
GENERATE_TRAP \
|
||||
} \
|
||||
} while (0); // (*)
|
||||
|
||||
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
|
||||
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
|
||||
* the function will exit.
|
||||
*/
|
||||
|
||||
#define ERR_FAIL_NULL(m_param) \
|
||||
{ \
|
||||
if (unlikely(!m_param)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \
|
||||
return; \
|
||||
} else \
|
||||
_err_error_exists = false; \
|
||||
}
|
||||
#define ERR_FAIL_NULL(m_param) \
|
||||
{ if ( !m_param ) { \
|
||||
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Parameter ' " _STR(m_param)" ' is null."); \
|
||||
return; \
|
||||
}else _err_error_exists=false; } \
|
||||
|
||||
#define ERR_FAIL_NULL_V(m_param, m_retval) \
|
||||
{ \
|
||||
if (unlikely(!m_param)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
_err_error_exists = false; \
|
||||
}
|
||||
|
||||
#define ERR_FAIL_NULL_V(m_param,m_retval) \
|
||||
{ if ( !m_param ) { \
|
||||
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Parameter ' " _STR(m_param)" ' is null."); \
|
||||
return m_retval; \
|
||||
}else _err_error_exists=false; } \
|
||||
|
||||
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
|
||||
* the function will exit.
|
||||
*/
|
||||
|
||||
#define ERR_FAIL_COND(m_cond) \
|
||||
{ \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true."); \
|
||||
return; \
|
||||
} else \
|
||||
_err_error_exists = false; \
|
||||
}
|
||||
|
||||
/** Use this one if there is no sensible fallback, that is, the error is unrecoverable.
|
||||
*/
|
||||
|
||||
#define CRASH_COND(m_cond) \
|
||||
{ \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition ' " _STR(m_cond) " ' is true."); \
|
||||
GENERATE_TRAP \
|
||||
} \
|
||||
}
|
||||
#define ERR_FAIL_COND(m_cond) \
|
||||
{ if ( m_cond ) { \
|
||||
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true."); \
|
||||
return; \
|
||||
}else _err_error_exists=false; } \
|
||||
|
||||
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
|
||||
* the function will exit.
|
||||
@ -217,98 +152,81 @@ extern bool _err_error_exists;
|
||||
* appropriate error condition from error_macros.h
|
||||
*/
|
||||
|
||||
#define ERR_FAIL_COND_V(m_cond, m_retval) \
|
||||
{ \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. returned: " _STR(m_retval)); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
_err_error_exists = false; \
|
||||
}
|
||||
#define ERR_FAIL_COND_V(m_cond,m_retval) \
|
||||
{ if ( m_cond ) { \
|
||||
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true. returned: " _STR(m_retval)); \
|
||||
return m_retval; \
|
||||
}else _err_error_exists=false; } \
|
||||
|
||||
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
|
||||
* the loop will skip to the next iteration.
|
||||
*/
|
||||
|
||||
#define ERR_CONTINUE(m_cond) \
|
||||
{ \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Continuing..:"); \
|
||||
continue; \
|
||||
} else \
|
||||
_err_error_exists = false; \
|
||||
}
|
||||
#define ERR_CONTINUE(m_cond) \
|
||||
{ if ( m_cond ) { \
|
||||
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true. Continuing..:"); \
|
||||
continue;\
|
||||
} else _err_error_exists=false;} \
|
||||
|
||||
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
|
||||
* the loop will break
|
||||
*/
|
||||
|
||||
#define ERR_BREAK(m_cond) \
|
||||
{ \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Breaking..:"); \
|
||||
break; \
|
||||
} else \
|
||||
_err_error_exists = false; \
|
||||
}
|
||||
#define ERR_BREAK(m_cond) \
|
||||
{ if ( m_cond ) { \
|
||||
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true. Breaking..:"); \
|
||||
break;\
|
||||
} else _err_error_exists=false;} \
|
||||
|
||||
/** Print an error string and return
|
||||
*/
|
||||
|
||||
#define ERR_FAIL() \
|
||||
{ \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed."); \
|
||||
_err_error_exists = false; \
|
||||
return; \
|
||||
}
|
||||
#define ERR_FAIL() \
|
||||
{ \
|
||||
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Method/Function Failed."); \
|
||||
_err_error_exists=false;\
|
||||
return;\
|
||||
} \
|
||||
|
||||
/** Print an error string and return with value
|
||||
*/
|
||||
|
||||
#define ERR_FAIL_V(m_value) \
|
||||
{ \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed, returning: " __STR(m_value)); \
|
||||
_err_error_exists = false; \
|
||||
return m_value; \
|
||||
}
|
||||
|
||||
/** Use this one if there is no sensible fallback, that is, the error is unrecoverable.
|
||||
*/
|
||||
|
||||
#define CRASH_NOW() \
|
||||
{ \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/Function Failed."); \
|
||||
GENERATE_TRAP \
|
||||
}
|
||||
#define ERR_FAIL_V(m_value) \
|
||||
{ \
|
||||
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Method/Function Failed, returning: " __STR(m_value)); \
|
||||
_err_error_exists=false; \
|
||||
return m_value;\
|
||||
} \
|
||||
|
||||
/** Print an error string.
|
||||
*/
|
||||
|
||||
#define ERR_PRINT(m_string) \
|
||||
{ \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string); \
|
||||
_err_error_exists = false; \
|
||||
}
|
||||
#define ERR_PRINT(m_string) \
|
||||
{ \
|
||||
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,m_string); \
|
||||
_err_error_exists=false;\
|
||||
} \
|
||||
|
||||
#define ERR_PRINTS(m_string) \
|
||||
{ \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, String(m_string).utf8().get_data()); \
|
||||
_err_error_exists = false; \
|
||||
}
|
||||
#define ERR_PRINTS(m_string) \
|
||||
{ \
|
||||
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,String(m_string).utf8().get_data()); \
|
||||
_err_error_exists=false;\
|
||||
} \
|
||||
|
||||
/** Print a warning string.
|
||||
*/
|
||||
|
||||
#define WARN_PRINT(m_string) \
|
||||
{ \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string, ERR_HANDLER_WARNING); \
|
||||
_err_error_exists = false; \
|
||||
}
|
||||
#define WARN_PRINT(m_string) \
|
||||
{ \
|
||||
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,m_string,ERR_HANDLER_WARNING); \
|
||||
_err_error_exists=false;\
|
||||
} \
|
||||
|
||||
#define WARN_PRINTS(m_string) \
|
||||
{ \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, String(m_string).utf8().get_data(), ERR_HANDLER_WARNING); \
|
||||
_err_error_exists = false; \
|
||||
}
|
||||
|
||||
#define WARN_PRINTS(m_string) \
|
||||
{ \
|
||||
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,String(m_string).utf8().get_data(),ERR_HANDLER_WARNING); \
|
||||
_err_error_exists=false;\
|
||||
} \
|
||||
|
||||
#endif
|
||||
|
||||
161
core/event_queue.cpp
Normal file
161
core/event_queue.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
/*************************************************************************/
|
||||
/* event_queue.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
#include "event_queue.h"
|
||||
|
||||
|
||||
Error EventQueue::push_call(uint32_t p_instance_ID, const StringName& p_method, VARIANT_ARG_DECLARE) {
|
||||
|
||||
uint8_t room_needed=sizeof(Event);
|
||||
int args=0;
|
||||
if (p_arg5.get_type()!=Variant::NIL)
|
||||
args=5;
|
||||
else if (p_arg4.get_type()!=Variant::NIL)
|
||||
args=4;
|
||||
else if (p_arg3.get_type()!=Variant::NIL)
|
||||
args=3;
|
||||
else if (p_arg2.get_type()!=Variant::NIL)
|
||||
args=2;
|
||||
else if (p_arg1.get_type()!=Variant::NIL)
|
||||
args=1;
|
||||
else
|
||||
args=0;
|
||||
|
||||
room_needed+=sizeof(Variant)*args;
|
||||
|
||||
ERR_FAIL_COND_V( (buffer_end+room_needed) >= buffer_size , ERR_OUT_OF_MEMORY );
|
||||
Event * ev = memnew_placement( &event_buffer[ buffer_end ], Event );
|
||||
ev->args=args;
|
||||
ev->instance_ID=p_instance_ID;
|
||||
ev->method=p_method;
|
||||
|
||||
buffer_end+=sizeof(Event);
|
||||
|
||||
if (args>=1) {
|
||||
|
||||
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
|
||||
buffer_end+=sizeof(Variant);
|
||||
*v=p_arg1;
|
||||
}
|
||||
|
||||
if (args>=2) {
|
||||
|
||||
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
|
||||
buffer_end+=sizeof(Variant);
|
||||
*v=p_arg2;
|
||||
}
|
||||
|
||||
if (args>=3) {
|
||||
|
||||
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
|
||||
buffer_end+=sizeof(Variant);
|
||||
*v=p_arg3;
|
||||
|
||||
}
|
||||
|
||||
if (args>=4) {
|
||||
|
||||
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
|
||||
buffer_end+=sizeof(Variant);
|
||||
*v=p_arg4;
|
||||
}
|
||||
|
||||
if (args>=5) {
|
||||
|
||||
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
|
||||
buffer_end+=sizeof(Variant);
|
||||
*v=p_arg5;
|
||||
}
|
||||
|
||||
if (buffer_end > buffer_max_used)
|
||||
buffer_max_used=buffer_end;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void EventQueue::flush_events() {
|
||||
|
||||
uint32_t read_pos=0;
|
||||
|
||||
while (read_pos < buffer_end ) {
|
||||
|
||||
Event *event = (Event*)&event_buffer[ read_pos ];
|
||||
Variant *args= (Variant*)(event+1);
|
||||
Object *obj = ObjectDB::get_instance(event->instance_ID);
|
||||
|
||||
if (obj) {
|
||||
// events don't expect a return value
|
||||
obj->call( event->method,
|
||||
(event->args>=1) ? args[0] : Variant(),
|
||||
(event->args>=2) ? args[1] : Variant(),
|
||||
(event->args>=3) ? args[2] : Variant(),
|
||||
(event->args>=4) ? args[3] : Variant(),
|
||||
(event->args>=5) ? args[4] : Variant() );
|
||||
}
|
||||
|
||||
if (event->args>=1) args[0].~Variant();
|
||||
if (event->args>=2) args[1].~Variant();
|
||||
if (event->args>=3) args[2].~Variant();
|
||||
if (event->args>=4) args[3].~Variant();
|
||||
if (event->args>=5) args[4].~Variant();
|
||||
event->~Event();
|
||||
|
||||
read_pos+=sizeof(Event)+sizeof(Variant)*event->args;
|
||||
}
|
||||
|
||||
buffer_end=0; // reset buffer
|
||||
}
|
||||
|
||||
EventQueue::EventQueue(uint32_t p_buffer_size) {
|
||||
|
||||
|
||||
buffer_end=0;
|
||||
buffer_max_used=0;
|
||||
buffer_size=p_buffer_size;
|
||||
event_buffer = memnew_arr( uint8_t, buffer_size );
|
||||
|
||||
}
|
||||
EventQueue::~EventQueue() {
|
||||
|
||||
uint32_t read_pos=0;
|
||||
|
||||
while (read_pos < buffer_end ) {
|
||||
|
||||
Event *event = (Event*)&event_buffer[ read_pos ];
|
||||
Variant *args= (Variant*)(event+1);
|
||||
for (int i=0;i<event->args;i++)
|
||||
args[i].~Variant();
|
||||
event->~Event();
|
||||
|
||||
read_pos+=sizeof(Event)+sizeof(Variant)*event->args;
|
||||
}
|
||||
|
||||
memdelete_arr(event_buffer);
|
||||
event_buffer=NULL;
|
||||
}
|
||||
|
||||
66
core/event_queue.h
Normal file
66
core/event_queue.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*************************************************************************/
|
||||
/* event_queue.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
#ifndef EVENT_QUEUE_H
|
||||
#define EVENT_QUEUE_H
|
||||
|
||||
#include "object.h"
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
class EventQueue {
|
||||
|
||||
enum {
|
||||
|
||||
DEFAULT_EVENT_QUEUE_SIZE_KB=256
|
||||
};
|
||||
|
||||
struct Event {
|
||||
|
||||
uint32_t instance_ID;
|
||||
StringName method;
|
||||
int args;
|
||||
};
|
||||
|
||||
|
||||
uint8_t *event_buffer;
|
||||
uint32_t buffer_end;
|
||||
uint32_t buffer_max_used;
|
||||
uint32_t buffer_size;
|
||||
public:
|
||||
|
||||
|
||||
Error push_call(uint32_t p_instance_ID, const StringName& p_method, VARIANT_ARG_LIST);
|
||||
void flush_events();
|
||||
|
||||
EventQueue(uint32_t p_buffer_size=DEFAULT_EVENT_QUEUE_SIZE_KB*1024);
|
||||
~EventQueue();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,49 +26,57 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "func_ref.h"
|
||||
|
||||
Variant FuncRef::call_func(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
|
||||
Variant FuncRef::call_func(const Variant** p_args, int p_argcount, Variant::CallError& r_error) {
|
||||
|
||||
if (id == 0) {
|
||||
r_error.error = Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL;
|
||||
if (id==0) {
|
||||
r_error.error=Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL;
|
||||
return Variant();
|
||||
}
|
||||
Object *obj = ObjectDB::get_instance(id);
|
||||
Object* obj = ObjectDB::get_instance(id);
|
||||
|
||||
if (!obj) {
|
||||
r_error.error = Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL;
|
||||
r_error.error=Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL;
|
||||
return Variant();
|
||||
}
|
||||
|
||||
return obj->call(function, p_args, p_argcount, r_error);
|
||||
return obj->call(function,p_args,p_argcount,r_error);
|
||||
|
||||
}
|
||||
|
||||
void FuncRef::set_instance(Object *p_obj) {
|
||||
void FuncRef::set_instance(Object *p_obj){
|
||||
|
||||
ERR_FAIL_NULL(p_obj);
|
||||
id = p_obj->get_instance_id();
|
||||
id=p_obj->get_instance_ID();
|
||||
}
|
||||
void FuncRef::set_function(const StringName &p_func) {
|
||||
void FuncRef::set_function(const StringName& p_func){
|
||||
|
||||
function = p_func;
|
||||
function=p_func;
|
||||
}
|
||||
|
||||
void FuncRef::_bind_methods() {
|
||||
|
||||
{
|
||||
MethodInfo mi;
|
||||
mi.name = "call_func";
|
||||
mi.name="call_func";
|
||||
Vector<Variant> defargs;
|
||||
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_func", &FuncRef::call_func, mi, defargs);
|
||||
for(int i=0;i<10;i++) {
|
||||
mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
|
||||
defargs.push_back(Variant());
|
||||
}
|
||||
ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_func",&FuncRef::call_func,mi,defargs);
|
||||
|
||||
}
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_instance", "instance"), &FuncRef::set_instance);
|
||||
ClassDB::bind_method(D_METHOD("set_function", "name"), &FuncRef::set_function);
|
||||
ObjectTypeDB::bind_method(_MD("set_instance","instance"),&FuncRef::set_instance);
|
||||
ObjectTypeDB::bind_method(_MD("set_function","name"),&FuncRef::set_function);
|
||||
|
||||
}
|
||||
|
||||
FuncRef::FuncRef() {
|
||||
|
||||
id = 0;
|
||||
FuncRef::FuncRef(){
|
||||
|
||||
id=0;
|
||||
}
|
||||
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,25 +26,25 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef FUNC_REF_H
|
||||
#define FUNC_REF_H
|
||||
|
||||
#include "reference.h"
|
||||
|
||||
class FuncRef : public Reference {
|
||||
class FuncRef : public Reference{
|
||||
|
||||
GDCLASS(FuncRef, Reference);
|
||||
OBJ_TYPE(FuncRef,Reference);
|
||||
ObjectID id;
|
||||
StringName function;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
static void _bind_methods();
|
||||
public:
|
||||
Variant call_func(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
|
||||
|
||||
Variant call_func(const Variant** p_args, int p_argcount, Variant::CallError& r_error);
|
||||
void set_instance(Object *p_obj);
|
||||
void set_function(const StringName &p_func);
|
||||
void set_function(const StringName& p_func);
|
||||
FuncRef();
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,16 +26,14 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef GLOBAL_CONSTANTS_H
|
||||
#define GLOBAL_CONSTANTS_H
|
||||
|
||||
#include "string_db.h"
|
||||
|
||||
class GlobalConstants {
|
||||
public:
|
||||
|
||||
static int get_global_constant_count();
|
||||
static StringName get_global_constant_enum(int p_idx);
|
||||
static const char *get_global_constant_name(int p_idx);
|
||||
static int get_global_constant_value(int p_idx);
|
||||
};
|
||||
|
||||
1562
core/globals.cpp
Normal file
1562
core/globals.cpp
Normal file
File diff suppressed because it is too large
Load Diff
154
core/globals.h
Normal file
154
core/globals.h
Normal file
@ -0,0 +1,154 @@
|
||||
/*************************************************************************/
|
||||
/* globals.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
#ifndef GLOBALS_H
|
||||
#define GLOBALS_H
|
||||
|
||||
#include "object.h"
|
||||
#include "set.h"
|
||||
#include "os/thread_safe.h"
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
class Globals : public Object {
|
||||
|
||||
OBJ_TYPE( Globals, Object );
|
||||
_THREAD_SAFE_CLASS_
|
||||
|
||||
public:
|
||||
|
||||
typedef Map<String,Variant> CustomMap;
|
||||
|
||||
struct Singleton {
|
||||
StringName name;
|
||||
Object *ptr;
|
||||
Singleton(const StringName& p_name=StringName(), Object *p_ptr=NULL) { name=p_name; ptr=p_ptr; }
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
enum {
|
||||
NO_ORDER_BASE=1<<18
|
||||
};
|
||||
|
||||
struct VariantContainer {
|
||||
int order;
|
||||
bool persist;
|
||||
Variant variant;
|
||||
bool hide_from_editor;
|
||||
bool overrided;
|
||||
VariantContainer(){ order=0; hide_from_editor=false; persist=false; overrided=false; }
|
||||
VariantContainer(const Variant& p_variant, int p_order, bool p_persist=false) { variant=p_variant; order=p_order; hide_from_editor=false; persist=p_persist; overrided=false; }
|
||||
};
|
||||
|
||||
bool registering_order;
|
||||
int last_order;
|
||||
Map<StringName,VariantContainer> props;
|
||||
String resource_path;
|
||||
Map<StringName,PropertyInfo> custom_prop_info;
|
||||
bool disable_platform_override;
|
||||
bool using_datapack;
|
||||
List<String> input_presets;
|
||||
|
||||
|
||||
bool _set(const StringName& p_name, const Variant& p_value);
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
static Globals *singleton;
|
||||
|
||||
Error _load_settings(const String p_path);
|
||||
Error _load_settings_binary(const String p_path);
|
||||
|
||||
Error _save_settings_text(const String& p_file,const Map<String,List<String> > &props,const CustomMap& p_custom=CustomMap());
|
||||
Error _save_settings_binary(const String& p_file,const Map<String,List<String> > &props,const CustomMap& p_custom=CustomMap());
|
||||
|
||||
List<Singleton> singletons;
|
||||
|
||||
Error _save_custom_bnd(const String& p_file);
|
||||
|
||||
bool _load_resource_pack(const String& p_pack);
|
||||
|
||||
void _add_property_info_bind(const Dictionary& p_info);
|
||||
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
|
||||
bool has(String p_var) const;
|
||||
String localize_path(const String& p_path) const;
|
||||
String globalize_path(const String& p_path) const;
|
||||
|
||||
void set_persisting(const String& p_name, bool p_persist);
|
||||
bool is_persisting(const String& p_name) const;
|
||||
|
||||
String get_resource_path() const;
|
||||
|
||||
static Globals *get_singleton();
|
||||
|
||||
void clear(const String& p_name);
|
||||
int get_order(const String& p_name) const;
|
||||
void set_order(const String& p_name, int p_order);
|
||||
|
||||
Error setup(const String& p_path, const String &p_main_pack);
|
||||
|
||||
Error save_custom(const String& p_path="",const CustomMap& p_custom=CustomMap(),const Set<String>& p_ignore_masks=Set<String>());
|
||||
Error save();
|
||||
void set_custom_property_info(const String& p_prop,const PropertyInfo& p_info);
|
||||
|
||||
void add_singleton(const Singleton &p_singleton);
|
||||
void get_singletons(List<Singleton> *p_singletons);
|
||||
|
||||
bool has_singleton(const String& p_name) const;
|
||||
|
||||
Vector<String> get_optimizer_presets() const;
|
||||
|
||||
List<String> get_input_presets() const { return input_presets; }
|
||||
|
||||
void set_disable_platform_override(bool p_disable);
|
||||
Object* get_singleton_object(const String& p_name) const;
|
||||
|
||||
void register_global_defaults();
|
||||
|
||||
bool is_using_datapack() const;
|
||||
|
||||
void set_registering_order(bool p_registering);
|
||||
|
||||
Globals();
|
||||
~Globals();
|
||||
|
||||
};
|
||||
|
||||
//not a macro any longer
|
||||
Variant _GLOBAL_DEF( const String& p_var, const Variant& p_default);
|
||||
#define GLOBAL_DEF(m_var,m_value) _GLOBAL_DEF(m_var,m_value)
|
||||
#endif
|
||||
422
core/hash_map.h
422
core/hash_map.h
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,16 +26,43 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef HASH_MAP_H
|
||||
#define HASH_MAP_H
|
||||
|
||||
#include "error_macros.h"
|
||||
#include "hashfuncs.h"
|
||||
#include "list.h"
|
||||
#include "math_funcs.h"
|
||||
#include "os/memory.h"
|
||||
#include "error_macros.h"
|
||||
#include "ustring.h"
|
||||
#include "os/memory.h"
|
||||
#include "list.h"
|
||||
|
||||
|
||||
class HashMapHahserDefault {
|
||||
public:
|
||||
|
||||
static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) {
|
||||
uint64_t v=p_int;
|
||||
v = (~v) + (v << 18); // v = (v << 18) - v - 1;
|
||||
v = v ^ (v >> 31);
|
||||
v = v * 21; // v = (v + (v << 2)) + (v << 4);
|
||||
v = v ^ (v >> 11);
|
||||
v = v + (v << 6);
|
||||
v = v ^ (v >> 22);
|
||||
return (int) v;
|
||||
}
|
||||
static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); }
|
||||
|
||||
|
||||
static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return p_int; }
|
||||
static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return (uint32_t)p_int; }
|
||||
static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return p_int; }
|
||||
static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return (uint32_t)p_int; }
|
||||
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; }
|
||||
static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; }
|
||||
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; }
|
||||
// static _FORCE_INLINE_ uint32_t hash(const void* p_ptr) { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @class HashMap
|
||||
@ -48,243 +74,242 @@
|
||||
* @param TKey Key, search is based on it, needs to be hasheable. It is unique in this container.
|
||||
* @param TData Data, data associated with the key
|
||||
* @param Hasher Hasher object, needs to provide a valid static hash function for TKey
|
||||
* @param Comparator comparator object, needs to be able to safely compare two TKey values. It needs to ensure that x == x for any items inserted in the map. Bear in mind that nan != nan when implementing an equality check.
|
||||
* @param MIN_HASH_TABLE_POWER Miminum size of the hash table, as a power of two. You rarely need to change this parameter.
|
||||
* @param RELATIONSHIP Relationship at which the hash table is resized. if amount of elements is RELATIONSHIP
|
||||
* times bigger than the hash table, table is resized to solve this condition. if RELATIONSHIP is zero, table is always MIN_HASH_TABLE_POWER.
|
||||
*
|
||||
*/
|
||||
|
||||
template <class TKey, class TData, class Hasher = HashMapHasherDefault, class Comparator = HashMapComparatorDefault<TKey>, uint8_t MIN_HASH_TABLE_POWER = 3, uint8_t RELATIONSHIP = 8>
|
||||
template<class TKey, class TData, class Hasher=HashMapHahserDefault,uint8_t MIN_HASH_TABLE_POWER=3,uint8_t RELATIONSHIP=8>
|
||||
class HashMap {
|
||||
public:
|
||||
|
||||
struct Pair {
|
||||
|
||||
TKey key;
|
||||
TData data;
|
||||
|
||||
Pair() {}
|
||||
Pair(const TKey &p_key, const TData &p_data) :
|
||||
key(p_key),
|
||||
data(p_data) {
|
||||
}
|
||||
Pair(const TKey& p_key, const TData& p_data) { key=p_key; data=p_data; }
|
||||
};
|
||||
|
||||
struct Element {
|
||||
private:
|
||||
friend class HashMap;
|
||||
|
||||
uint32_t hash;
|
||||
Element *next;
|
||||
Element() { next = 0; }
|
||||
Pair pair;
|
||||
|
||||
public:
|
||||
const TKey &key() const {
|
||||
return pair.key;
|
||||
}
|
||||
|
||||
TData &value() {
|
||||
return pair.data;
|
||||
}
|
||||
|
||||
const TData &value() const {
|
||||
return pair.value();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
Element **hash_table;
|
||||
struct Entry {
|
||||
|
||||
uint32_t hash;
|
||||
Entry *next;
|
||||
Pair pair;
|
||||
|
||||
Entry() { next=0; }
|
||||
};
|
||||
|
||||
Entry **hash_table;
|
||||
uint8_t hash_table_power;
|
||||
uint32_t elements;
|
||||
|
||||
void make_hash_table() {
|
||||
|
||||
ERR_FAIL_COND(hash_table);
|
||||
ERR_FAIL_COND( hash_table );
|
||||
|
||||
hash_table = memnew_arr(Element *, (1 << MIN_HASH_TABLE_POWER));
|
||||
|
||||
hash_table = memnew_arr( Entry*, (1<<MIN_HASH_TABLE_POWER) );
|
||||
|
||||
hash_table_power = MIN_HASH_TABLE_POWER;
|
||||
elements = 0;
|
||||
for (int i = 0; i < (1 << MIN_HASH_TABLE_POWER); i++)
|
||||
hash_table[i] = 0;
|
||||
elements=0;
|
||||
for (int i=0;i<(1<<MIN_HASH_TABLE_POWER);i++)
|
||||
hash_table[i]=0;
|
||||
}
|
||||
|
||||
void erase_hash_table() {
|
||||
|
||||
ERR_FAIL_COND(elements);
|
||||
|
||||
memdelete_arr(hash_table);
|
||||
hash_table = 0;
|
||||
hash_table_power = 0;
|
||||
elements = 0;
|
||||
memdelete_arr( hash_table );
|
||||
hash_table=0;
|
||||
hash_table_power=0;
|
||||
elements=0;
|
||||
}
|
||||
|
||||
void check_hash_table() {
|
||||
|
||||
int new_hash_table_power = -1;
|
||||
int new_hash_table_power=-1;
|
||||
|
||||
if ((int)elements > ((1 << hash_table_power) * RELATIONSHIP)) {
|
||||
if ((int)elements > ( (1<<hash_table_power) * RELATIONSHIP ) ) {
|
||||
/* rehash up */
|
||||
new_hash_table_power = hash_table_power + 1;
|
||||
new_hash_table_power=hash_table_power+1;
|
||||
|
||||
while ((int)elements > ((1 << new_hash_table_power) * RELATIONSHIP)) {
|
||||
while( (int)elements > ( (1<<new_hash_table_power) * RELATIONSHIP ) ) {
|
||||
|
||||
new_hash_table_power++;
|
||||
}
|
||||
|
||||
} else if ((hash_table_power > (int)MIN_HASH_TABLE_POWER) && ((int)elements < ((1 << (hash_table_power - 1)) * RELATIONSHIP))) {
|
||||
} else if ( (hash_table_power>(int)MIN_HASH_TABLE_POWER) && ((int)elements < ( (1<<(hash_table_power-1)) * RELATIONSHIP ) ) ) {
|
||||
|
||||
/* rehash down */
|
||||
new_hash_table_power = hash_table_power - 1;
|
||||
new_hash_table_power=hash_table_power-1;
|
||||
|
||||
while ((int)elements < ((1 << (new_hash_table_power - 1)) * RELATIONSHIP)) {
|
||||
while( (int)elements < ( (1<<(new_hash_table_power-1)) * RELATIONSHIP ) ) {
|
||||
|
||||
new_hash_table_power--;
|
||||
}
|
||||
|
||||
if (new_hash_table_power < (int)MIN_HASH_TABLE_POWER)
|
||||
new_hash_table_power = MIN_HASH_TABLE_POWER;
|
||||
if (new_hash_table_power<(int)MIN_HASH_TABLE_POWER)
|
||||
new_hash_table_power=MIN_HASH_TABLE_POWER;
|
||||
}
|
||||
|
||||
if (new_hash_table_power == -1)
|
||||
|
||||
if (new_hash_table_power==-1)
|
||||
return;
|
||||
|
||||
Element **new_hash_table = memnew_arr(Element *, (1 << new_hash_table_power));
|
||||
Entry ** new_hash_table = memnew_arr( Entry*, (1<<new_hash_table_power) );
|
||||
if (!new_hash_table) {
|
||||
|
||||
ERR_PRINT("Out of Memory");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < (1 << new_hash_table_power); i++) {
|
||||
for (int i=0;i<(1<<new_hash_table_power);i++) {
|
||||
|
||||
new_hash_table[i] = 0;
|
||||
new_hash_table[i]=0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < (1 << hash_table_power); i++) {
|
||||
for (int i=0;i<(1<<hash_table_power);i++) {
|
||||
|
||||
while (hash_table[i]) {
|
||||
while( hash_table[i] ) {
|
||||
|
||||
Element *se = hash_table[i];
|
||||
hash_table[i] = se->next;
|
||||
int new_pos = se->hash & ((1 << new_hash_table_power) - 1);
|
||||
se->next = new_hash_table[new_pos];
|
||||
new_hash_table[new_pos] = se;
|
||||
Entry *se=hash_table[i];
|
||||
hash_table[i]=se->next;
|
||||
int new_pos = se->hash & ((1<<new_hash_table_power)-1);
|
||||
se->next=new_hash_table[new_pos];
|
||||
new_hash_table[new_pos]=se;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (hash_table)
|
||||
memdelete_arr(hash_table);
|
||||
hash_table = new_hash_table;
|
||||
hash_table_power = new_hash_table_power;
|
||||
memdelete_arr( hash_table );
|
||||
hash_table=new_hash_table;
|
||||
hash_table_power=new_hash_table_power;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* I want to have only one function.. */
|
||||
_FORCE_INLINE_ const Element *get_element(const TKey &p_key) const {
|
||||
_FORCE_INLINE_ const Entry * get_entry( const TKey& p_key ) const {
|
||||
|
||||
uint32_t hash = Hasher::hash(p_key);
|
||||
uint32_t index = hash & ((1 << hash_table_power) - 1);
|
||||
uint32_t hash = Hasher::hash( p_key );
|
||||
uint32_t index = hash&((1<<hash_table_power)-1);
|
||||
|
||||
Element *e = hash_table[index];
|
||||
Entry *e = hash_table[index];
|
||||
|
||||
while (e) {
|
||||
|
||||
/* checking hash first avoids comparing key, which may take longer */
|
||||
if (e->hash == hash && Comparator::compare(e->pair.key, p_key)) {
|
||||
if (e->hash == hash && e->pair.key == p_key ) {
|
||||
|
||||
/* the pair exists in this hashtable, so just update data */
|
||||
return e;
|
||||
}
|
||||
|
||||
e = e->next;
|
||||
e=e->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Element *create_element(const TKey &p_key) {
|
||||
Entry * create_entry(const TKey& p_key) {
|
||||
|
||||
/* if element doesn't exist, create it */
|
||||
Element *e = memnew(Element);
|
||||
ERR_FAIL_COND_V(!e, NULL); /* out of memory */
|
||||
uint32_t hash = Hasher::hash(p_key);
|
||||
uint32_t index = hash & ((1 << hash_table_power) - 1);
|
||||
/* if entry doesn't exist, create it */
|
||||
Entry *e = memnew( Entry );
|
||||
ERR_FAIL_COND_V(!e,NULL); /* out of memory */
|
||||
uint32_t hash = Hasher::hash( p_key );
|
||||
uint32_t index = hash&((1<<hash_table_power)-1);
|
||||
e->next = hash_table[index];
|
||||
e->hash = hash;
|
||||
e->pair.key = p_key;
|
||||
e->pair.key=p_key;
|
||||
|
||||
hash_table[index] = e;
|
||||
hash_table[index]=e;
|
||||
elements++;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void copy_from(const HashMap &p_t) {
|
||||
|
||||
if (&p_t == this)
|
||||
void copy_from(const HashMap& p_t) {
|
||||
|
||||
if (&p_t==this)
|
||||
return; /* much less bother with that */
|
||||
|
||||
clear();
|
||||
|
||||
if (!p_t.hash_table || p_t.hash_table_power == 0)
|
||||
if (!p_t.hash_table || p_t.hash_table_power==0)
|
||||
return; /* not copying from empty table */
|
||||
|
||||
hash_table = memnew_arr(Element *, 1 << p_t.hash_table_power);
|
||||
hash_table_power = p_t.hash_table_power;
|
||||
elements = p_t.elements;
|
||||
hash_table = memnew_arr(Entry*,1<<p_t.hash_table_power);
|
||||
hash_table_power=p_t.hash_table_power;
|
||||
elements=p_t.elements;
|
||||
|
||||
for (int i = 0; i < (1 << p_t.hash_table_power); i++) {
|
||||
for (int i=0;i<( 1<<p_t.hash_table_power );i++) {
|
||||
|
||||
hash_table[i] = NULL;
|
||||
hash_table[i]=NULL;
|
||||
/* elements will be in the reverse order, but it doesn't matter */
|
||||
|
||||
const Element *e = p_t.hash_table[i];
|
||||
const Entry *e = p_t.hash_table[i];
|
||||
|
||||
while (e) {
|
||||
while(e) {
|
||||
|
||||
Element *le = memnew(Element); /* local element */
|
||||
Entry *le = memnew( Entry ); /* local entry */
|
||||
|
||||
*le = *e; /* copy data */
|
||||
*le=*e; /* copy data */
|
||||
|
||||
/* add to list and reassign pointers */
|
||||
le->next = hash_table[i];
|
||||
hash_table[i] = le;
|
||||
le->next=hash_table[i];
|
||||
hash_table[i]=le;
|
||||
|
||||
e = e->next;
|
||||
e=e->next;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
public:
|
||||
Element *set(const TKey &p_key, const TData &p_data) {
|
||||
return set(Pair(p_key, p_data));
|
||||
|
||||
|
||||
void set( const TKey& p_key, const TData& p_data ) {
|
||||
|
||||
set( Pair( p_key, p_data ) );
|
||||
|
||||
}
|
||||
|
||||
Element *set(const Pair &p_pair) {
|
||||
void set( const Pair& p_pair ) {
|
||||
|
||||
Element *e = NULL;
|
||||
Entry *e=NULL;
|
||||
if (!hash_table)
|
||||
make_hash_table(); // if no table, make one
|
||||
else
|
||||
e = const_cast<Element *>(get_element(p_pair.key));
|
||||
e = const_cast<Entry*>( get_entry(p_pair.key) );
|
||||
|
||||
/* if we made it up to here, the pair doesn't exist, create and assign */
|
||||
|
||||
if (!e) {
|
||||
|
||||
e = create_element(p_pair.key);
|
||||
e=create_entry(p_pair.key);
|
||||
if (!e)
|
||||
return NULL;
|
||||
return;
|
||||
check_hash_table(); // perform mantenience routine
|
||||
}
|
||||
|
||||
e->pair.data = p_pair.data;
|
||||
return e;
|
||||
|
||||
}
|
||||
|
||||
bool has(const TKey &p_key) const {
|
||||
|
||||
return getptr(p_key) != NULL;
|
||||
bool has( const TKey& p_key ) const {
|
||||
|
||||
return getptr(p_key)!=NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -293,17 +318,17 @@ public:
|
||||
* first with has(key)
|
||||
*/
|
||||
|
||||
const TData &get(const TKey &p_key) const {
|
||||
const TData& get( const TKey& p_key ) const {
|
||||
|
||||
const TData *res = getptr(p_key);
|
||||
ERR_FAIL_COND_V(!res, *res);
|
||||
const TData* res = getptr(p_key);
|
||||
ERR_FAIL_COND_V(!res,*res);
|
||||
return *res;
|
||||
}
|
||||
|
||||
TData &get(const TKey &p_key) {
|
||||
TData& get( const TKey& p_key ) {
|
||||
|
||||
TData *res = getptr(p_key);
|
||||
ERR_FAIL_COND_V(!res, *res);
|
||||
TData* res = getptr(p_key);
|
||||
ERR_FAIL_COND_V(!res,*res);
|
||||
return *res;
|
||||
}
|
||||
|
||||
@ -312,30 +337,33 @@ public:
|
||||
* This is mainly used for speed purposes.
|
||||
*/
|
||||
|
||||
_FORCE_INLINE_ TData *getptr(const TKey &p_key) {
|
||||
|
||||
if (unlikely(!hash_table))
|
||||
_FORCE_INLINE_ TData* getptr( const TKey& p_key ) {
|
||||
|
||||
if (!hash_table)
|
||||
return NULL;
|
||||
|
||||
Element *e = const_cast<Element *>(get_element(p_key));
|
||||
Entry *e=const_cast<Entry*>(get_entry(p_key ));
|
||||
|
||||
if (e)
|
||||
return &e->pair.data;
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ const TData *getptr(const TKey &p_key) const {
|
||||
_FORCE_INLINE_ const TData* getptr( const TKey& p_key ) const {
|
||||
|
||||
if (unlikely(!hash_table))
|
||||
if (!hash_table)
|
||||
return NULL;
|
||||
|
||||
const Element *e = const_cast<Element *>(get_element(p_key));
|
||||
const Entry *e=const_cast<Entry*>(get_entry(p_key ));
|
||||
|
||||
if (e)
|
||||
return &e->pair.data;
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -343,123 +371,129 @@ public:
|
||||
* This version is custom, will take a hash and a custom key (that should support operator==()
|
||||
*/
|
||||
|
||||
template <class C>
|
||||
_FORCE_INLINE_ TData *custom_getptr(C p_custom_key, uint32_t p_custom_hash) {
|
||||
template<class C>
|
||||
_FORCE_INLINE_ TData* custom_getptr( C p_custom_key,uint32_t p_custom_hash ) {
|
||||
|
||||
if (unlikely(!hash_table))
|
||||
if (!hash_table)
|
||||
return NULL;
|
||||
|
||||
uint32_t hash = p_custom_hash;
|
||||
uint32_t index = hash & ((1 << hash_table_power) - 1);
|
||||
uint32_t index = hash&((1<<hash_table_power)-1);
|
||||
|
||||
Element *e = hash_table[index];
|
||||
Entry *e = hash_table[index];
|
||||
|
||||
while (e) {
|
||||
|
||||
/* checking hash first avoids comparing key, which may take longer */
|
||||
if (e->hash == hash && Comparator::compare(e->pair.key, p_custom_key)) {
|
||||
if (e->hash == hash && e->pair.key == p_custom_key ) {
|
||||
|
||||
/* the pair exists in this hashtable, so just update data */
|
||||
return &e->pair.data;
|
||||
}
|
||||
|
||||
e = e->next;
|
||||
e=e->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <class C>
|
||||
_FORCE_INLINE_ const TData *custom_getptr(C p_custom_key, uint32_t p_custom_hash) const {
|
||||
template<class C>
|
||||
_FORCE_INLINE_ const TData* custom_getptr( C p_custom_key,uint32_t p_custom_hash ) const {
|
||||
|
||||
if (unlikely(!hash_table))
|
||||
if (!hash_table)
|
||||
return NULL;
|
||||
|
||||
uint32_t hash = p_custom_hash;
|
||||
uint32_t index = hash & ((1 << hash_table_power) - 1);
|
||||
uint32_t index = hash&((1<<hash_table_power)-1);
|
||||
|
||||
const Element *e = hash_table[index];
|
||||
const Entry *e = hash_table[index];
|
||||
|
||||
while (e) {
|
||||
|
||||
/* checking hash first avoids comparing key, which may take longer */
|
||||
if (e->hash == hash && Comparator::compare(e->pair.key, p_custom_key)) {
|
||||
if (e->hash == hash && e->pair.key == p_custom_key ) {
|
||||
|
||||
/* the pair exists in this hashtable, so just update data */
|
||||
return &e->pair.data;
|
||||
}
|
||||
|
||||
e = e->next;
|
||||
e=e->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Erase an item, return true if erasing was successful
|
||||
* Erase an item, return true if erasing was succesful
|
||||
*/
|
||||
|
||||
bool erase(const TKey &p_key) {
|
||||
bool erase( const TKey& p_key ) {
|
||||
|
||||
if (unlikely(!hash_table))
|
||||
if (!hash_table)
|
||||
return false;
|
||||
|
||||
uint32_t hash = Hasher::hash(p_key);
|
||||
uint32_t index = hash & ((1 << hash_table_power) - 1);
|
||||
uint32_t hash = Hasher::hash( p_key );
|
||||
uint32_t index = hash&((1<<hash_table_power)-1);
|
||||
|
||||
Element *e = hash_table[index];
|
||||
Element *p = NULL;
|
||||
|
||||
Entry *e = hash_table[index];
|
||||
Entry *p=NULL;
|
||||
while (e) {
|
||||
|
||||
/* checking hash first avoids comparing key, which may take longer */
|
||||
if (e->hash == hash && Comparator::compare(e->pair.key, p_key)) {
|
||||
if (e->hash == hash && e->pair.key == p_key ) {
|
||||
|
||||
if (p) {
|
||||
|
||||
p->next = e->next;
|
||||
p->next=e->next;
|
||||
} else {
|
||||
//begin of list
|
||||
hash_table[index] = e->next;
|
||||
hash_table[index]=e->next;
|
||||
}
|
||||
|
||||
memdelete(e);
|
||||
elements--;
|
||||
|
||||
if (elements == 0)
|
||||
if (elements==0)
|
||||
erase_hash_table();
|
||||
else
|
||||
check_hash_table();
|
||||
return true;
|
||||
}
|
||||
|
||||
p = e;
|
||||
e = e->next;
|
||||
p=e;
|
||||
e=e->next;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
inline const TData &operator[](const TKey &p_key) const { //constref
|
||||
inline const TData& operator[](const TKey& p_key) const { //constref
|
||||
|
||||
return get(p_key);
|
||||
}
|
||||
inline TData &operator[](const TKey &p_key) { //assignment
|
||||
inline TData& operator[](const TKey& p_key ) { //assignment
|
||||
|
||||
Element *e = NULL;
|
||||
Entry *e=NULL;
|
||||
if (!hash_table)
|
||||
make_hash_table(); // if no table, make one
|
||||
else
|
||||
e = const_cast<Element *>(get_element(p_key));
|
||||
e = const_cast<Entry*>( get_entry(p_key) );
|
||||
|
||||
/* if we made it up to here, the pair doesn't exist, create */
|
||||
if (!e) {
|
||||
|
||||
e = create_element(p_key);
|
||||
CRASH_COND(!e);
|
||||
e=create_entry(p_key);
|
||||
if (!e)
|
||||
return *(TData*)NULL; /* panic! */
|
||||
check_hash_table(); // perform mantenience routine
|
||||
}
|
||||
|
||||
return e->pair.data;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -477,14 +511,13 @@ public:
|
||||
* }
|
||||
*
|
||||
*/
|
||||
const TKey *next(const TKey *p_key) const {
|
||||
const TKey* next(const TKey* p_key) const {
|
||||
|
||||
if (unlikely(!hash_table))
|
||||
return NULL;
|
||||
if (!hash_table) return NULL;
|
||||
|
||||
if (!p_key) { /* get the first key */
|
||||
|
||||
for (int i = 0; i < (1 << hash_table_power); i++) {
|
||||
for (int i=0;i<(1<<hash_table_power);i++) {
|
||||
|
||||
if (hash_table[i]) {
|
||||
return &hash_table[i]->pair.key;
|
||||
@ -493,17 +526,17 @@ public:
|
||||
|
||||
} else { /* get the next key */
|
||||
|
||||
const Element *e = get_element(*p_key);
|
||||
ERR_FAIL_COND_V(!e, NULL); /* invalid key supplied */
|
||||
const Entry *e = get_entry( *p_key );
|
||||
ERR_FAIL_COND_V( !e, NULL ); /* invalid key supplied */
|
||||
|
||||
if (e->next) {
|
||||
/* if there is a "next" in the list, return that */
|
||||
return &e->next->pair.key;
|
||||
} else {
|
||||
/* go to next elements */
|
||||
uint32_t index = e->hash & ((1 << hash_table_power) - 1);
|
||||
/* go to next entries */
|
||||
uint32_t index = e->hash&((1<<hash_table_power)-1);
|
||||
index++;
|
||||
for (int i = index; i < (1 << hash_table_power); i++) {
|
||||
for (int i=index;i<(1<<hash_table_power);i++) {
|
||||
|
||||
if (hash_table[i]) {
|
||||
return &hash_table[i]->pair.key;
|
||||
@ -512,8 +545,10 @@ public:
|
||||
}
|
||||
|
||||
/* nothing found, was at end */
|
||||
|
||||
}
|
||||
|
||||
|
||||
return NULL; /* nothing found */
|
||||
}
|
||||
|
||||
@ -524,82 +559,71 @@ public:
|
||||
|
||||
inline bool empty() const {
|
||||
|
||||
return elements == 0;
|
||||
return elements==0;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
|
||||
/* clean up */
|
||||
if (hash_table) {
|
||||
for (int i = 0; i < (1 << hash_table_power); i++) {
|
||||
for (int i=0;i<(1<<hash_table_power);i++) {
|
||||
|
||||
while (hash_table[i]) {
|
||||
|
||||
Element *e = hash_table[i];
|
||||
hash_table[i] = e->next;
|
||||
memdelete(e);
|
||||
Entry *e=hash_table[i];
|
||||
hash_table[i]=e->next;
|
||||
memdelete( e );
|
||||
}
|
||||
}
|
||||
|
||||
memdelete_arr(hash_table);
|
||||
memdelete_arr( hash_table );
|
||||
}
|
||||
|
||||
hash_table = 0;
|
||||
hash_table_power = 0;
|
||||
elements = 0;
|
||||
hash_table=0;
|
||||
hash_table_power=0;
|
||||
elements=0;
|
||||
}
|
||||
|
||||
void operator=(const HashMap &p_table) {
|
||||
|
||||
void operator=(const HashMap& p_table) {
|
||||
|
||||
copy_from(p_table);
|
||||
}
|
||||
|
||||
HashMap() {
|
||||
hash_table = NULL;
|
||||
elements = 0;
|
||||
hash_table_power = 0;
|
||||
}
|
||||
|
||||
void get_key_value_ptr_array(const Pair **p_pairs) const {
|
||||
if (unlikely(!hash_table))
|
||||
return;
|
||||
for (int i = 0; i < (1 << hash_table_power); i++) {
|
||||
|
||||
Element *e = hash_table[i];
|
||||
while (e) {
|
||||
*p_pairs = &e->pair;
|
||||
p_pairs++;
|
||||
e = e->next;
|
||||
}
|
||||
}
|
||||
hash_table=NULL;
|
||||
elements=0;
|
||||
hash_table_power=0;
|
||||
}
|
||||
|
||||
void get_key_list(List<TKey> *p_keys) const {
|
||||
if (unlikely(!hash_table))
|
||||
if (!hash_table)
|
||||
return;
|
||||
for (int i = 0; i < (1 << hash_table_power); i++) {
|
||||
for(int i=0;i<(1<<hash_table_power);i++) {
|
||||
|
||||
Element *e = hash_table[i];
|
||||
while (e) {
|
||||
Entry *e=hash_table[i];
|
||||
while(e) {
|
||||
p_keys->push_back(e->pair.key);
|
||||
e = e->next;
|
||||
e=e->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HashMap(const HashMap &p_table) {
|
||||
HashMap(const HashMap& p_table) {
|
||||
|
||||
hash_table = NULL;
|
||||
elements = 0;
|
||||
hash_table_power = 0;
|
||||
hash_table=NULL;
|
||||
elements=0;
|
||||
hash_table_power=0;
|
||||
|
||||
copy_from(p_table);
|
||||
|
||||
}
|
||||
|
||||
~HashMap() {
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,19 +26,17 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef HASHFUNCS_H
|
||||
#define HASHFUNCS_H
|
||||
|
||||
#include "math_defs.h"
|
||||
#include "math_funcs.h"
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "ustring.h"
|
||||
|
||||
/**
|
||||
* Hashing functions
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* DJB2 Hash function
|
||||
* @param C String
|
||||
@ -47,7 +44,7 @@
|
||||
*/
|
||||
static inline uint32_t hash_djb2(const char *p_cstr) {
|
||||
|
||||
const unsigned char *chr = (const unsigned char *)p_cstr;
|
||||
const unsigned char* chr=(const unsigned char*)p_cstr;
|
||||
uint32_t hash = 5381;
|
||||
uint32_t c;
|
||||
|
||||
@ -57,110 +54,66 @@ static inline uint32_t hash_djb2(const char *p_cstr) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
static inline uint32_t hash_djb2_buffer(const uint8_t *p_buff, int p_len, uint32_t p_prev = 5381) {
|
||||
static inline uint32_t hash_djb2_buffer(const uint8_t *p_buff, int p_len,uint32_t p_prev=5381) {
|
||||
|
||||
uint32_t hash = p_prev;
|
||||
|
||||
for (int i = 0; i < p_len; i++)
|
||||
for(int i=0;i<p_len;i++)
|
||||
hash = ((hash << 5) + hash) + p_buff[i]; /* hash * 33 + c */
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
static inline uint32_t hash_djb2_one_32(uint32_t p_in, uint32_t p_prev = 5381) {
|
||||
static inline uint32_t hash_djb2_one_32(uint32_t p_in,uint32_t p_prev=5381) {
|
||||
|
||||
return ((p_prev << 5) + p_prev) + p_in;
|
||||
return ((p_prev<<5)+p_prev)+p_in;
|
||||
}
|
||||
|
||||
static inline uint32_t hash_one_uint64(const uint64_t p_int) {
|
||||
uint64_t v = p_int;
|
||||
v = (~v) + (v << 18); // v = (v << 18) - v - 1;
|
||||
v = v ^ (v >> 31);
|
||||
v = v * 21; // v = (v + (v << 2)) + (v << 4);
|
||||
v = v ^ (v >> 11);
|
||||
v = v + (v << 6);
|
||||
v = v ^ (v >> 22);
|
||||
return (int)v;
|
||||
}
|
||||
|
||||
static inline uint32_t hash_djb2_one_float(double p_in, uint32_t p_prev = 5381) {
|
||||
static inline uint32_t hash_djb2_one_float(float p_in,uint32_t p_prev=5381) {
|
||||
union {
|
||||
double d;
|
||||
uint64_t i;
|
||||
float f;
|
||||
uint32_t i;
|
||||
} u;
|
||||
|
||||
// Normalize +/- 0.0 and NaN values so they hash the same.
|
||||
if (p_in == 0.0f)
|
||||
u.d = 0.0;
|
||||
else if (Math::is_nan(p_in))
|
||||
u.d = Math_NAN;
|
||||
else
|
||||
u.d = p_in;
|
||||
// handle -0 case
|
||||
if (p_in==0.0f) u.f=0.0f;
|
||||
else u.f=p_in;
|
||||
|
||||
return ((p_prev << 5) + p_prev) + hash_one_uint64(u.i);
|
||||
return ((p_prev<<5)+p_prev)+u.i;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template<class T>
|
||||
static inline uint32_t make_uint32_t(T p_in) {
|
||||
|
||||
union {
|
||||
T t;
|
||||
uint32_t _u32;
|
||||
} _u;
|
||||
_u._u32 = 0;
|
||||
_u.t = p_in;
|
||||
_u._u32=0;
|
||||
_u.t=p_in;
|
||||
return _u._u32;
|
||||
}
|
||||
|
||||
static inline uint64_t hash_djb2_one_64(uint64_t p_in, uint64_t p_prev = 5381) {
|
||||
|
||||
return ((p_prev << 5) + p_prev) + p_in;
|
||||
static inline uint64_t hash_djb2_one_64(uint64_t p_in,uint64_t p_prev=5381) {
|
||||
|
||||
return ((p_prev<<5)+p_prev)+p_in;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
||||
template<class T>
|
||||
static inline uint64_t make_uint64_t(T p_in) {
|
||||
|
||||
union {
|
||||
T t;
|
||||
uint64_t _u64;
|
||||
} _u;
|
||||
_u._u64 = 0; // in case p_in is smaller
|
||||
_u._u64=0; // in case p_in is smaller
|
||||
|
||||
_u.t = p_in;
|
||||
_u.t=p_in;
|
||||
return _u._u64;
|
||||
}
|
||||
|
||||
struct HashMapHasherDefault {
|
||||
static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); }
|
||||
|
||||
static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_djb2_one_float(p_double); }
|
||||
static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return p_int; }
|
||||
static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return (uint32_t)p_int; }
|
||||
static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return p_int; }
|
||||
static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return (uint32_t)p_int; }
|
||||
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; }
|
||||
static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; }
|
||||
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; }
|
||||
//static _FORCE_INLINE_ uint32_t hash(const void* p_ptr) { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct HashMapComparatorDefault {
|
||||
static bool compare(const T &p_lhs, const T &p_rhs) {
|
||||
return p_lhs == p_rhs;
|
||||
}
|
||||
|
||||
bool compare(const float &p_lhs, const float &p_rhs) {
|
||||
return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs));
|
||||
}
|
||||
|
||||
bool compare(const double &p_lhs, const double &p_rhs) {
|
||||
return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs));
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
Import('env')
|
||||
|
||||
env.add_source_files(env.core_sources, "*.cpp")
|
||||
|
||||
Export('env')
|
||||
@ -1,181 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* math_fieldwise.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
#include "core/helper/math_fieldwise.h"
|
||||
|
||||
#define SETUP_TYPE(m_type) \
|
||||
m_type source = p_source; \
|
||||
m_type target = p_target;
|
||||
#define TRY_TRANSFER_FIELD(m_name, m_member) \
|
||||
if (p_field == m_name) { \
|
||||
target.m_member = source.m_member; \
|
||||
}
|
||||
|
||||
Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const String &p_field) {
|
||||
|
||||
ERR_FAIL_COND_V(p_target.get_type() != p_source.get_type(), p_target);
|
||||
|
||||
/* clang-format makes a mess of this macro usage */
|
||||
/* clang-format off */
|
||||
|
||||
switch (p_source.get_type()) {
|
||||
|
||||
case Variant::VECTOR2: {
|
||||
|
||||
SETUP_TYPE(Vector2)
|
||||
|
||||
/**/ TRY_TRANSFER_FIELD("x", x)
|
||||
else TRY_TRANSFER_FIELD("y", y)
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
case Variant::RECT2: {
|
||||
|
||||
SETUP_TYPE(Rect2)
|
||||
|
||||
/**/ TRY_TRANSFER_FIELD("x", position.x)
|
||||
else TRY_TRANSFER_FIELD("y", position.y)
|
||||
else TRY_TRANSFER_FIELD("w", size.x)
|
||||
else TRY_TRANSFER_FIELD("h", size.y)
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
case Variant::VECTOR3: {
|
||||
|
||||
SETUP_TYPE(Vector3)
|
||||
|
||||
/**/ TRY_TRANSFER_FIELD("x", x)
|
||||
else TRY_TRANSFER_FIELD("y", y)
|
||||
else TRY_TRANSFER_FIELD("z", z)
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
case Variant::PLANE: {
|
||||
|
||||
SETUP_TYPE(Plane)
|
||||
|
||||
/**/ TRY_TRANSFER_FIELD("x", normal.x)
|
||||
else TRY_TRANSFER_FIELD("y", normal.y)
|
||||
else TRY_TRANSFER_FIELD("z", normal.z)
|
||||
else TRY_TRANSFER_FIELD("d", d)
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
case Variant::QUAT: {
|
||||
|
||||
SETUP_TYPE(Quat)
|
||||
|
||||
/**/ TRY_TRANSFER_FIELD("x", x)
|
||||
else TRY_TRANSFER_FIELD("y", y)
|
||||
else TRY_TRANSFER_FIELD("z", z)
|
||||
else TRY_TRANSFER_FIELD("w", w)
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
case Variant::AABB: {
|
||||
|
||||
SETUP_TYPE(AABB)
|
||||
|
||||
/**/ TRY_TRANSFER_FIELD("px", position.x)
|
||||
else TRY_TRANSFER_FIELD("py", position.y)
|
||||
else TRY_TRANSFER_FIELD("pz", position.z)
|
||||
else TRY_TRANSFER_FIELD("sx", size.x)
|
||||
else TRY_TRANSFER_FIELD("sy", size.y)
|
||||
else TRY_TRANSFER_FIELD("sz", size.z)
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
case Variant::TRANSFORM2D: {
|
||||
|
||||
SETUP_TYPE(Transform2D)
|
||||
|
||||
/**/ TRY_TRANSFER_FIELD("xx", elements[0][0])
|
||||
else TRY_TRANSFER_FIELD("xy", elements[0][1])
|
||||
else TRY_TRANSFER_FIELD("yx", elements[1][0])
|
||||
else TRY_TRANSFER_FIELD("yy", elements[1][1])
|
||||
else TRY_TRANSFER_FIELD("ox", elements[2][0])
|
||||
else TRY_TRANSFER_FIELD("oy", elements[2][1])
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
case Variant::BASIS: {
|
||||
|
||||
SETUP_TYPE(Basis)
|
||||
|
||||
/**/ TRY_TRANSFER_FIELD("xx", elements[0][0])
|
||||
else TRY_TRANSFER_FIELD("xy", elements[0][1])
|
||||
else TRY_TRANSFER_FIELD("xz", elements[0][2])
|
||||
else TRY_TRANSFER_FIELD("yx", elements[1][0])
|
||||
else TRY_TRANSFER_FIELD("yy", elements[1][1])
|
||||
else TRY_TRANSFER_FIELD("yz", elements[1][2])
|
||||
else TRY_TRANSFER_FIELD("zx", elements[2][0])
|
||||
else TRY_TRANSFER_FIELD("zy", elements[2][1])
|
||||
else TRY_TRANSFER_FIELD("zz", elements[2][2])
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
case Variant::TRANSFORM: {
|
||||
|
||||
SETUP_TYPE(Transform)
|
||||
|
||||
/**/ TRY_TRANSFER_FIELD("xx", basis.elements[0][0])
|
||||
else TRY_TRANSFER_FIELD("xy", basis.elements[0][1])
|
||||
else TRY_TRANSFER_FIELD("xz", basis.elements[0][2])
|
||||
else TRY_TRANSFER_FIELD("yx", basis.elements[1][0])
|
||||
else TRY_TRANSFER_FIELD("yy", basis.elements[1][1])
|
||||
else TRY_TRANSFER_FIELD("yz", basis.elements[1][2])
|
||||
else TRY_TRANSFER_FIELD("zx", basis.elements[2][0])
|
||||
else TRY_TRANSFER_FIELD("zy", basis.elements[2][1])
|
||||
else TRY_TRANSFER_FIELD("zz", basis.elements[2][2])
|
||||
else TRY_TRANSFER_FIELD("xo", origin.x)
|
||||
else TRY_TRANSFER_FIELD("yo", origin.y)
|
||||
else TRY_TRANSFER_FIELD("zo", origin.z)
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
default: {
|
||||
ERR_FAIL_V(p_target);
|
||||
}
|
||||
}
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
#endif // TOOLS_ENABLED
|
||||
@ -1,42 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* math_fieldwise.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef MATH_FIELDWISE_H
|
||||
#define MATH_FIELDWISE_H
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
#include "core/variant.h"
|
||||
|
||||
Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const String &p_field);
|
||||
|
||||
#endif // TOOLS_ENABLED
|
||||
|
||||
#endif // MATH_FIELDWISE_H
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,7 +26,6 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef VALUE_EVALUATOR_H
|
||||
#define VALUE_EVALUATOR_H
|
||||
|
||||
@ -35,10 +33,9 @@
|
||||
|
||||
class ValueEvaluator : public Object {
|
||||
|
||||
GDCLASS(ValueEvaluator, Object);
|
||||
|
||||
OBJ_TYPE(ValueEvaluator, Object);
|
||||
public:
|
||||
virtual double eval(const String &p_text) {
|
||||
virtual double eval(const String& p_text) {
|
||||
return p_text.to_double();
|
||||
}
|
||||
};
|
||||
|
||||
3499
core/image.cpp
3499
core/image.cpp
File diff suppressed because it is too large
Load Diff
374
core/image.h
374
core/image.h
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,15 +26,12 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef IMAGE_H
|
||||
#define IMAGE_H
|
||||
|
||||
#include "color.h"
|
||||
#include "dvector.h"
|
||||
#include "color.h"
|
||||
#include "math_2d.h"
|
||||
#include "resource.h"
|
||||
|
||||
/**
|
||||
* @author Juan Linietsky <reduzio@gmail.com>
|
||||
*
|
||||
@ -46,62 +42,52 @@
|
||||
|
||||
class Image;
|
||||
|
||||
typedef Error (*SavePNGFunc)(const String &p_path, const Ref<Image> &p_img);
|
||||
typedef Error (*SavePNGFunc)(const String &p_path, Image& p_img);
|
||||
|
||||
class Image : public Resource {
|
||||
GDCLASS(Image, Resource);
|
||||
|
||||
public:
|
||||
static SavePNGFunc save_png_func;
|
||||
class Image {
|
||||
|
||||
enum {
|
||||
MAX_WIDTH = 16384, // force a limit somehow
|
||||
MAX_HEIGHT = 16384 // force a limit somehow
|
||||
MAX_WIDTH=16384, // force a limit somehow
|
||||
MAX_HEIGHT=16384// force a limit somehow
|
||||
};
|
||||
public:
|
||||
|
||||
static SavePNGFunc save_png_func;
|
||||
|
||||
enum Format {
|
||||
|
||||
FORMAT_L8, //luminance
|
||||
FORMAT_LA8, //luminance-alpha
|
||||
FORMAT_R8,
|
||||
FORMAT_RG8,
|
||||
FORMAT_RGB8,
|
||||
FORMAT_RGBA8,
|
||||
FORMAT_RGBA4444,
|
||||
FORMAT_RGBA5551,
|
||||
FORMAT_RF, //float
|
||||
FORMAT_RGF,
|
||||
FORMAT_RGBF,
|
||||
FORMAT_RGBAF,
|
||||
FORMAT_RH, //half float
|
||||
FORMAT_RGH,
|
||||
FORMAT_RGBH,
|
||||
FORMAT_RGBAH,
|
||||
FORMAT_RGBE9995,
|
||||
FORMAT_DXT1, //s3tc bc1
|
||||
FORMAT_DXT3, //bc2
|
||||
FORMAT_DXT5, //bc3
|
||||
FORMAT_RGTC_R,
|
||||
FORMAT_RGTC_RG,
|
||||
FORMAT_BPTC_RGBA, //btpc bc7
|
||||
FORMAT_BPTC_RGBF, //float bc6h
|
||||
FORMAT_BPTC_RGBFU, //unsigned float bc6hu
|
||||
FORMAT_PVRTC2, //pvrtc
|
||||
FORMAT_PVRTC2A,
|
||||
FORMAT_GRAYSCALE, ///< one byte per pixel, 0-255
|
||||
FORMAT_INTENSITY, ///< one byte per pixel, 0-255
|
||||
FORMAT_GRAYSCALE_ALPHA, ///< two bytes per pixel, 0-255. alpha 0-255
|
||||
FORMAT_RGB, ///< one byte R, one byte G, one byte B
|
||||
FORMAT_RGBA, ///< one byte R, one byte G, one byte B, one byte A
|
||||
FORMAT_INDEXED, ///< index byte 0-256, and after image end, 256*3 bytes of palette
|
||||
FORMAT_INDEXED_ALPHA, ///< index byte 0-256, and after image end, 256*4 bytes of palette (alpha)
|
||||
FORMAT_YUV_422,
|
||||
FORMAT_YUV_444,
|
||||
FORMAT_BC1, // DXT1
|
||||
FORMAT_BC2, // DXT3
|
||||
FORMAT_BC3, // DXT5
|
||||
FORMAT_BC4, // ATI1
|
||||
FORMAT_BC5, // ATI2
|
||||
FORMAT_PVRTC2,
|
||||
FORMAT_PVRTC2_ALPHA,
|
||||
FORMAT_PVRTC4,
|
||||
FORMAT_PVRTC4A,
|
||||
FORMAT_ETC, //etc1
|
||||
FORMAT_ETC2_R11, //etc2
|
||||
FORMAT_ETC2_R11S, //signed, NOT srgb.
|
||||
FORMAT_ETC2_RG11,
|
||||
FORMAT_ETC2_RG11S,
|
||||
FORMAT_ETC2_RGB8,
|
||||
FORMAT_ETC2_RGBA8,
|
||||
FORMAT_ETC2_RGB8A1,
|
||||
FORMAT_PVRTC4_ALPHA,
|
||||
FORMAT_ETC, // regular ETC, no transparency
|
||||
FORMAT_ATC,
|
||||
FORMAT_ATC_ALPHA_EXPLICIT,
|
||||
FORMAT_ATC_ALPHA_INTERPOLATED,
|
||||
/*FORMAT_ETC2_R, for the future..
|
||||
FORMAT_ETC2_RG,
|
||||
FORMAT_ETC2_RGB,
|
||||
FORMAT_ETC2_RGBA1,
|
||||
FORMAT_ETC2_RGBA,*/
|
||||
FORMAT_CUSTOM,
|
||||
|
||||
FORMAT_MAX
|
||||
};
|
||||
|
||||
static const char *format_names[FORMAT_MAX];
|
||||
static const char* format_names[FORMAT_MAX];
|
||||
enum Interpolation {
|
||||
|
||||
INTERPOLATE_NEAREST,
|
||||
@ -110,82 +96,141 @@ public:
|
||||
/* INTERPOLATE GAUSS */
|
||||
};
|
||||
|
||||
enum CompressSource {
|
||||
COMPRESS_SOURCE_GENERIC,
|
||||
COMPRESS_SOURCE_SRGB,
|
||||
COMPRESS_SOURCE_NORMAL
|
||||
};
|
||||
|
||||
//some functions provided by something else
|
||||
|
||||
static Ref<Image> (*_png_mem_loader_func)(const uint8_t *p_png, int p_size);
|
||||
static Ref<Image> (*_jpg_mem_loader_func)(const uint8_t *p_png, int p_size);
|
||||
|
||||
static void (*_image_compress_bc_func)(Image *, CompressSource p_source);
|
||||
static Image (*_png_mem_loader_func)(const uint8_t* p_png,int p_size);
|
||||
static Image (*_jpg_mem_loader_func)(const uint8_t* p_png,int p_size);
|
||||
static void (*_image_compress_bc_func)(Image *);
|
||||
static void (*_image_compress_pvrtc2_func)(Image *);
|
||||
static void (*_image_compress_pvrtc4_func)(Image *);
|
||||
static void (*_image_compress_etc1_func)(Image *, float);
|
||||
static void (*_image_compress_etc2_func)(Image *, float, CompressSource p_source);
|
||||
|
||||
static void (*_image_compress_etc_func)(Image *);
|
||||
static void (*_image_decompress_pvrtc)(Image *);
|
||||
static void (*_image_decompress_bc)(Image *);
|
||||
static void (*_image_decompress_etc1)(Image *);
|
||||
static void (*_image_decompress_etc2)(Image *);
|
||||
static void (*_image_decompress_etc)(Image *);
|
||||
|
||||
static PoolVector<uint8_t> (*lossy_packer)(const Ref<Image> &p_image, float p_quality);
|
||||
static Ref<Image> (*lossy_unpacker)(const PoolVector<uint8_t> &p_buffer);
|
||||
static PoolVector<uint8_t> (*lossless_packer)(const Ref<Image> &p_image);
|
||||
static Ref<Image> (*lossless_unpacker)(const PoolVector<uint8_t> &p_buffer);
|
||||
|
||||
PoolVector<uint8_t>::Write write_lock;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
Error _decompress_bc();
|
||||
|
||||
static DVector<uint8_t> (*lossy_packer)(const Image& p_image,float p_quality);
|
||||
static Image (*lossy_unpacker)(const DVector<uint8_t>& p_buffer);
|
||||
static DVector<uint8_t> (*lossless_packer)(const Image& p_image);
|
||||
static Image (*lossless_unpacker)(const DVector<uint8_t>& p_buffer);
|
||||
private:
|
||||
void _create_empty(int p_width, int p_height, bool p_use_mipmaps, Format p_format) {
|
||||
create(p_width, p_height, p_use_mipmaps, p_format);
|
||||
}
|
||||
|
||||
void _create_from_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const PoolVector<uint8_t> &p_data) {
|
||||
create(p_width, p_height, p_use_mipmaps, p_format, p_data);
|
||||
}
|
||||
//internal byte based color
|
||||
struct BColor {
|
||||
union {
|
||||
uint8_t col[4];
|
||||
struct {
|
||||
uint8_t r,g,b,a;
|
||||
};
|
||||
};
|
||||
|
||||
bool operator==(const BColor& p_color) const { for(int i=0;i<4;i++) {if (col[i]!=p_color.col[i]) return false; } return true; }
|
||||
_FORCE_INLINE_ uint8_t gray() const { return (uint16_t(col[0])+uint16_t(col[1])+uint16_t(col[2]))/3; }
|
||||
_FORCE_INLINE_ BColor() {}
|
||||
BColor(uint8_t p_r,uint8_t p_g,uint8_t p_b,uint8_t p_a=255) { col[0]=p_r; col[1]=p_g; col[2]=p_b; col[3]=p_a; }
|
||||
};
|
||||
|
||||
//median cut classes
|
||||
|
||||
struct BColorPos {
|
||||
|
||||
uint32_t index;
|
||||
BColor color;
|
||||
struct SortR {
|
||||
|
||||
bool operator()(const BColorPos& ca, const BColorPos& cb) const { return ca.color.r < cb.color.r; }
|
||||
};
|
||||
|
||||
struct SortG {
|
||||
|
||||
bool operator()(const BColorPos& ca, const BColorPos& cb) const { return ca.color.g < cb.color.g; }
|
||||
};
|
||||
|
||||
struct SortB {
|
||||
|
||||
bool operator()(const BColorPos& ca, const BColorPos& cb) const { return ca.color.b < cb.color.b; }
|
||||
};
|
||||
|
||||
struct SortA {
|
||||
|
||||
bool operator()(const BColorPos& ca, const BColorPos& cb) const { return ca.color.a < cb.color.a; }
|
||||
};
|
||||
};
|
||||
|
||||
struct SPTree {
|
||||
|
||||
bool leaf;
|
||||
uint8_t split_plane;
|
||||
uint8_t split_value;
|
||||
union {
|
||||
int left;
|
||||
int color;
|
||||
};
|
||||
int right;
|
||||
SPTree() { leaf=true; left=-1; right=-1;}
|
||||
};
|
||||
|
||||
struct MCBlock {
|
||||
|
||||
BColorPos min_color,max_color;
|
||||
BColorPos *colors;
|
||||
int sp_idx;
|
||||
int color_count;
|
||||
int get_longest_axis_index() const;
|
||||
int get_longest_axis_length() const;
|
||||
bool operator<(const MCBlock& p_block) const;
|
||||
void shrink();
|
||||
MCBlock();
|
||||
MCBlock(BColorPos *p_colors,int p_color_count);
|
||||
};
|
||||
|
||||
Format format;
|
||||
PoolVector<uint8_t> data;
|
||||
int width, height;
|
||||
bool mipmaps;
|
||||
DVector<uint8_t> data;
|
||||
int width,height,mipmaps;
|
||||
|
||||
void _copy_internals_from(const Image &p_image) {
|
||||
format = p_image.format;
|
||||
width = p_image.width;
|
||||
height = p_image.height;
|
||||
mipmaps = p_image.mipmaps;
|
||||
data = p_image.data;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void _get_mipmap_offset_and_size(int p_mipmap, int &r_offset, int &r_width, int &r_height) const; //get where the mipmap begins in data
|
||||
|
||||
static int _get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps = -1);
|
||||
_FORCE_INLINE_ BColor _get_pixel(int p_x,int p_y,const unsigned char *p_data,int p_data_size) const;
|
||||
_FORCE_INLINE_ BColor _get_pixelw(int p_x,int p_y,int p_width,const unsigned char *p_data,int p_data_size) const;
|
||||
_FORCE_INLINE_ void _put_pixelw(int p_x,int p_y, int p_width, const BColor& p_color, unsigned char *p_data);
|
||||
_FORCE_INLINE_ void _put_pixel(int p_x,int p_y, const BColor& p_color, unsigned char *p_data);
|
||||
_FORCE_INLINE_ void _get_mipmap_offset_and_size(int p_mipmap,int &r_offset, int &r_width, int &r_height) const; //get where the mipmap begins in data
|
||||
_FORCE_INLINE_ static void _get_format_min_data_size(Format p_format,int &r_w, int &r_h);
|
||||
|
||||
static int _get_dst_image_size(int p_width, int p_height, Format p_format,int &r_mipmaps,int p_mipmaps=-1);
|
||||
bool _can_modify(Format p_format) const;
|
||||
|
||||
_FORCE_INLINE_ void _put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, const uint8_t *p_pixel);
|
||||
_FORCE_INLINE_ void _get_pixelb(int p_x, int p_y, uint32_t p_pixelsize, const uint8_t *p_data, uint8_t *p_pixel);
|
||||
|
||||
void _set_data(const Dictionary &p_data);
|
||||
Dictionary _get_data() const;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
|
||||
int get_width() const; ///< Get image width
|
||||
int get_height() const; ///< Get image height
|
||||
Vector2 get_size() const;
|
||||
bool has_mipmaps() const;
|
||||
int get_mipmap_count() const;
|
||||
int get_mipmaps() const;
|
||||
|
||||
/**
|
||||
* Convert the image to another format, conversion only to raw byte format
|
||||
* Get a pixel from the image. for grayscale or indexed formats, use Color::gray to obtain the actual
|
||||
* value.
|
||||
*/
|
||||
void convert(Format p_new_format);
|
||||
Color get_pixel(int p_x,int p_y,int p_mipmap=0) const;
|
||||
/**
|
||||
* Set a pixel into the image. for grayscale or indexed formats, a suitable Color constructor.
|
||||
*/
|
||||
void put_pixel(int p_x,int p_y, const Color& p_color,int p_mipmap=0); /* alpha and index are averaged */
|
||||
|
||||
/**
|
||||
* Convert the image to another format, as close as it can be done.
|
||||
*/
|
||||
void convert( Format p_new_format );
|
||||
|
||||
Image converted(int p_new_format) {
|
||||
ERR_FAIL_INDEX_V(p_new_format, FORMAT_MAX, Image());
|
||||
|
||||
Image ret = *this;
|
||||
ret.convert((Format)p_new_format);
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the current image format.
|
||||
@ -193,50 +238,57 @@ public:
|
||||
Format get_format() const;
|
||||
|
||||
int get_mipmap_offset(int p_mipmap) const; //get where the mipmap begins in data
|
||||
void get_mipmap_offset_and_size(int p_mipmap, int &r_ofs, int &r_size) const; //get where the mipmap begins in data
|
||||
void get_mipmap_offset_size_and_dimensions(int p_mipmap, int &r_ofs, int &r_size, int &w, int &h) const; //get where the mipmap begins in data
|
||||
void get_mipmap_offset_and_size(int p_mipmap,int &r_ofs, int &r_size) const; //get where the mipmap begins in data
|
||||
void get_mipmap_offset_size_and_dimensions(int p_mipmap,int &r_ofs, int &r_size,int &w, int& h) const; //get where the mipmap begins in data
|
||||
|
||||
/**
|
||||
* Resize the image, using the preferred interpolation method.
|
||||
* Resize the image, using the prefered interpolation method.
|
||||
* Indexed-Color images always use INTERPOLATE_NEAREST.
|
||||
*/
|
||||
|
||||
void resize_to_po2(bool p_square = false);
|
||||
void resize(int p_width, int p_height, Interpolation p_interpolation = INTERPOLATE_BILINEAR);
|
||||
void resize_to_po2(bool p_square=false);
|
||||
void resize( int p_width, int p_height, Interpolation p_interpolation=INTERPOLATE_BILINEAR );
|
||||
Image resized( int p_width, int p_height, int p_interpolation=INTERPOLATE_BILINEAR );
|
||||
void shrink_x2();
|
||||
void expand_x2_hq2x();
|
||||
/**
|
||||
* Crop the image to a specific size, if larger, then the image is filled by black
|
||||
*/
|
||||
void crop_from_point(int p_x, int p_y, int p_width, int p_height);
|
||||
void crop(int p_width, int p_height);
|
||||
void crop( int p_width, int p_height );
|
||||
|
||||
|
||||
void flip_x();
|
||||
void flip_y();
|
||||
|
||||
/**
|
||||
* Generate a mipmap to an image (creates an image 1/4 the size, with averaging of 4->1)
|
||||
*/
|
||||
Error generate_mipmaps();
|
||||
Error generate_mipmaps(int p_amount=-1,bool p_keep_existing=false);
|
||||
|
||||
void clear_mipmaps();
|
||||
|
||||
|
||||
/**
|
||||
* Generate a normal map from a grayscale image
|
||||
*/
|
||||
|
||||
void make_normalmap(float p_height_scale=1.0);
|
||||
|
||||
/**
|
||||
* Create a new image of a given size and format. Current image will be lost
|
||||
*/
|
||||
void create(int p_width, int p_height, bool p_use_mipmaps, Format p_format);
|
||||
void create(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const PoolVector<uint8_t> &p_data);
|
||||
void create(int p_width, int p_height, int p_mipmaps, Format p_format, const DVector<uint8_t>& p_data);
|
||||
|
||||
void create(const char **p_xpm);
|
||||
void create( const char ** p_xpm );
|
||||
/**
|
||||
* returns true when the image is empty (0,0) in size
|
||||
*/
|
||||
bool empty() const;
|
||||
|
||||
PoolVector<uint8_t> get_data() const;
|
||||
DVector<uint8_t> get_data() const;
|
||||
|
||||
Error load(const String &p_path);
|
||||
Error save_png(const String &p_path) const;
|
||||
Error load(const String& p_path);
|
||||
Error save_png(const String& p_path);
|
||||
|
||||
/**
|
||||
* create an empty image
|
||||
@ -249,7 +301,7 @@ public:
|
||||
/**
|
||||
* import an image of a specific size and format from a pointer
|
||||
*/
|
||||
Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const PoolVector<uint8_t> &p_data);
|
||||
Image(int p_width, int p_height, int p_mipmaps, Format p_format, const DVector<uint8_t>& p_data);
|
||||
|
||||
enum AlphaMode {
|
||||
ALPHA_NONE,
|
||||
@ -260,24 +312,35 @@ public:
|
||||
AlphaMode detect_alpha() const;
|
||||
bool is_invisible() const;
|
||||
|
||||
void put_indexed_pixel(int p_x, int p_y, uint8_t p_idx,int p_mipmap=0);
|
||||
uint8_t get_indexed_pixel(int p_x, int p_y,int p_mipmap=0) const;
|
||||
void set_pallete(const DVector<uint8_t>& p_data);
|
||||
|
||||
|
||||
static int get_format_pixel_size(Format p_format);
|
||||
static int get_format_pixel_rshift(Format p_format);
|
||||
static int get_format_block_size(Format p_format);
|
||||
static void get_format_min_pixel_size(Format p_format, int &r_w, int &r_h);
|
||||
|
||||
static int get_image_data_size(int p_width, int p_height, Format p_format, int p_mipmaps = 0);
|
||||
static int get_format_pallete_size(Format p_format);
|
||||
static int get_image_data_size(int p_width, int p_height, Format p_format,int p_mipmaps=0);
|
||||
static int get_image_required_mipmaps(int p_width, int p_height, Format p_format);
|
||||
|
||||
|
||||
|
||||
|
||||
bool operator==(const Image& p_image) const;
|
||||
|
||||
void quantize();
|
||||
|
||||
enum CompressMode {
|
||||
COMPRESS_S3TC,
|
||||
COMPRESS_BC,
|
||||
COMPRESS_PVRTC2,
|
||||
COMPRESS_PVRTC4,
|
||||
COMPRESS_ETC,
|
||||
COMPRESS_ETC2,
|
||||
COMPRESS_ETC
|
||||
};
|
||||
|
||||
Error compress(CompressMode p_mode = COMPRESS_S3TC, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7);
|
||||
Error compress(CompressMode p_mode=COMPRESS_BC);
|
||||
Image compressed(int p_mode); /* from the Image::CompressMode enum */
|
||||
Error decompress();
|
||||
Image decompressed() const;
|
||||
bool is_compressed() const;
|
||||
|
||||
void fix_alpha_edges();
|
||||
@ -285,60 +348,21 @@ public:
|
||||
void srgb_to_linear();
|
||||
void normalmap_to_xy();
|
||||
|
||||
void blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest);
|
||||
void blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest);
|
||||
void blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest);
|
||||
void blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest);
|
||||
void fill(const Color &c);
|
||||
void blit_rect(const Image& p_src, const Rect2& p_src_rect,const Point2& p_dest);
|
||||
void brush_transfer(const Image& p_src, const Image& p_brush, const Point2& p_dest);
|
||||
Image brushed(const Image& p_src, const Image& p_brush, const Point2& p_dest) const;
|
||||
|
||||
Rect2 get_used_rect() const;
|
||||
Ref<Image> get_rect(const Rect2 &p_area) const;
|
||||
Image get_rect(const Rect2& p_area) const;
|
||||
|
||||
static void set_compress_bc_func(void (*p_compress_func)(Image *, CompressSource));
|
||||
static void set_compress_bc_func(void (*p_compress_func)(Image *));
|
||||
static String get_format_name(Format p_format);
|
||||
|
||||
Error load_png_from_buffer(const PoolVector<uint8_t> &p_array);
|
||||
Error load_jpg_from_buffer(const PoolVector<uint8_t> &p_array);
|
||||
|
||||
Image(const uint8_t *p_mem_png_jpg, int p_len = -1);
|
||||
Image(const uint8_t* p_mem_png_jpg, int p_len=-1);
|
||||
Image(const char **p_xpm);
|
||||
|
||||
virtual Ref<Resource> duplicate(bool p_subresources = false) const;
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
//this is used for compression
|
||||
enum DetectChannels {
|
||||
DETECTED_L,
|
||||
DETECTED_LA,
|
||||
DETECTED_R,
|
||||
DETECTED_RG,
|
||||
DETECTED_RGB,
|
||||
DETECTED_RGBA,
|
||||
};
|
||||
|
||||
DetectChannels get_detected_channels();
|
||||
|
||||
Color get_pixel(int p_x, int p_y) const;
|
||||
void set_pixel(int p_x, int p_y, const Color &p_color);
|
||||
|
||||
void copy_internals_from(const Ref<Image> &p_image) {
|
||||
ERR_FAIL_COND(p_image.is_null());
|
||||
format = p_image->format;
|
||||
width = p_image->width;
|
||||
height = p_image->height;
|
||||
mipmaps = p_image->mipmaps;
|
||||
data = p_image->data;
|
||||
}
|
||||
|
||||
~Image();
|
||||
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(Image::Format)
|
||||
VARIANT_ENUM_CAST(Image::Interpolation)
|
||||
VARIANT_ENUM_CAST(Image::CompressMode)
|
||||
VARIANT_ENUM_CAST(Image::CompressSource)
|
||||
VARIANT_ENUM_CAST(Image::AlphaMode)
|
||||
|
||||
#endif
|
||||
|
||||
365
core/image_quantize.cpp
Normal file
365
core/image_quantize.cpp
Normal file
@ -0,0 +1,365 @@
|
||||
/*************************************************************************/
|
||||
/* image_quantize.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
#include "image.h"
|
||||
#include <stdio.h>
|
||||
#include "print_string.h"
|
||||
#ifdef TOOLS_ENABLED
|
||||
#include "set.h"
|
||||
#include "sort.h"
|
||||
#include "os/os.h"
|
||||
|
||||
//#define QUANTIZE_SPEED_OVER_QUALITY
|
||||
|
||||
|
||||
Image::MCBlock::MCBlock() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
Image::MCBlock::MCBlock(BColorPos *p_colors,int p_color_count) {
|
||||
|
||||
colors=p_colors;
|
||||
color_count=p_color_count;
|
||||
min_color.color=BColor(255,255,255,255);
|
||||
max_color.color=BColor(0,0,0,0);
|
||||
shrink();
|
||||
}
|
||||
|
||||
int Image::MCBlock::get_longest_axis_index() const {
|
||||
|
||||
int max_dist=-1;
|
||||
int max_index=0;
|
||||
|
||||
for(int i=0;i<4;i++) {
|
||||
|
||||
int d = max_color.color.col[i]-min_color.color.col[i];
|
||||
if (d>max_dist) {
|
||||
max_index=i;
|
||||
max_dist=d;
|
||||
}
|
||||
}
|
||||
|
||||
return max_index;
|
||||
}
|
||||
int Image::MCBlock::get_longest_axis_length() const {
|
||||
|
||||
int max_dist=-1;
|
||||
|
||||
for(int i=0;i<4;i++) {
|
||||
|
||||
int d = max_color.color.col[i]-min_color.color.col[i];
|
||||
if (d>max_dist) {
|
||||
max_dist=d;
|
||||
}
|
||||
}
|
||||
|
||||
return max_dist;
|
||||
}
|
||||
|
||||
bool Image::MCBlock::operator<(const MCBlock& p_block) const {
|
||||
|
||||
int alen = get_longest_axis_length();
|
||||
int blen = p_block.get_longest_axis_length();
|
||||
if (alen==blen) {
|
||||
|
||||
return colors < p_block.colors;
|
||||
} else
|
||||
return alen < blen;
|
||||
|
||||
}
|
||||
|
||||
void Image::MCBlock::shrink() {
|
||||
|
||||
min_color=colors[0];
|
||||
max_color=colors[0];
|
||||
|
||||
for(int i=1;i<color_count;i++) {
|
||||
|
||||
for(int j=0;j<4;j++) {
|
||||
|
||||
min_color.color.col[j]=MIN(min_color.color.col[j],colors[i].color.col[j]);
|
||||
max_color.color.col[j]=MAX(max_color.color.col[j],colors[i].color.col[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Image::quantize() {
|
||||
|
||||
bool has_alpha = detect_alpha()!=ALPHA_NONE;
|
||||
|
||||
bool quantize_fast=OS::get_singleton()->has_environment("QUANTIZE_FAST");
|
||||
|
||||
convert(FORMAT_RGBA);
|
||||
|
||||
ERR_FAIL_COND( format!=FORMAT_RGBA );
|
||||
|
||||
DVector<uint8_t> indexed_data;
|
||||
|
||||
|
||||
{
|
||||
int color_count = data.size()/4;
|
||||
|
||||
ERR_FAIL_COND(color_count==0);
|
||||
|
||||
Set<MCBlock> block_queue;
|
||||
|
||||
DVector<BColorPos> data_colors;
|
||||
data_colors.resize(color_count);
|
||||
|
||||
DVector<BColorPos>::Write dcw=data_colors.write();
|
||||
|
||||
DVector<uint8_t>::Read dr = data.read();
|
||||
const BColor * drptr=(const BColor*)&dr[0];
|
||||
BColorPos *bcptr=&dcw[0];
|
||||
|
||||
|
||||
|
||||
{
|
||||
for(int i=0;i<color_count;i++) {
|
||||
|
||||
//uint32_t data_ofs=i<<2;
|
||||
bcptr[i].color=drptr[i];//BColor(drptr[data_ofs+0],drptr[data_ofs+1],drptr[data_ofs+2],drptr[data_ofs+3]);
|
||||
bcptr[i].index=i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//printf("color count: %i\n",color_count);
|
||||
/*
|
||||
for(int i=0;i<color_count;i++) {
|
||||
|
||||
BColor bc = ((BColor*)&wb[0])[i];
|
||||
printf("%i - %i,%i,%i,%i\n",i,bc.r,bc.g,bc.b,bc.a);
|
||||
}*/
|
||||
|
||||
MCBlock initial_block((BColorPos*)&dcw[0],color_count);
|
||||
|
||||
block_queue.insert(initial_block);
|
||||
|
||||
while( block_queue.size() < 256 && block_queue.back()->get().color_count > 1 ) {
|
||||
|
||||
MCBlock longest = block_queue.back()->get();
|
||||
//printf("longest: %i (%i)\n",longest.get_longest_axis_index(),longest.get_longest_axis_length());
|
||||
|
||||
block_queue.erase(block_queue.back());
|
||||
|
||||
BColorPos *first = longest.colors;
|
||||
BColorPos *median = longest.colors + (longest.color_count+1)/2;
|
||||
BColorPos *end = longest.colors + longest.color_count;
|
||||
|
||||
#if 0
|
||||
int lai =longest.get_longest_axis_index();
|
||||
switch(lai) {
|
||||
#if 0
|
||||
case 0: { SortArray<BColorPos,BColorPos::SortR> sort; sort.sort(first,end-first); } break;
|
||||
case 1: { SortArray<BColorPos,BColorPos::SortG> sort; sort.sort(first,end-first); } break;
|
||||
case 2: { SortArray<BColorPos,BColorPos::SortB> sort; sort.sort(first,end-first); } break;
|
||||
case 3: { SortArray<BColorPos,BColorPos::SortA> sort; sort.sort(first,end-first); } break;
|
||||
#else
|
||||
case 0: { SortArray<BColorPos,BColorPos::SortR> sort; sort.nth_element(0,end-first,median-first,first); } break;
|
||||
case 1: { SortArray<BColorPos,BColorPos::SortG> sort; sort.nth_element(0,end-first,median-first,first); } break;
|
||||
case 2: { SortArray<BColorPos,BColorPos::SortB> sort; sort.nth_element(0,end-first,median-first,first); } break;
|
||||
case 3: { SortArray<BColorPos,BColorPos::SortA> sort; sort.nth_element(0,end-first,median-first,first); } break;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//avoid same color from being split in 2
|
||||
//search forward and flip
|
||||
BColorPos *median_end=median;
|
||||
BColorPos *p=median_end+1;
|
||||
|
||||
while(p!=end) {
|
||||
if (median_end->color==p->color) {
|
||||
SWAP(*(median_end+1),*p);
|
||||
median_end++;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
//search backward and flip
|
||||
BColorPos *median_begin=median;
|
||||
p=median_begin-1;
|
||||
|
||||
while(p!=(first-1)) {
|
||||
if (median_begin->color==p->color) {
|
||||
SWAP(*(median_begin-1),*p);
|
||||
median_begin--;
|
||||
}
|
||||
p--;
|
||||
}
|
||||
|
||||
|
||||
if (first < median_begin) {
|
||||
median=median_begin;
|
||||
} else if (median_end < end-1) {
|
||||
median=median_end+1;
|
||||
} else {
|
||||
break; //shouldn't have arrived here, since it means all pixels are equal, but wathever
|
||||
}
|
||||
|
||||
MCBlock left(first,median-first);
|
||||
MCBlock right(median,end-median);
|
||||
|
||||
block_queue.insert(left);
|
||||
block_queue.insert(right);
|
||||
|
||||
#else
|
||||
switch(longest.get_longest_axis_index()) {
|
||||
case 0: { SortArray<BColorPos,BColorPos::SortR> sort; sort.nth_element(0,end-first,median-first,first); } break;
|
||||
case 1: { SortArray<BColorPos,BColorPos::SortG> sort; sort.nth_element(0,end-first,median-first,first); } break;
|
||||
case 2: { SortArray<BColorPos,BColorPos::SortB> sort; sort.nth_element(0,end-first,median-first,first); } break;
|
||||
case 3: { SortArray<BColorPos,BColorPos::SortA> sort; sort.nth_element(0,end-first,median-first,first); } break;
|
||||
|
||||
}
|
||||
|
||||
MCBlock left(first,median-first);
|
||||
MCBlock right(median,end-median);
|
||||
|
||||
block_queue.insert(left);
|
||||
block_queue.insert(right);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
while(block_queue.size() > 256) {
|
||||
|
||||
block_queue.erase(block_queue.front());// erase least significant
|
||||
}
|
||||
|
||||
int res_colors=0;
|
||||
|
||||
int comp_size = (has_alpha?4:3);
|
||||
indexed_data.resize(color_count + 256*comp_size);
|
||||
|
||||
DVector<uint8_t>::Write iw = indexed_data.write();
|
||||
uint8_t *iwptr=&iw[0];
|
||||
BColor pallete[256];
|
||||
|
||||
// print_line("applying quantization - res colors "+itos(block_queue.size()));
|
||||
|
||||
while(block_queue.size()) {
|
||||
|
||||
const MCBlock &b = block_queue.back()->get();
|
||||
|
||||
uint64_t sum[4]={0,0,0,0};
|
||||
|
||||
for(int i=0;i<b.color_count;i++) {
|
||||
|
||||
sum[0]+=b.colors[i].color.col[0];
|
||||
sum[1]+=b.colors[i].color.col[1];
|
||||
sum[2]+=b.colors[i].color.col[2];
|
||||
sum[3]+=b.colors[i].color.col[3];
|
||||
}
|
||||
|
||||
BColor c( sum[0]/b.color_count, sum[1]/b.color_count, sum[2]/b.color_count, sum[3]/b.color_count );
|
||||
|
||||
|
||||
|
||||
//printf(" %i: %i,%i,%i,%i out of %i\n",res_colors,c.r,c.g,c.b,c.a,b.color_count);
|
||||
|
||||
|
||||
|
||||
for(int i=0;i<comp_size;i++) {
|
||||
iwptr[ color_count + res_colors * comp_size + i ] = c.col[i];
|
||||
}
|
||||
|
||||
if (quantize_fast) {
|
||||
for(int i=0;i<b.color_count;i++) {
|
||||
iwptr[b.colors[i].index]=res_colors;
|
||||
}
|
||||
} else {
|
||||
|
||||
pallete[res_colors]=c;
|
||||
}
|
||||
|
||||
|
||||
res_colors++;
|
||||
|
||||
block_queue.erase(block_queue.back());
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (!quantize_fast) {
|
||||
|
||||
for(int i=0;i<color_count;i++) {
|
||||
|
||||
const BColor &c=drptr[i];
|
||||
uint8_t best_dist_idx=0;
|
||||
uint32_t dist=0xFFFFFFFF;
|
||||
|
||||
for(int j=0;j<res_colors;j++) {
|
||||
|
||||
const BColor &pc=pallete[j];
|
||||
uint32_t d = 0;
|
||||
{ int16_t v = (int16_t)c.r-(int16_t)pc.r; d+=v*v; }
|
||||
{ int16_t v = (int16_t)c.g-(int16_t)pc.g; d+=v*v; }
|
||||
{ int16_t v = (int16_t)c.b-(int16_t)pc.b; d+=v*v; }
|
||||
{ int16_t v = (int16_t)c.a-(int16_t)pc.a; d+=v*v; }
|
||||
|
||||
if (d<=dist) {
|
||||
best_dist_idx=j;
|
||||
dist=d;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
iwptr[ i ] = best_dist_idx;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//iw = DVector<uint8_t>::Write();
|
||||
//dr = DVector<uint8_t>::Read();
|
||||
//wb = DVector<uint8_t>::Write();
|
||||
}
|
||||
|
||||
print_line(itos(indexed_data.size()));
|
||||
data=indexed_data;
|
||||
format=has_alpha?FORMAT_INDEXED_ALPHA:FORMAT_INDEXED;
|
||||
|
||||
|
||||
} //do none
|
||||
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
void Image::quantize() {} //do none
|
||||
|
||||
|
||||
#endif
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,52 +26,65 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "input_map.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "os/keyboard.h"
|
||||
#include "project_settings.h"
|
||||
|
||||
InputMap *InputMap::singleton = NULL;
|
||||
InputMap *InputMap::singleton=NULL;
|
||||
|
||||
void InputMap::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("has_action", "action"), &InputMap::has_action);
|
||||
ClassDB::bind_method(D_METHOD("get_actions"), &InputMap::_get_actions);
|
||||
ClassDB::bind_method(D_METHOD("add_action", "action"), &InputMap::add_action);
|
||||
ClassDB::bind_method(D_METHOD("erase_action", "action"), &InputMap::erase_action);
|
||||
ObjectTypeDB::bind_method(_MD("has_action","action"),&InputMap::has_action);
|
||||
ObjectTypeDB::bind_method(_MD("get_action_id","action"),&InputMap::get_action_id);
|
||||
ObjectTypeDB::bind_method(_MD("get_action_from_id","id"),&InputMap::get_action_from_id);
|
||||
ObjectTypeDB::bind_method(_MD("get_actions"),&InputMap::_get_actions);
|
||||
ObjectTypeDB::bind_method(_MD("add_action","action"),&InputMap::add_action);
|
||||
ObjectTypeDB::bind_method(_MD("erase_action","action"),&InputMap::erase_action);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("action_add_event","action","event"),&InputMap::action_add_event);
|
||||
ObjectTypeDB::bind_method(_MD("action_has_event","action","event"),&InputMap::action_has_event);
|
||||
ObjectTypeDB::bind_method(_MD("action_erase_event","action","event"),&InputMap::action_erase_event);
|
||||
ObjectTypeDB::bind_method(_MD("get_action_list","action"),&InputMap::_get_action_list);
|
||||
ObjectTypeDB::bind_method(_MD("event_is_action","event","action"),&InputMap::event_is_action);
|
||||
ObjectTypeDB::bind_method(_MD("load_from_globals"),&InputMap::load_from_globals);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("action_add_event", "action", "event"), &InputMap::action_add_event);
|
||||
ClassDB::bind_method(D_METHOD("action_has_event", "action", "event"), &InputMap::action_has_event);
|
||||
ClassDB::bind_method(D_METHOD("action_erase_event", "action", "event"), &InputMap::action_erase_event);
|
||||
ClassDB::bind_method(D_METHOD("get_action_list", "action"), &InputMap::_get_action_list);
|
||||
ClassDB::bind_method(D_METHOD("event_is_action", "event", "action"), &InputMap::event_is_action);
|
||||
ClassDB::bind_method(D_METHOD("load_from_globals"), &InputMap::load_from_globals);
|
||||
}
|
||||
|
||||
void InputMap::add_action(const StringName &p_action) {
|
||||
|
||||
ERR_FAIL_COND(input_map.has(p_action));
|
||||
input_map[p_action] = Action();
|
||||
static int last_id = 1;
|
||||
input_map[p_action].id = last_id;
|
||||
void InputMap::add_action(const StringName& p_action) {
|
||||
|
||||
ERR_FAIL_COND( input_map.has(p_action) );
|
||||
input_map[p_action]=Action();
|
||||
static int last_id=1;
|
||||
input_map[p_action].id=last_id;
|
||||
input_id_map[last_id]=p_action;
|
||||
last_id++;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void InputMap::erase_action(const StringName &p_action) {
|
||||
void InputMap::erase_action(const StringName& p_action) {
|
||||
|
||||
ERR_FAIL_COND(!input_map.has(p_action));
|
||||
ERR_FAIL_COND( !input_map.has(p_action) );
|
||||
input_id_map.erase(input_map[p_action].id);
|
||||
input_map.erase(p_action);
|
||||
|
||||
}
|
||||
|
||||
StringName InputMap::get_action_from_id(int p_id) const {
|
||||
|
||||
ERR_FAIL_COND_V(!input_id_map.has(p_id),StringName());
|
||||
return input_id_map[p_id];
|
||||
}
|
||||
|
||||
Array InputMap::_get_actions() {
|
||||
|
||||
Array ret;
|
||||
List<StringName> actions = get_actions();
|
||||
if (actions.empty())
|
||||
if(actions.empty())
|
||||
return ret;
|
||||
|
||||
for (const List<StringName>::Element *E = actions.front(); E; E = E->next()) {
|
||||
for(const List<StringName>::Element *E=actions.front();E;E=E->next()) {
|
||||
|
||||
ret.push_back(E->get());
|
||||
}
|
||||
@ -83,210 +95,238 @@ Array InputMap::_get_actions() {
|
||||
List<StringName> InputMap::get_actions() const {
|
||||
|
||||
List<StringName> actions = List<StringName>();
|
||||
if (input_map.empty()) {
|
||||
if(input_map.empty()){
|
||||
return actions;
|
||||
}
|
||||
|
||||
for (Map<StringName, Action>::Element *E = input_map.front(); E; E = E->next()) {
|
||||
for (Map<StringName, Action>::Element *E=input_map.front();E;E=E->next()) {
|
||||
actions.push_back(E->key());
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
List<Ref<InputEvent> >::Element *InputMap::_find_event(List<Ref<InputEvent> > &p_list, const Ref<InputEvent> &p_event, bool p_action_test) const {
|
||||
List<InputEvent>::Element *InputMap::_find_event(List<InputEvent> &p_list,const InputEvent& p_event) const {
|
||||
|
||||
for (List<Ref<InputEvent> >::Element *E = p_list.front(); E; E = E->next()) {
|
||||
for (List<InputEvent>::Element *E=p_list.front();E;E=E->next()) {
|
||||
|
||||
const Ref<InputEvent> e = E->get();
|
||||
|
||||
//if (e.type != Ref<InputEvent>::KEY && e.device != p_event.device) -- unsure about the KEY comparison, why is this here?
|
||||
// continue;
|
||||
|
||||
if (e->get_device() != p_event->get_device())
|
||||
const InputEvent& e=E->get();
|
||||
if(e.type!=p_event.type)
|
||||
continue;
|
||||
if (e->action_match(p_event))
|
||||
if (e.type!=InputEvent::KEY && e.device!=p_event.device)
|
||||
continue;
|
||||
|
||||
bool same=false;
|
||||
|
||||
switch(p_event.type) {
|
||||
|
||||
case InputEvent::KEY: {
|
||||
|
||||
same=(e.key.scancode==p_event.key.scancode && e.key.mod == p_event.key.mod);
|
||||
|
||||
} break;
|
||||
case InputEvent::JOYSTICK_BUTTON: {
|
||||
|
||||
same=(e.joy_button.button_index==p_event.joy_button.button_index);
|
||||
|
||||
} break;
|
||||
case InputEvent::MOUSE_BUTTON: {
|
||||
|
||||
same=(e.mouse_button.button_index==p_event.mouse_button.button_index);
|
||||
|
||||
} break;
|
||||
case InputEvent::JOYSTICK_MOTION: {
|
||||
|
||||
same=(e.joy_motion.axis==p_event.joy_motion.axis && (e.joy_motion.axis_value < 0) == (p_event.joy_motion.axis_value < 0));
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
if (same)
|
||||
return E;
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool InputMap::has_action(const StringName &p_action) const {
|
||||
|
||||
bool InputMap::has_action(const StringName& p_action) const {
|
||||
|
||||
return input_map.has(p_action);
|
||||
}
|
||||
|
||||
void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
|
||||
void InputMap::action_add_event(const StringName& p_action,const InputEvent& p_event) {
|
||||
|
||||
ERR_FAIL_COND(p_event.is_null());
|
||||
ERR_FAIL_COND(!input_map.has(p_action));
|
||||
if (_find_event(input_map[p_action].inputs, p_event))
|
||||
ERR_FAIL_COND(p_event.type==InputEvent::ACTION);
|
||||
ERR_FAIL_COND( !input_map.has(p_action) );
|
||||
if (_find_event(input_map[p_action].inputs,p_event))
|
||||
return; //already gots
|
||||
|
||||
input_map[p_action].inputs.push_back(p_event);
|
||||
|
||||
}
|
||||
|
||||
bool InputMap::action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
|
||||
|
||||
ERR_FAIL_COND_V(!input_map.has(p_action), false);
|
||||
return (_find_event(input_map[p_action].inputs, p_event) != NULL);
|
||||
int InputMap::get_action_id(const StringName& p_action) const {
|
||||
|
||||
ERR_FAIL_COND_V(!input_map.has(p_action),-1);
|
||||
return input_map[p_action].id;
|
||||
}
|
||||
|
||||
void InputMap::action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
|
||||
bool InputMap::action_has_event(const StringName& p_action,const InputEvent& p_event) {
|
||||
|
||||
ERR_FAIL_COND(!input_map.has(p_action));
|
||||
ERR_FAIL_COND_V( !input_map.has(p_action), false );
|
||||
return (_find_event(input_map[p_action].inputs,p_event)!=NULL);
|
||||
|
||||
List<Ref<InputEvent> >::Element *E = _find_event(input_map[p_action].inputs, p_event);
|
||||
}
|
||||
|
||||
void InputMap::action_erase_event(const StringName& p_action,const InputEvent& p_event) {
|
||||
|
||||
ERR_FAIL_COND( !input_map.has(p_action) );
|
||||
|
||||
List<InputEvent>::Element *E=_find_event(input_map[p_action].inputs,p_event);
|
||||
if (E)
|
||||
input_map[p_action].inputs.erase(E);
|
||||
}
|
||||
|
||||
Array InputMap::_get_action_list(const StringName &p_action) {
|
||||
|
||||
Array InputMap::_get_action_list(const StringName& p_action) {
|
||||
|
||||
Array ret;
|
||||
const List<Ref<InputEvent> > *al = get_action_list(p_action);
|
||||
const List<InputEvent> *al = get_action_list(p_action);
|
||||
if (al) {
|
||||
for (const List<Ref<InputEvent> >::Element *E = al->front(); E; E = E->next()) {
|
||||
for(const List<InputEvent>::Element *E=al->front();E;E=E->next()) {
|
||||
|
||||
ret.push_back(E->get());
|
||||
ret.push_back(E->get());;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
const List<Ref<InputEvent> > *InputMap::get_action_list(const StringName &p_action) {
|
||||
const List<InputEvent> *InputMap::get_action_list(const StringName& p_action) {
|
||||
|
||||
const Map<StringName, Action>::Element *E = input_map.find(p_action);
|
||||
const Map<StringName, Action>::Element *E=input_map.find(p_action);
|
||||
if (!E)
|
||||
return NULL;
|
||||
|
||||
return &E->get().inputs;
|
||||
}
|
||||
|
||||
bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action) const {
|
||||
bool InputMap::event_is_action(const InputEvent& p_event, const StringName& p_action) const {
|
||||
|
||||
Map<StringName, Action>::Element *E = input_map.find(p_action);
|
||||
if (!E) {
|
||||
ERR_EXPLAIN("Request for nonexistent InputMap action: " + String(p_action));
|
||||
ERR_FAIL_COND_V(!E, false);
|
||||
|
||||
Map<StringName,Action >::Element *E=input_map.find(p_action);
|
||||
if(!E) {
|
||||
ERR_EXPLAIN("Request for nonexistent InputMap action: "+String(p_action));
|
||||
ERR_FAIL_COND_V(!E,false);
|
||||
}
|
||||
|
||||
Ref<InputEventAction> iea = p_event;
|
||||
if (iea.is_valid()) {
|
||||
return iea->get_action() == p_action;
|
||||
if (p_event.type==InputEvent::ACTION) {
|
||||
|
||||
return p_event.action.action==E->get().id;
|
||||
}
|
||||
|
||||
return _find_event(E->get().inputs, p_event, true) != NULL;
|
||||
}
|
||||
|
||||
const Map<StringName, InputMap::Action> &InputMap::get_action_map() const {
|
||||
return input_map;
|
||||
return _find_event(E->get().inputs,p_event)!=NULL;
|
||||
}
|
||||
|
||||
void InputMap::load_from_globals() {
|
||||
|
||||
input_map.clear();
|
||||
input_map.clear();;
|
||||
|
||||
List<PropertyInfo> pinfo;
|
||||
ProjectSettings::get_singleton()->get_property_list(&pinfo);
|
||||
Globals::get_singleton()->get_property_list(&pinfo);
|
||||
|
||||
for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
|
||||
const PropertyInfo &pi = E->get();
|
||||
for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
|
||||
const PropertyInfo &pi=E->get();
|
||||
|
||||
if (!pi.name.begins_with("input/"))
|
||||
continue;
|
||||
|
||||
String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length());
|
||||
String name = pi.name.substr(pi.name.find("/")+1,pi.name.length());
|
||||
|
||||
add_action(name);
|
||||
|
||||
Array va = ProjectSettings::get_singleton()->get(pi.name);
|
||||
Array va = Globals::get_singleton()->get(pi.name);;
|
||||
|
||||
for (int i = 0; i < va.size(); i++) {
|
||||
for(int i=0;i<va.size();i++) {
|
||||
|
||||
Ref<InputEvent> ie = va[i];
|
||||
if (ie.is_null())
|
||||
InputEvent ie=va[i];
|
||||
if (ie.type==InputEvent::NONE)
|
||||
continue;
|
||||
action_add_event(name, ie);
|
||||
action_add_event(name,ie);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void InputMap::load_default() {
|
||||
|
||||
Ref<InputEventKey> key;
|
||||
InputEvent key;
|
||||
key.type=InputEvent::KEY;
|
||||
|
||||
add_action("ui_accept");
|
||||
key.instance();
|
||||
key->set_scancode(KEY_ENTER);
|
||||
action_add_event("ui_accept", key);
|
||||
|
||||
key.instance();
|
||||
key->set_scancode(KEY_KP_ENTER);
|
||||
action_add_event("ui_accept", key);
|
||||
|
||||
key.instance();
|
||||
key->set_scancode(KEY_SPACE);
|
||||
action_add_event("ui_accept", key);
|
||||
key.key.scancode=KEY_RETURN;
|
||||
action_add_event("ui_accept",key);
|
||||
key.key.scancode=KEY_ENTER;
|
||||
action_add_event("ui_accept",key);
|
||||
key.key.scancode=KEY_SPACE;
|
||||
action_add_event("ui_accept",key);
|
||||
|
||||
add_action("ui_select");
|
||||
key.instance();
|
||||
key->set_scancode(KEY_SPACE);
|
||||
action_add_event("ui_select", key);
|
||||
key.key.scancode=KEY_SPACE;
|
||||
action_add_event("ui_select",key);
|
||||
|
||||
add_action("ui_cancel");
|
||||
key.instance();
|
||||
key->set_scancode(KEY_ESCAPE);
|
||||
action_add_event("ui_cancel", key);
|
||||
key.key.scancode=KEY_ESCAPE;
|
||||
action_add_event("ui_cancel",key);
|
||||
|
||||
add_action("ui_focus_next");
|
||||
key.instance();
|
||||
key->set_scancode(KEY_TAB);
|
||||
action_add_event("ui_focus_next", key);
|
||||
key.key.scancode=KEY_TAB;
|
||||
action_add_event("ui_focus_next",key);
|
||||
|
||||
add_action("ui_focus_prev");
|
||||
key.instance();
|
||||
key->set_scancode(KEY_TAB);
|
||||
key->set_shift(true);
|
||||
action_add_event("ui_focus_prev", key);
|
||||
key.key.scancode=KEY_TAB;
|
||||
key.key.mod.shift=true;
|
||||
action_add_event("ui_focus_prev",key);
|
||||
key.key.mod.shift=false;
|
||||
|
||||
add_action("ui_left");
|
||||
key.instance();
|
||||
key->set_scancode(KEY_LEFT);
|
||||
action_add_event("ui_left", key);
|
||||
key.key.scancode=KEY_LEFT;
|
||||
action_add_event("ui_left",key);
|
||||
|
||||
add_action("ui_right");
|
||||
key.instance();
|
||||
key->set_scancode(KEY_RIGHT);
|
||||
action_add_event("ui_right", key);
|
||||
key.key.scancode=KEY_RIGHT;
|
||||
action_add_event("ui_right",key);
|
||||
|
||||
add_action("ui_up");
|
||||
key.instance();
|
||||
key->set_scancode(KEY_UP);
|
||||
action_add_event("ui_up", key);
|
||||
key.key.scancode=KEY_UP;
|
||||
action_add_event("ui_up",key);
|
||||
|
||||
add_action("ui_down");
|
||||
key.instance();
|
||||
key->set_scancode(KEY_DOWN);
|
||||
action_add_event("ui_down", key);
|
||||
key.key.scancode=KEY_DOWN;
|
||||
action_add_event("ui_down",key);
|
||||
|
||||
|
||||
add_action("ui_page_up");
|
||||
key.instance();
|
||||
key->set_scancode(KEY_PAGEUP);
|
||||
action_add_event("ui_page_up", key);
|
||||
key.key.scancode=KEY_PAGEUP;
|
||||
action_add_event("ui_page_up",key);
|
||||
|
||||
add_action("ui_page_down");
|
||||
key.instance();
|
||||
key->set_scancode(KEY_PAGEDOWN);
|
||||
action_add_event("ui_page_down", key);
|
||||
key.key.scancode=KEY_PAGEDOWN;
|
||||
action_add_event("ui_page_down",key);
|
||||
|
||||
// set("display/orientation", "landscape");
|
||||
|
||||
|
||||
//set("display/window/handheld/orientation", "landscape");
|
||||
}
|
||||
|
||||
InputMap::InputMap() {
|
||||
|
||||
ERR_FAIL_COND(singleton);
|
||||
singleton = this;
|
||||
singleton=this;
|
||||
}
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,52 +26,52 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef INPUT_MAP_H
|
||||
#define INPUT_MAP_H
|
||||
|
||||
|
||||
#include "object.h"
|
||||
#include "os/input_event.h"
|
||||
|
||||
class InputMap : public Object {
|
||||
|
||||
GDCLASS(InputMap, Object);
|
||||
|
||||
public:
|
||||
struct Action {
|
||||
int id;
|
||||
List<Ref<InputEvent> > inputs;
|
||||
};
|
||||
|
||||
private:
|
||||
OBJ_TYPE( InputMap, Object );
|
||||
static InputMap *singleton;
|
||||
|
||||
struct Action {
|
||||
int id;
|
||||
List<InputEvent> inputs;
|
||||
};
|
||||
mutable Map<StringName, Action> input_map;
|
||||
mutable Map<int,StringName> input_id_map;
|
||||
|
||||
List<Ref<InputEvent> >::Element *_find_event(List<Ref<InputEvent> > &p_list, const Ref<InputEvent> &p_event, bool p_action_test = false) const;
|
||||
List<InputEvent>::Element *_find_event(List<InputEvent> &p_list,const InputEvent& p_event) const;
|
||||
|
||||
Array _get_action_list(const StringName &p_action);
|
||||
Array _get_action_list(const StringName& p_action);
|
||||
Array _get_actions();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
static _FORCE_INLINE_ InputMap *get_singleton() { return singleton; }
|
||||
|
||||
bool has_action(const StringName &p_action) const;
|
||||
|
||||
bool has_action(const StringName& p_action) const;
|
||||
int get_action_id(const StringName& p_action) const;
|
||||
StringName get_action_from_id(int p_id) const;
|
||||
List<StringName> get_actions() const;
|
||||
void add_action(const StringName &p_action);
|
||||
void erase_action(const StringName &p_action);
|
||||
void add_action(const StringName& p_action);
|
||||
void erase_action(const StringName& p_action);
|
||||
|
||||
void action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event);
|
||||
bool action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event);
|
||||
void action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event);
|
||||
void action_add_event(const StringName& p_action,const InputEvent& p_event);
|
||||
bool action_has_event(const StringName& p_action,const InputEvent& p_event);
|
||||
void action_erase_event(const StringName& p_action,const InputEvent& p_event);
|
||||
|
||||
const List<InputEvent> *get_action_list(const StringName& p_action);
|
||||
bool event_is_action(const InputEvent& p_event, const StringName& p_action) const;
|
||||
|
||||
const List<Ref<InputEvent> > *get_action_list(const StringName &p_action);
|
||||
bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action) const;
|
||||
|
||||
const Map<StringName, Action> &get_action_map() const;
|
||||
void load_from_globals();
|
||||
void load_default();
|
||||
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -30,25 +29,25 @@
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
typedef signed __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
typedef signed __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
#else
|
||||
|
||||
#ifdef NO_STDINT_H
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef signed short int16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef signed int int32_t;
|
||||
typedef long long int64_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef signed short int16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef signed int int32_t;
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
|
||||
60
core/io/LICENSE-InfoZip.txt
Normal file
60
core/io/LICENSE-InfoZip.txt
Normal file
@ -0,0 +1,60 @@
|
||||
This is version 2007-Mar-4 of the Info-ZIP license.
|
||||
The definitive version of this document should be available at
|
||||
ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely and
|
||||
a copy at http://www.info-zip.org/pub/infozip/license.html.
|
||||
|
||||
|
||||
Copyright (c) 1990-2007 Info-ZIP. All rights reserved.
|
||||
|
||||
For the purposes of this copyright and license, "Info-ZIP" is defined as
|
||||
the following set of individuals:
|
||||
|
||||
Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,
|
||||
Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth,
|
||||
Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz,
|
||||
David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko,
|
||||
Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,
|
||||
Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda,
|
||||
Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren,
|
||||
Rich Wales, Mike White.
|
||||
|
||||
This software is provided "as is," without warranty of any kind, express
|
||||
or implied. In no event shall Info-ZIP or its contributors be held liable
|
||||
for any direct, indirect, incidental, special or consequential damages
|
||||
arising out of the use of or inability to use this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the above disclaimer and the following restrictions:
|
||||
|
||||
1. Redistributions of source code (in whole or in part) must retain
|
||||
the above copyright notice, definition, disclaimer, and this list
|
||||
of conditions.
|
||||
|
||||
2. Redistributions in binary form (compiled executables and libraries)
|
||||
must reproduce the above copyright notice, definition, disclaimer,
|
||||
and this list of conditions in documentation and/or other materials
|
||||
provided with the distribution. The sole exception to this condition
|
||||
is redistribution of a standard UnZipSFX binary (including SFXWiz) as
|
||||
part of a self-extracting archive; that is permitted without inclusion
|
||||
of this license, as long as the normal SFX banner has not been removed
|
||||
from the binary or disabled.
|
||||
|
||||
3. Altered versions--including, but not limited to, ports to new operating
|
||||
systems, existing ports with new graphical interfaces, versions with
|
||||
modified or added functionality, and dynamic, shared, or static library
|
||||
versions not from Info-ZIP--must be plainly marked as such and must not
|
||||
be misrepresented as being the original source or, if binaries,
|
||||
compiled from the original source. Such altered versions also must not
|
||||
be misrepresented as being Info-ZIP releases--including, but not
|
||||
limited to, labeling of the altered versions with the names "Info-ZIP"
|
||||
(or any variation thereof, including, but not limited to, different
|
||||
capitalizations), "Pocket UnZip," "WiZ" or "MacZip" without the
|
||||
explicit permission of Info-ZIP. Such altered versions are further
|
||||
prohibited from misrepresentative use of the Zip-Bugs or Info-ZIP
|
||||
e-mail addresses or the Info-ZIP URL(s), such as to imply Info-ZIP
|
||||
will provide support for the altered versions.
|
||||
|
||||
4. Info-ZIP retains the right to use the names "Info-ZIP," "Zip," "UnZip,"
|
||||
"UnZipSFX," "WiZ," "Pocket UnZip," "Pocket Zip," and "MacZip" for its
|
||||
own source and binary releases.
|
||||
32
core/io/LICENSE-MiniZip.txt
Normal file
32
core/io/LICENSE-MiniZip.txt
Normal file
@ -0,0 +1,32 @@
|
||||
Credits
|
||||
|
||||
Gilles Vollant - Original MiniZip author
|
||||
Even Rouault - ZIP64 unzip Support
|
||||
Daniel Borca - BZip Compression method support in unzip
|
||||
Mathias Svensson - ZIP64 zip support
|
||||
Mathias Svensson - BZip Compression method support in zip
|
||||
|
||||
This version has been modified for Godot Engine
|
||||
|
||||
|
||||
License
|
||||
----------------------------------------------------------------------------
|
||||
Condition of use and distribution are the same than zlib :
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
@ -3,6 +3,7 @@
|
||||
Import('env')
|
||||
|
||||
env.add_source_files(env.core_sources, "*.cpp")
|
||||
env.add_source_files(env.core_sources, "*.c")
|
||||
# env.core_sources.append("io/fastlz.c")
|
||||
|
||||
Export('env')
|
||||
|
||||
|
||||
@ -44,7 +44,8 @@ static uint8_t rj_sbox_inv(uint8_t);
|
||||
|
||||
#ifdef BACK_TO_TABLES
|
||||
|
||||
static const uint8_t sbox[256] = {
|
||||
static const uint8_t sbox[256] =
|
||||
{
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
|
||||
0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
|
||||
@ -78,7 +79,8 @@ static const uint8_t sbox[256] = {
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
|
||||
0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
|
||||
};
|
||||
static const uint8_t sboxinv[256] = {
|
||||
static const uint8_t sboxinv[256] =
|
||||
{
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
|
||||
0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
|
||||
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
|
||||
@ -1,11 +1,3 @@
|
||||
/*
|
||||
* File: base64.c
|
||||
* Description: Simple BASE64 conversion methods
|
||||
* Author: Ari Edelkind
|
||||
* License: Public Domain
|
||||
* Website: http://episec.com/people/edelkind/c.html
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
char b64string[] =
|
||||
11
core/io/base64.h
Normal file
11
core/io/base64.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef BASE64_H
|
||||
#define BASE64_H
|
||||
|
||||
extern "C" {
|
||||
|
||||
uint32_t base64_encode (char* to, char* from, uint32_t len);
|
||||
uint32_t base64_decode (char* to, char* from, uint32_t len);
|
||||
|
||||
};
|
||||
|
||||
#endif /* BASE64_H */
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,165 +26,123 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "compression.h"
|
||||
#include "zlib.h"
|
||||
#include "os/copymem.h"
|
||||
#include "project_settings.h"
|
||||
#include "compression.h"
|
||||
|
||||
#include "fastlz.h"
|
||||
#include "zip_io.h"
|
||||
|
||||
#include "thirdparty/misc/fastlz.h"
|
||||
int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,Mode p_mode) {
|
||||
|
||||
#include <zlib.h>
|
||||
#include <zstd.h>
|
||||
|
||||
int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size, Mode p_mode) {
|
||||
|
||||
switch (p_mode) {
|
||||
switch(p_mode) {
|
||||
case MODE_FASTLZ: {
|
||||
|
||||
if (p_src_size < 16) {
|
||||
if (p_src_size<16) {
|
||||
uint8_t src[16];
|
||||
zeromem(&src[p_src_size], 16 - p_src_size);
|
||||
copymem(src, p_src, p_src_size);
|
||||
return fastlz_compress(src, 16, p_dst);
|
||||
zeromem(&src[p_src_size],16-p_src_size);
|
||||
copymem(src,p_src,p_src_size);
|
||||
return fastlz_compress(src,16,p_dst);
|
||||
} else {
|
||||
return fastlz_compress(p_src, p_src_size, p_dst);
|
||||
return fastlz_compress(p_src,p_src_size,p_dst);
|
||||
}
|
||||
|
||||
} break;
|
||||
case MODE_DEFLATE:
|
||||
case MODE_GZIP: {
|
||||
|
||||
int window_bits = p_mode == MODE_DEFLATE ? 15 : 15 + 16;
|
||||
case MODE_DEFLATE: {
|
||||
|
||||
z_stream strm;
|
||||
strm.zalloc = zipio_alloc;
|
||||
strm.zfree = zipio_free;
|
||||
strm.opaque = Z_NULL;
|
||||
int level = p_mode == MODE_DEFLATE ? zlib_level : gzip_level;
|
||||
int err = deflateInit2(&strm, level, Z_DEFLATED, window_bits, 8, Z_DEFAULT_STRATEGY);
|
||||
if (err != Z_OK)
|
||||
return -1;
|
||||
int err = deflateInit(&strm,Z_DEFAULT_COMPRESSION);
|
||||
if (err!=Z_OK)
|
||||
return -1;
|
||||
|
||||
strm.avail_in = p_src_size;
|
||||
int aout = deflateBound(&strm, p_src_size);
|
||||
strm.avail_out = aout;
|
||||
strm.next_in = (Bytef *)p_src;
|
||||
strm.next_out = p_dst;
|
||||
deflate(&strm, Z_FINISH);
|
||||
strm.avail_in=p_src_size;
|
||||
int aout = deflateBound(&strm,p_src_size);;
|
||||
strm.avail_out=aout;
|
||||
strm.next_in=(Bytef*)p_src;
|
||||
strm.next_out=p_dst;
|
||||
deflate(&strm,Z_FINISH);
|
||||
aout = aout - strm.avail_out;
|
||||
deflateEnd(&strm);
|
||||
return aout;
|
||||
|
||||
} break;
|
||||
case MODE_ZSTD: {
|
||||
ZSTD_CCtx *cctx = ZSTD_createCCtx();
|
||||
ZSTD_CCtx_setParameter(cctx, ZSTD_p_compressionLevel, zstd_level);
|
||||
if (zstd_long_distance_matching) {
|
||||
ZSTD_CCtx_setParameter(cctx, ZSTD_p_enableLongDistanceMatching, 1);
|
||||
ZSTD_CCtx_setParameter(cctx, ZSTD_p_windowLog, zstd_window_log_size);
|
||||
}
|
||||
int max_dst_size = get_max_compressed_buffer_size(p_src_size, MODE_ZSTD);
|
||||
int ret = ZSTD_compressCCtx(cctx, p_dst, max_dst_size, p_src, p_src_size, zstd_level);
|
||||
ZSTD_freeCCtx(cctx);
|
||||
return ret;
|
||||
} break;
|
||||
}
|
||||
|
||||
ERR_FAIL_V(-1);
|
||||
}
|
||||
|
||||
int Compression::get_max_compressed_buffer_size(int p_src_size, Mode p_mode) {
|
||||
int Compression::get_max_compressed_buffer_size(int p_src_size,Mode p_mode){
|
||||
|
||||
switch (p_mode) {
|
||||
switch(p_mode) {
|
||||
case MODE_FASTLZ: {
|
||||
|
||||
int ss = p_src_size + p_src_size * 6 / 100;
|
||||
if (ss < 66)
|
||||
ss = 66;
|
||||
|
||||
int ss = p_src_size+p_src_size*6/100;
|
||||
if (ss<66)
|
||||
ss=66;
|
||||
return ss;
|
||||
|
||||
} break;
|
||||
case MODE_DEFLATE:
|
||||
case MODE_GZIP: {
|
||||
|
||||
int window_bits = p_mode == MODE_DEFLATE ? 15 : 15 + 16;
|
||||
case MODE_DEFLATE: {
|
||||
|
||||
z_stream strm;
|
||||
strm.zalloc = zipio_alloc;
|
||||
strm.zfree = zipio_free;
|
||||
strm.opaque = Z_NULL;
|
||||
int err = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, window_bits, 8, Z_DEFAULT_STRATEGY);
|
||||
if (err != Z_OK)
|
||||
return -1;
|
||||
int aout = deflateBound(&strm, p_src_size);
|
||||
int err = deflateInit(&strm,Z_DEFAULT_COMPRESSION);
|
||||
if (err!=Z_OK)
|
||||
return -1;
|
||||
int aout = deflateBound(&strm,p_src_size);
|
||||
deflateEnd(&strm);
|
||||
return aout;
|
||||
} break;
|
||||
case MODE_ZSTD: {
|
||||
|
||||
return ZSTD_compressBound(p_src_size);
|
||||
} break;
|
||||
}
|
||||
|
||||
ERR_FAIL_V(-1);
|
||||
|
||||
}
|
||||
|
||||
int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size, Mode p_mode) {
|
||||
|
||||
switch (p_mode) {
|
||||
|
||||
void Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size,Mode p_mode){
|
||||
|
||||
switch(p_mode) {
|
||||
case MODE_FASTLZ: {
|
||||
|
||||
int ret_size = 0;
|
||||
|
||||
if (p_dst_max_size < 16) {
|
||||
if (p_dst_max_size<16) {
|
||||
uint8_t dst[16];
|
||||
ret_size = fastlz_decompress(p_src, p_src_size, dst, 16);
|
||||
copymem(p_dst, dst, p_dst_max_size);
|
||||
fastlz_decompress(p_src,p_src_size,dst,16);
|
||||
copymem(p_dst,dst,p_dst_max_size);
|
||||
} else {
|
||||
ret_size = fastlz_decompress(p_src, p_src_size, p_dst, p_dst_max_size);
|
||||
fastlz_decompress(p_src,p_src_size,p_dst,p_dst_max_size);
|
||||
}
|
||||
return ret_size;
|
||||
return;
|
||||
} break;
|
||||
case MODE_DEFLATE:
|
||||
case MODE_GZIP: {
|
||||
|
||||
int window_bits = p_mode == MODE_DEFLATE ? 15 : 15 + 16;
|
||||
case MODE_DEFLATE: {
|
||||
|
||||
z_stream strm;
|
||||
strm.zalloc = zipio_alloc;
|
||||
strm.zfree = zipio_free;
|
||||
strm.opaque = Z_NULL;
|
||||
strm.avail_in = 0;
|
||||
strm.next_in = Z_NULL;
|
||||
int err = inflateInit2(&strm, window_bits);
|
||||
ERR_FAIL_COND_V(err != Z_OK, -1);
|
||||
strm.avail_in= 0;
|
||||
strm.next_in=Z_NULL;
|
||||
int err = inflateInit(&strm);
|
||||
ERR_FAIL_COND(err!=Z_OK);
|
||||
|
||||
strm.avail_in = p_src_size;
|
||||
strm.avail_out = p_dst_max_size;
|
||||
strm.next_in = (Bytef *)p_src;
|
||||
strm.next_out = p_dst;
|
||||
strm.avail_in=p_src_size;
|
||||
strm.avail_out=p_dst_max_size;
|
||||
strm.next_in=(Bytef*)p_src;
|
||||
strm.next_out=p_dst;
|
||||
|
||||
err = inflate(&strm, Z_FINISH);
|
||||
int total = strm.total_out;
|
||||
err = inflate(&strm,Z_FINISH);
|
||||
inflateEnd(&strm);
|
||||
ERR_FAIL_COND_V(err != Z_STREAM_END, -1);
|
||||
return total;
|
||||
} break;
|
||||
case MODE_ZSTD: {
|
||||
ZSTD_DCtx *dctx = ZSTD_createDCtx();
|
||||
if (zstd_long_distance_matching) ZSTD_DCtx_setMaxWindowSize(dctx, 1 << zstd_window_log_size);
|
||||
int ret = ZSTD_decompressDCtx(dctx, p_dst, p_dst_max_size, p_src, p_src_size);
|
||||
ZSTD_freeDCtx(dctx);
|
||||
return ret;
|
||||
ERR_FAIL_COND(err!=Z_STREAM_END);
|
||||
return;
|
||||
} break;
|
||||
}
|
||||
|
||||
ERR_FAIL_V(-1);
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
int Compression::zlib_level = Z_DEFAULT_COMPRESSION;
|
||||
int Compression::gzip_level = Z_DEFAULT_COMPRESSION;
|
||||
int Compression::zstd_level = 3;
|
||||
bool Compression::zstd_long_distance_matching = false;
|
||||
int Compression::zstd_window_log_size = 27;
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,33 +26,28 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef COMPRESSION_H
|
||||
#define COMPRESSION_H
|
||||
|
||||
#include "typedefs.h"
|
||||
|
||||
class Compression {
|
||||
|
||||
class Compression
|
||||
{
|
||||
public:
|
||||
static int zlib_level;
|
||||
static int gzip_level;
|
||||
static int zstd_level;
|
||||
static bool zstd_long_distance_matching;
|
||||
static int zstd_window_log_size;
|
||||
|
||||
enum Mode {
|
||||
MODE_FASTLZ,
|
||||
MODE_DEFLATE,
|
||||
MODE_ZSTD,
|
||||
MODE_GZIP
|
||||
MODE_DEFLATE
|
||||
};
|
||||
|
||||
static int compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size, Mode p_mode = MODE_ZSTD);
|
||||
static int get_max_compressed_buffer_size(int p_src_size, Mode p_mode = MODE_ZSTD);
|
||||
static int decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size, Mode p_mode = MODE_ZSTD);
|
||||
|
||||
static int compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,Mode p_mode=MODE_FASTLZ);
|
||||
static int get_max_compressed_buffer_size(int p_src_size,Mode p_mode=MODE_FASTLZ);
|
||||
static void decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size,Mode p_mode=MODE_FASTLZ);
|
||||
|
||||
Compression();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // COMPRESSION_H
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,45 +26,46 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "config_file.h"
|
||||
#include "os/file_access.h"
|
||||
#include "os/keyboard.h"
|
||||
#include "os/file_access.h"
|
||||
#include "variant_parser.h"
|
||||
|
||||
PoolStringArray ConfigFile::_get_sections() const {
|
||||
StringArray ConfigFile::_get_sections() const {
|
||||
|
||||
List<String> s;
|
||||
get_sections(&s);
|
||||
PoolStringArray arr;
|
||||
StringArray arr;
|
||||
arr.resize(s.size());
|
||||
int idx = 0;
|
||||
for (const List<String>::Element *E = s.front(); E; E = E->next()) {
|
||||
int idx=0;
|
||||
for(const List<String>::Element *E=s.front();E;E=E->next()) {
|
||||
|
||||
arr.set(idx++, E->get());
|
||||
arr.set(idx++,E->get());
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
PoolStringArray ConfigFile::_get_section_keys(const String &p_section) const {
|
||||
StringArray ConfigFile::_get_section_keys(const String& p_section) const{
|
||||
|
||||
List<String> s;
|
||||
get_section_keys(p_section, &s);
|
||||
PoolStringArray arr;
|
||||
get_section_keys(p_section,&s);
|
||||
StringArray arr;
|
||||
arr.resize(s.size());
|
||||
int idx = 0;
|
||||
for (const List<String>::Element *E = s.front(); E; E = E->next()) {
|
||||
int idx=0;
|
||||
for(const List<String>::Element *E=s.front();E;E=E->next()) {
|
||||
|
||||
arr.set(idx++, E->get());
|
||||
arr.set(idx++,E->get());
|
||||
}
|
||||
|
||||
return arr;
|
||||
|
||||
}
|
||||
|
||||
void ConfigFile::set_value(const String &p_section, const String &p_key, const Variant &p_value) {
|
||||
|
||||
if (p_value.get_type() == Variant::NIL) {
|
||||
void ConfigFile::set_value(const String& p_section, const String& p_key, const Variant& p_value){
|
||||
|
||||
if (p_value.get_type()==Variant::NIL) {
|
||||
//erase
|
||||
if (!values.has(p_section))
|
||||
return; // ?
|
||||
@ -76,59 +76,55 @@ void ConfigFile::set_value(const String &p_section, const String &p_key, const V
|
||||
|
||||
} else {
|
||||
if (!values.has(p_section)) {
|
||||
values[p_section] = OrderedHashMap<String, Variant>();
|
||||
values[p_section]=Map<String, Variant>();
|
||||
}
|
||||
|
||||
values[p_section][p_key] = p_value;
|
||||
values[p_section][p_key]=p_value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Variant ConfigFile::get_value(const String &p_section, const String &p_key, Variant p_default) const {
|
||||
Variant ConfigFile::get_value(const String& p_section, const String& p_key, Variant p_default) const {
|
||||
|
||||
if (!values.has(p_section) || !values[p_section].has(p_key)) {
|
||||
if (p_default.get_type() == Variant::NIL) {
|
||||
ERR_EXPLAIN("Couldn't find the given section/key and no default was given");
|
||||
ERR_FAIL_V(p_default);
|
||||
}
|
||||
return p_default;
|
||||
}
|
||||
ERR_FAIL_COND_V(!values.has(p_section),p_default);
|
||||
ERR_FAIL_COND_V(!values[p_section].has(p_key),p_default);
|
||||
return values[p_section][p_key];
|
||||
|
||||
}
|
||||
|
||||
bool ConfigFile::has_section(const String &p_section) const {
|
||||
bool ConfigFile::has_section(const String& p_section) const {
|
||||
|
||||
return values.has(p_section);
|
||||
}
|
||||
bool ConfigFile::has_section_key(const String &p_section, const String &p_key) const {
|
||||
bool ConfigFile::has_section_key(const String& p_section,const String& p_key) const {
|
||||
|
||||
if (!values.has(p_section))
|
||||
return false;
|
||||
return values[p_section].has(p_key);
|
||||
}
|
||||
|
||||
void ConfigFile::get_sections(List<String> *r_sections) const {
|
||||
void ConfigFile::get_sections(List<String> *r_sections) const{
|
||||
|
||||
for (OrderedHashMap<String, OrderedHashMap<String, Variant> >::ConstElement E = values.front(); E; E = E.next()) {
|
||||
r_sections->push_back(E.key());
|
||||
for(const Map< String, Map<String, Variant> >::Element *E=values.front();E;E=E->next()) {
|
||||
r_sections->push_back(E->key());
|
||||
}
|
||||
}
|
||||
void ConfigFile::get_section_keys(const String &p_section, List<String> *r_keys) const {
|
||||
void ConfigFile::get_section_keys(const String& p_section,List<String> *r_keys) const{
|
||||
|
||||
ERR_FAIL_COND(!values.has(p_section));
|
||||
|
||||
for (OrderedHashMap<String, Variant>::ConstElement E = values[p_section].front(); E; E = E.next()) {
|
||||
r_keys->push_back(E.key());
|
||||
for(const Map<String, Variant> ::Element *E=values[p_section].front();E;E=E->next()) {
|
||||
r_keys->push_back(E->key());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ConfigFile::erase_section(const String &p_section) {
|
||||
|
||||
values.erase(p_section);
|
||||
}
|
||||
|
||||
Error ConfigFile::save(const String &p_path) {
|
||||
Error ConfigFile::save(const String& p_path){
|
||||
|
||||
Error err;
|
||||
FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err);
|
||||
FileAccess *file = FileAccess::open(p_path,FileAccess::WRITE,&err);
|
||||
|
||||
if (err) {
|
||||
if (file)
|
||||
@ -136,17 +132,18 @@ Error ConfigFile::save(const String &p_path) {
|
||||
return err;
|
||||
}
|
||||
|
||||
for (OrderedHashMap<String, OrderedHashMap<String, Variant> >::Element E = values.front(); E; E = E.next()) {
|
||||
|
||||
if (E != values.front())
|
||||
for(Map< String, Map<String, Variant> >::Element *E=values.front();E;E=E->next()) {
|
||||
|
||||
if (E!=values.front())
|
||||
file->store_string("\n");
|
||||
file->store_string("[" + E.key() + "]\n\n");
|
||||
file->store_string("["+E->key()+"]\n\n");
|
||||
|
||||
for (OrderedHashMap<String, Variant>::Element F = E.get().front(); F; F = F.next()) {
|
||||
for(Map<String, Variant>::Element *F=E->get().front();F;F=F->next()) {
|
||||
|
||||
String vstr;
|
||||
VariantWriter::write_to_string(F.get(), vstr);
|
||||
file->store_string(F.key() + "=" + vstr + "\n");
|
||||
VariantWriter::write_to_string(F->get(),vstr);
|
||||
file->store_string(F->key()+"="+vstr+"\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,46 +152,48 @@ Error ConfigFile::save(const String &p_path) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
Error ConfigFile::load(const String &p_path) {
|
||||
|
||||
Error ConfigFile::load(const String& p_path) {
|
||||
|
||||
Error err;
|
||||
FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
|
||||
FileAccess *f= FileAccess::open(p_path,FileAccess::READ,&err);
|
||||
|
||||
if (!f)
|
||||
return ERR_CANT_OPEN;
|
||||
|
||||
VariantParser::StreamFile stream;
|
||||
stream.f = f;
|
||||
stream.f=f;
|
||||
|
||||
String assign;
|
||||
Variant value;
|
||||
VariantParser::Tag next_tag;
|
||||
|
||||
int lines = 0;
|
||||
int lines=0;
|
||||
String error_text;
|
||||
|
||||
String section;
|
||||
|
||||
while (true) {
|
||||
while(true) {
|
||||
|
||||
assign = Variant();
|
||||
assign=Variant();
|
||||
next_tag.fields.clear();
|
||||
next_tag.name = String();
|
||||
next_tag.name=String();
|
||||
|
||||
err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, NULL, true);
|
||||
if (err == ERR_FILE_EOF) {
|
||||
err = VariantParser::parse_tag_assign_eof(&stream,lines,error_text,next_tag,assign,value,NULL,true);
|
||||
if (err==ERR_FILE_EOF) {
|
||||
memdelete(f);
|
||||
return OK;
|
||||
} else if (err != OK) {
|
||||
ERR_PRINTS("ConfgFile::load - " + p_path + ":" + itos(lines) + " error: " + error_text);
|
||||
}
|
||||
else if (err!=OK) {
|
||||
ERR_PRINTS("ConfgFile::load - "+p_path+":"+itos(lines)+" error: "+error_text);
|
||||
memdelete(f);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (assign != String()) {
|
||||
set_value(section, assign, value);
|
||||
} else if (next_tag.name != String()) {
|
||||
section = next_tag.name;
|
||||
if (assign!=String()) {
|
||||
set_value(section,assign,value);
|
||||
} else if (next_tag.name!=String()) {
|
||||
section=next_tag.name;
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,22 +202,25 @@ Error ConfigFile::load(const String &p_path) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
void ConfigFile::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_value", "section", "key", "value"), &ConfigFile::set_value);
|
||||
ClassDB::bind_method(D_METHOD("get_value", "section", "key", "default"), &ConfigFile::get_value, DEFVAL(Variant()));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("has_section", "section"), &ConfigFile::has_section);
|
||||
ClassDB::bind_method(D_METHOD("has_section_key", "section", "key"), &ConfigFile::has_section_key);
|
||||
void ConfigFile::_bind_methods(){
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_sections"), &ConfigFile::_get_sections);
|
||||
ClassDB::bind_method(D_METHOD("get_section_keys", "section"), &ConfigFile::_get_section_keys);
|
||||
ObjectTypeDB::bind_method(_MD("set_value","section","key","value"),&ConfigFile::set_value);
|
||||
ObjectTypeDB::bind_method(_MD("get_value:Variant","section","key","default"),&ConfigFile::get_value,DEFVAL(Variant()));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("erase_section", "section"), &ConfigFile::erase_section);
|
||||
ObjectTypeDB::bind_method(_MD("has_section","section"),&ConfigFile::has_section);
|
||||
ObjectTypeDB::bind_method(_MD("has_section_key","section","key"),&ConfigFile::has_section_key);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_sections"),&ConfigFile::_get_sections);
|
||||
ObjectTypeDB::bind_method(_MD("get_section_keys","section"),&ConfigFile::_get_section_keys);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("load:Error","path"),&ConfigFile::load);
|
||||
ObjectTypeDB::bind_method(_MD("save:Error","path"),&ConfigFile::save);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("load", "path"), &ConfigFile::load);
|
||||
ClassDB::bind_method(D_METHOD("save", "path"), &ConfigFile::save);
|
||||
}
|
||||
|
||||
ConfigFile::ConfigFile() {
|
||||
|
||||
ConfigFile::ConfigFile()
|
||||
{
|
||||
}
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,39 +26,36 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef CONFIG_FILE_H
|
||||
#define CONFIG_FILE_H
|
||||
|
||||
#include "core/ordered_hash_map.h"
|
||||
#include "reference.h"
|
||||
|
||||
|
||||
class ConfigFile : public Reference {
|
||||
|
||||
GDCLASS(ConfigFile, Reference);
|
||||
OBJ_TYPE(ConfigFile,Reference);
|
||||
|
||||
OrderedHashMap<String, OrderedHashMap<String, Variant> > values;
|
||||
|
||||
PoolStringArray _get_sections() const;
|
||||
PoolStringArray _get_section_keys(const String &p_section) const;
|
||||
Map< String, Map<String, Variant> > values;
|
||||
|
||||
StringArray _get_sections() const;
|
||||
StringArray _get_section_keys(const String& p_section) const;
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_value(const String &p_section, const String &p_key, const Variant &p_value);
|
||||
Variant get_value(const String &p_section, const String &p_key, Variant p_default = Variant()) const;
|
||||
|
||||
bool has_section(const String &p_section) const;
|
||||
bool has_section_key(const String &p_section, const String &p_key) const;
|
||||
void set_value(const String& p_section, const String& p_key, const Variant& p_value);
|
||||
Variant get_value(const String& p_section, const String& p_key, Variant p_default=Variant()) const;
|
||||
|
||||
bool has_section(const String& p_section) const;
|
||||
bool has_section_key(const String& p_section,const String& p_key) const;
|
||||
|
||||
void get_sections(List<String> *r_sections) const;
|
||||
void get_section_keys(const String &p_section, List<String> *r_keys) const;
|
||||
void get_section_keys(const String& p_section,List<String> *r_keys) const;
|
||||
|
||||
void erase_section(const String &p_section);
|
||||
|
||||
Error save(const String &p_path);
|
||||
Error load(const String &p_path);
|
||||
Error save(const String& p_path);
|
||||
Error load(const String& p_path);
|
||||
|
||||
ConfigFile();
|
||||
};
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
/***********************************************************************
|
||||
* Return the next byte in the pseudo-random sequence
|
||||
*/
|
||||
static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab)
|
||||
static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
|
||||
{
|
||||
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
|
||||
* unpredictable manner on 16-bit systems; not a problem
|
||||
@ -45,7 +45,7 @@ static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab)
|
||||
/***********************************************************************
|
||||
* Update the encryption keys with the next byte of plain text
|
||||
*/
|
||||
static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c)
|
||||
static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
|
||||
{
|
||||
(*(pkeys+0)) = CRC32((*(pkeys+0)), c);
|
||||
(*(pkeys+1)) += (*(pkeys+0)) & 0xff;
|
||||
@ -62,7 +62,7 @@ static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c)
|
||||
* Initialize the encryption keys and the random header according to
|
||||
* the given password.
|
||||
*/
|
||||
static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab)
|
||||
static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
|
||||
{
|
||||
*(pkeys+0) = 305419896L;
|
||||
*(pkeys+1) = 591751049L;
|
||||
@ -91,7 +91,7 @@ static int crypthead(const char* passwd, /* password string */
|
||||
unsigned char* buf, /* where to write header */
|
||||
int bufSize,
|
||||
unsigned long* pkeys,
|
||||
const z_crc_t* pcrc_32_tab,
|
||||
const unsigned long* pcrc_32_tab,
|
||||
unsigned long crcForCrypting)
|
||||
{
|
||||
int n; /* index in random header */
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,7 +26,6 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "file_access_buffered.h"
|
||||
|
||||
#include <string.h>
|
||||
@ -77,7 +75,7 @@ void FileAccessBuffered::seek_end(int64_t p_position) {
|
||||
file.offset = file.size + p_position;
|
||||
};
|
||||
|
||||
size_t FileAccessBuffered::get_position() const {
|
||||
size_t FileAccessBuffered::get_pos() const {
|
||||
|
||||
return file.offset;
|
||||
};
|
||||
@ -94,7 +92,7 @@ bool FileAccessBuffered::eof_reached() const {
|
||||
|
||||
uint8_t FileAccessBuffered::get_8() const {
|
||||
|
||||
ERR_FAIL_COND_V(!file.open, 0);
|
||||
ERR_FAIL_COND_V(!file.open,0);
|
||||
|
||||
uint8_t byte = 0;
|
||||
if (cache_data_left() >= 1) {
|
||||
@ -107,11 +105,11 @@ uint8_t FileAccessBuffered::get_8() const {
|
||||
return byte;
|
||||
};
|
||||
|
||||
int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const {
|
||||
int FileAccessBuffered::get_buffer(uint8_t *p_dest,int p_elements) const {
|
||||
|
||||
ERR_FAIL_COND_V(!file.open, -1);
|
||||
|
||||
if (p_length > cache_size) {
|
||||
if (p_elements > cache_size) {
|
||||
|
||||
int total_read = 0;
|
||||
|
||||
@ -119,16 +117,16 @@ int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const {
|
||||
|
||||
int size = (cache.buffer.size() - (file.offset - cache.offset));
|
||||
size = size - (size % 4);
|
||||
//PoolVector<uint8_t>::Read read = cache.buffer.read();
|
||||
//DVector<uint8_t>::Read read = cache.buffer.read();
|
||||
//memcpy(p_dest, read.ptr() + (file.offset - cache.offset), size);
|
||||
memcpy(p_dest, cache.buffer.ptr() + (file.offset - cache.offset), size);
|
||||
p_dest += size;
|
||||
p_length -= size;
|
||||
p_elements -= size;
|
||||
file.offset += size;
|
||||
total_read += size;
|
||||
};
|
||||
|
||||
int err = read_data_block(file.offset, p_length, p_dest);
|
||||
int err = read_data_block(file.offset, p_elements, p_dest);
|
||||
if (err >= 0) {
|
||||
total_read += err;
|
||||
file.offset += err;
|
||||
@ -137,7 +135,8 @@ int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const {
|
||||
return total_read;
|
||||
};
|
||||
|
||||
int to_read = p_length;
|
||||
|
||||
int to_read = p_elements;
|
||||
int total_read = 0;
|
||||
while (to_read > 0) {
|
||||
|
||||
@ -153,16 +152,16 @@ int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const {
|
||||
};
|
||||
|
||||
int r = MIN(left, to_read);
|
||||
//PoolVector<uint8_t>::Read read = cache.buffer.read();
|
||||
//DVector<uint8_t>::Read read = cache.buffer.read();
|
||||
//memcpy(p_dest+total_read, &read.ptr()[file.offset - cache.offset], r);
|
||||
memcpy(p_dest + total_read, cache.buffer.ptr() + (file.offset - cache.offset), r);
|
||||
memcpy(p_dest+total_read, cache.buffer.ptr() + (file.offset - cache.offset), r);
|
||||
|
||||
file.offset += r;
|
||||
total_read += r;
|
||||
to_read -= r;
|
||||
};
|
||||
|
||||
return p_length;
|
||||
return p_elements;
|
||||
};
|
||||
|
||||
bool FileAccessBuffered::is_open() const {
|
||||
@ -180,5 +179,6 @@ FileAccessBuffered::FileAccessBuffered() {
|
||||
cache_size = DEFAULT_CACHE_SIZE;
|
||||
};
|
||||
|
||||
FileAccessBuffered::~FileAccessBuffered() {
|
||||
FileAccessBuffered::~FileAccessBuffered(){
|
||||
|
||||
}
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,7 +26,6 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef FILE_ACCESS_BUFFERED_H
|
||||
#define FILE_ACCESS_BUFFERED_H
|
||||
|
||||
@ -44,12 +42,14 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
int cache_size;
|
||||
|
||||
int cache_data_left() const;
|
||||
mutable Error last_error;
|
||||
|
||||
protected:
|
||||
|
||||
Error set_error(Error p_error) const;
|
||||
|
||||
mutable struct File {
|
||||
@ -67,22 +67,23 @@ protected:
|
||||
int offset;
|
||||
} cache;
|
||||
|
||||
virtual int read_data_block(int p_offset, int p_size, uint8_t *p_dest = 0) const = 0;
|
||||
virtual int read_data_block(int p_offset, int p_size, uint8_t *p_dest = 0) const =0;
|
||||
|
||||
void set_cache_size(int p_size);
|
||||
int get_cache_size();
|
||||
|
||||
public:
|
||||
virtual size_t get_position() const; ///< get position in the file
|
||||
|
||||
virtual size_t get_pos() const; ///< get position in the file
|
||||
virtual size_t get_len() const; ///< get size of the file
|
||||
|
||||
virtual void seek(size_t p_position); ///< seek to a given position
|
||||
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
|
||||
virtual void seek_end(int64_t p_position=0); ///< seek from the end of file
|
||||
|
||||
virtual bool eof_reached() const;
|
||||
|
||||
virtual uint8_t get_8() const;
|
||||
virtual int get_buffer(uint8_t *p_dest, int p_length) const; ///< get an array of bytes
|
||||
virtual int get_buffer(uint8_t *p_dst,int p_length) const; ///< get an array of bytes
|
||||
|
||||
virtual bool is_open() const;
|
||||
|
||||
@ -93,3 +94,4 @@ public:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,22 +26,21 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef FILE_ACCESS_BUFFERED_FA_H
|
||||
#define FILE_ACCESS_BUFFERED_FA_H
|
||||
|
||||
#include "core/io/file_access_buffered.h"
|
||||
|
||||
template <class T>
|
||||
template<class T>
|
||||
class FileAccessBufferedFA : public FileAccessBuffered {
|
||||
|
||||
T f;
|
||||
|
||||
int read_data_block(int p_offset, int p_size, uint8_t *p_dest = 0) const {
|
||||
|
||||
ERR_FAIL_COND_V(!f.is_open(), -1);
|
||||
ERR_FAIL_COND_V( !f.is_open(), -1 );
|
||||
|
||||
((T *)&f)->seek(p_offset);
|
||||
((T*)&f)->seek(p_offset);
|
||||
|
||||
if (p_dest) {
|
||||
|
||||
@ -55,19 +53,19 @@ class FileAccessBufferedFA : public FileAccessBuffered {
|
||||
cache.buffer.resize(p_size);
|
||||
|
||||
// on dvector
|
||||
//PoolVector<uint8_t>::Write write = cache.buffer.write();
|
||||
//f.get_buffer(write.ptrw(), p_size);
|
||||
//DVector<uint8_t>::Write write = cache.buffer.write();
|
||||
//f.get_buffer(write.ptr(), p_size);
|
||||
|
||||
// on vector
|
||||
f.get_buffer(cache.buffer.ptrw(), p_size);
|
||||
f.get_buffer(cache.buffer.ptr(), p_size);
|
||||
|
||||
return p_size;
|
||||
};
|
||||
};
|
||||
|
||||
static FileAccess *create() {
|
||||
static FileAccess* create() {
|
||||
|
||||
return memnew(FileAccessBufferedFA<T>());
|
||||
return memnew( FileAccessBufferedFA<T>() );
|
||||
};
|
||||
|
||||
protected:
|
||||
@ -77,32 +75,29 @@ protected:
|
||||
};
|
||||
|
||||
public:
|
||||
void flush() {
|
||||
|
||||
f.flush();
|
||||
};
|
||||
|
||||
void store_8(uint8_t p_dest) {
|
||||
|
||||
f.store_8(p_dest);
|
||||
};
|
||||
|
||||
void store_buffer(const uint8_t *p_src, int p_length) {
|
||||
void store_buffer(const uint8_t *p_src,int p_length) {
|
||||
|
||||
f.store_buffer(p_src, p_length);
|
||||
};
|
||||
|
||||
bool file_exists(const String &p_name) {
|
||||
bool file_exists(const String& p_name) {
|
||||
|
||||
return f.file_exists(p_name);
|
||||
};
|
||||
|
||||
Error _open(const String &p_path, int p_mode_flags) {
|
||||
Error _open(const String& p_path, int p_mode_flags) {
|
||||
|
||||
close();
|
||||
|
||||
Error ret = f._open(p_path, p_mode_flags);
|
||||
if (ret != OK)
|
||||
if (ret !=OK)
|
||||
return ret;
|
||||
//ERR_FAIL_COND_V( ret != OK, ret );
|
||||
|
||||
@ -132,20 +127,21 @@ public:
|
||||
set_error(OK);
|
||||
};
|
||||
|
||||
/*
|
||||
static void make_default() {
|
||||
FileAccess::create_func = FileAccessBufferedFA<T>::create;
|
||||
};
|
||||
*/
|
||||
// static void make_default() {
|
||||
|
||||
virtual uint64_t _get_modified_time(const String &p_file) {
|
||||
//FileAccess::create_func = FileAccessBufferedFA<T>::create;
|
||||
// };
|
||||
|
||||
virtual uint64_t _get_modified_time(const String& p_file) {
|
||||
|
||||
return f._get_modified_time(p_file);
|
||||
}
|
||||
|
||||
FileAccessBufferedFA(){
|
||||
FileAccessBufferedFA() {
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif // FILE_ACCESS_BUFFERED_FA_H
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,226 +26,246 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "file_access_compressed.h"
|
||||
#include "print_string.h"
|
||||
void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_mode, int p_block_size) {
|
||||
void FileAccessCompressed::configure(const String& p_magic, Compression::Mode p_mode, int p_block_size) {
|
||||
|
||||
magic = p_magic.ascii().get_data();
|
||||
if (magic.length() > 4)
|
||||
magic = magic.substr(0, 4);
|
||||
magic=p_magic.ascii().get_data();
|
||||
if (magic.length()>4)
|
||||
magic=magic.substr(0,4);
|
||||
else {
|
||||
while (magic.length() < 4)
|
||||
magic += " ";
|
||||
while(magic.length()<4)
|
||||
magic+=" ";
|
||||
}
|
||||
|
||||
cmode = p_mode;
|
||||
block_size = p_block_size;
|
||||
cmode=p_mode;
|
||||
block_size=p_block_size;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#define WRITE_FIT(m_bytes) \
|
||||
{\
|
||||
if (write_pos+(m_bytes) > write_max) {\
|
||||
write_max=write_pos+(m_bytes);\
|
||||
}\
|
||||
if (write_max > write_buffer_size) {\
|
||||
write_buffer_size = nearest_power_of_2( write_max );\
|
||||
buffer.resize(write_buffer_size);\
|
||||
write_ptr=buffer.ptr();\
|
||||
}\
|
||||
}
|
||||
|
||||
#define WRITE_FIT(m_bytes) \
|
||||
{ \
|
||||
if (write_pos + (m_bytes) > write_max) { \
|
||||
write_max = write_pos + (m_bytes); \
|
||||
} \
|
||||
if (write_max > write_buffer_size) { \
|
||||
write_buffer_size = next_power_of_2(write_max); \
|
||||
buffer.resize(write_buffer_size); \
|
||||
write_ptr = buffer.ptrw(); \
|
||||
} \
|
||||
}
|
||||
|
||||
Error FileAccessCompressed::open_after_magic(FileAccess *p_base) {
|
||||
|
||||
f = p_base;
|
||||
cmode = (Compression::Mode)f->get_32();
|
||||
block_size = f->get_32();
|
||||
read_total = f->get_32();
|
||||
int bc = (read_total / block_size) + 1;
|
||||
int acc_ofs = f->get_position() + bc * 4;
|
||||
int max_bs = 0;
|
||||
for (int i = 0; i < bc; i++) {
|
||||
|
||||
f=p_base;
|
||||
cmode=(Compression::Mode)f->get_32();
|
||||
block_size=f->get_32();
|
||||
read_total=f->get_32();
|
||||
int bc = (read_total/block_size)+1;
|
||||
int acc_ofs=f->get_pos()+bc*4;
|
||||
int max_bs=0;
|
||||
for(int i=0;i<bc;i++) {
|
||||
|
||||
ReadBlock rb;
|
||||
rb.offset = acc_ofs;
|
||||
rb.csize = f->get_32();
|
||||
acc_ofs += rb.csize;
|
||||
max_bs = MAX(max_bs, rb.csize);
|
||||
rb.offset=acc_ofs;
|
||||
rb.csize=f->get_32();
|
||||
acc_ofs+=rb.csize;
|
||||
max_bs=MAX(max_bs,rb.csize);
|
||||
read_blocks.push_back(rb);
|
||||
|
||||
|
||||
}
|
||||
|
||||
comp_buffer.resize(max_bs);
|
||||
buffer.resize(block_size);
|
||||
read_ptr = buffer.ptrw();
|
||||
f->get_buffer(comp_buffer.ptrw(), read_blocks[0].csize);
|
||||
at_end = false;
|
||||
read_eof = false;
|
||||
read_block_count = bc;
|
||||
read_block_size = read_blocks.size() == 1 ? read_total : block_size;
|
||||
read_ptr=buffer.ptr();
|
||||
f->get_buffer(comp_buffer.ptr(),read_blocks[0].csize);
|
||||
at_end=false;
|
||||
read_eof=false;
|
||||
read_block_count=bc;
|
||||
read_block_size=read_blocks.size()==1?read_total:block_size;
|
||||
|
||||
Compression::decompress(buffer.ptrw(), read_block_size, comp_buffer.ptr(), read_blocks[0].csize, cmode);
|
||||
read_block = 0;
|
||||
read_pos = 0;
|
||||
Compression::decompress(buffer.ptr(),read_block_size,comp_buffer.ptr(),read_blocks[0].csize,cmode);
|
||||
read_block=0;
|
||||
read_pos=0;
|
||||
|
||||
return OK;
|
||||
|
||||
}
|
||||
|
||||
Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) {
|
||||
Error FileAccessCompressed::_open(const String& p_path, int p_mode_flags){
|
||||
|
||||
ERR_FAIL_COND_V(p_mode_flags == READ_WRITE, ERR_UNAVAILABLE);
|
||||
ERR_FAIL_COND_V(p_mode_flags==READ_WRITE,ERR_UNAVAILABLE);
|
||||
|
||||
if (f)
|
||||
close();
|
||||
|
||||
|
||||
Error err;
|
||||
f = FileAccess::open(p_path, p_mode_flags, &err);
|
||||
if (err != OK) {
|
||||
f = FileAccess::open(p_path,p_mode_flags,&err);
|
||||
if (err!=OK) {
|
||||
//not openable
|
||||
|
||||
f = NULL;
|
||||
f=NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
if (p_mode_flags & WRITE) {
|
||||
if (p_mode_flags&WRITE) {
|
||||
|
||||
buffer.clear();
|
||||
writing = true;
|
||||
write_pos = 0;
|
||||
write_buffer_size = 256;
|
||||
writing=true;
|
||||
write_pos=0;
|
||||
write_buffer_size=256;
|
||||
buffer.resize(256);
|
||||
write_max = 0;
|
||||
write_ptr = buffer.ptrw();
|
||||
write_max=0;
|
||||
write_ptr=buffer.ptr();
|
||||
|
||||
|
||||
|
||||
//don't store anything else unless it's done saving!
|
||||
} else {
|
||||
|
||||
char rmagic[5];
|
||||
f->get_buffer((uint8_t *)rmagic, 4);
|
||||
rmagic[4] = 0;
|
||||
if (magic != rmagic) {
|
||||
f->get_buffer((uint8_t*)rmagic,4);
|
||||
rmagic[4]=0;
|
||||
if (magic!=rmagic) {
|
||||
memdelete(f);
|
||||
f = NULL;
|
||||
f=NULL;
|
||||
return ERR_FILE_UNRECOGNIZED;
|
||||
}
|
||||
|
||||
open_after_magic(f);
|
||||
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
}
|
||||
void FileAccessCompressed::close() {
|
||||
void FileAccessCompressed::close(){
|
||||
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
|
||||
if (writing) {
|
||||
//save block table and all compressed blocks
|
||||
|
||||
CharString mgc = magic.utf8();
|
||||
f->store_buffer((const uint8_t *)mgc.get_data(), mgc.length()); //write header 4
|
||||
f->store_buffer((const uint8_t*)mgc.get_data(),mgc.length()); //write header 4
|
||||
f->store_32(cmode); //write compression mode 4
|
||||
f->store_32(block_size); //write block size 4
|
||||
f->store_32(write_max); //max amount of data written 4
|
||||
int bc = (write_max / block_size) + 1;
|
||||
int bc=(write_max/block_size)+1;
|
||||
|
||||
for (int i = 0; i < bc; i++) {
|
||||
for(int i=0;i<bc;i++) {
|
||||
f->store_32(0); //compressed sizes, will update later
|
||||
}
|
||||
|
||||
Vector<int> block_sizes;
|
||||
for (int i = 0; i < bc; i++) {
|
||||
|
||||
int bl = i == (bc - 1) ? write_max % block_size : block_size;
|
||||
uint8_t *bp = &write_ptr[i * block_size];
|
||||
Vector<int> block_sizes;
|
||||
for(int i=0;i<bc;i++) {
|
||||
|
||||
int bl = i==(bc-1) ? write_max % block_size : block_size;
|
||||
uint8_t *bp = &write_ptr[i*block_size];
|
||||
|
||||
Vector<uint8_t> cblock;
|
||||
cblock.resize(Compression::get_max_compressed_buffer_size(bl, cmode));
|
||||
int s = Compression::compress(cblock.ptrw(), bp, bl, cmode);
|
||||
cblock.resize(Compression::get_max_compressed_buffer_size(bl,cmode));
|
||||
int s = Compression::compress(cblock.ptr(),bp,bl,cmode);
|
||||
|
||||
f->store_buffer(cblock.ptr(), s);
|
||||
f->store_buffer(cblock.ptr(),s);
|
||||
block_sizes.push_back(s);
|
||||
}
|
||||
|
||||
f->seek(16); //ok write block sizes
|
||||
for (int i = 0; i < bc; i++)
|
||||
for(int i=0;i<bc;i++)
|
||||
f->store_32(block_sizes[i]);
|
||||
f->seek_end();
|
||||
f->store_buffer((const uint8_t *)mgc.get_data(), mgc.length()); //magic at the end too
|
||||
f->store_buffer((const uint8_t*)mgc.get_data(),mgc.length()); //magic at the end too
|
||||
|
||||
buffer.clear();
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
comp_buffer.clear();
|
||||
buffer.clear();
|
||||
read_blocks.clear();
|
||||
}
|
||||
|
||||
memdelete(f);
|
||||
f = NULL;
|
||||
f=NULL;
|
||||
|
||||
}
|
||||
|
||||
bool FileAccessCompressed::is_open() const {
|
||||
bool FileAccessCompressed::is_open() const{
|
||||
|
||||
return f != NULL;
|
||||
return f!=NULL;
|
||||
}
|
||||
|
||||
void FileAccessCompressed::seek(size_t p_position) {
|
||||
void FileAccessCompressed::seek(size_t p_position){
|
||||
|
||||
ERR_FAIL_COND(!f);
|
||||
if (writing) {
|
||||
|
||||
ERR_FAIL_COND(p_position > write_max);
|
||||
ERR_FAIL_COND(p_position>write_max);
|
||||
|
||||
write_pos = p_position;
|
||||
write_pos=p_position;
|
||||
|
||||
} else {
|
||||
|
||||
ERR_FAIL_COND(p_position > read_total);
|
||||
if (p_position == read_total) {
|
||||
at_end = true;
|
||||
ERR_FAIL_COND(p_position>read_total);
|
||||
if (p_position==read_total) {
|
||||
at_end=true;
|
||||
} else {
|
||||
|
||||
int block_idx = p_position / block_size;
|
||||
if (block_idx != read_block) {
|
||||
int block_idx = p_position/block_size;
|
||||
if (block_idx!=read_block) {
|
||||
|
||||
read_block = block_idx;
|
||||
read_block=block_idx;
|
||||
f->seek(read_blocks[read_block].offset);
|
||||
f->get_buffer(comp_buffer.ptrw(), read_blocks[read_block].csize);
|
||||
Compression::decompress(buffer.ptrw(), read_blocks.size() == 1 ? read_total : block_size, comp_buffer.ptr(), read_blocks[read_block].csize, cmode);
|
||||
read_block_size = read_block == read_block_count - 1 ? read_total % block_size : block_size;
|
||||
f->get_buffer(comp_buffer.ptr(),read_blocks[read_block].csize);
|
||||
Compression::decompress(buffer.ptr(),read_blocks.size()==1?read_total:block_size,comp_buffer.ptr(),read_blocks[read_block].csize,cmode);
|
||||
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size;
|
||||
}
|
||||
|
||||
read_pos = p_position % block_size;
|
||||
read_pos=p_position%block_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileAccessCompressed::seek_end(int64_t p_position) {
|
||||
|
||||
void FileAccessCompressed::seek_end(int64_t p_position){
|
||||
|
||||
ERR_FAIL_COND(!f);
|
||||
if (writing) {
|
||||
|
||||
seek(write_max + p_position);
|
||||
seek(write_max+p_position);
|
||||
} else {
|
||||
|
||||
seek(read_total + p_position);
|
||||
}
|
||||
}
|
||||
size_t FileAccessCompressed::get_position() const {
|
||||
seek(read_total+p_position);
|
||||
|
||||
ERR_FAIL_COND_V(!f, 0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
size_t FileAccessCompressed::get_pos() const{
|
||||
|
||||
ERR_FAIL_COND_V(!f,0);
|
||||
if (writing) {
|
||||
|
||||
return write_pos;
|
||||
} else {
|
||||
|
||||
return read_block * block_size + read_pos;
|
||||
return read_block*block_size+read_pos;
|
||||
}
|
||||
}
|
||||
size_t FileAccessCompressed::get_len() const {
|
||||
|
||||
ERR_FAIL_COND_V(!f, 0);
|
||||
}
|
||||
size_t FileAccessCompressed::get_len() const{
|
||||
|
||||
ERR_FAIL_COND_V(!f,0);
|
||||
if (writing) {
|
||||
|
||||
return write_max;
|
||||
@ -255,9 +274,9 @@ size_t FileAccessCompressed::get_len() const {
|
||||
}
|
||||
}
|
||||
|
||||
bool FileAccessCompressed::eof_reached() const {
|
||||
bool FileAccessCompressed::eof_reached() const{
|
||||
|
||||
ERR_FAIL_COND_V(!f, false);
|
||||
ERR_FAIL_COND_V(!f,false);
|
||||
if (writing) {
|
||||
return false;
|
||||
} else {
|
||||
@ -265,105 +284,106 @@ bool FileAccessCompressed::eof_reached() const {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t FileAccessCompressed::get_8() const {
|
||||
uint8_t FileAccessCompressed::get_8() const{
|
||||
|
||||
ERR_FAIL_COND_V(writing, 0);
|
||||
ERR_FAIL_COND_V(!f, 0);
|
||||
ERR_FAIL_COND_V(writing,0);
|
||||
ERR_FAIL_COND_V(!f,0);
|
||||
|
||||
if (at_end) {
|
||||
read_eof = true;
|
||||
read_eof=true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t ret = read_ptr[read_pos];
|
||||
|
||||
read_pos++;
|
||||
if (read_pos >= read_block_size) {
|
||||
if (read_pos>=read_block_size) {
|
||||
read_block++;
|
||||
|
||||
if (read_block < read_block_count) {
|
||||
if (read_block<read_block_count) {
|
||||
//read another block of compressed data
|
||||
f->get_buffer(comp_buffer.ptrw(), read_blocks[read_block].csize);
|
||||
Compression::decompress(buffer.ptrw(), read_blocks.size() == 1 ? read_total : block_size, comp_buffer.ptr(), read_blocks[read_block].csize, cmode);
|
||||
read_block_size = read_block == read_block_count - 1 ? read_total % block_size : block_size;
|
||||
read_pos = 0;
|
||||
f->get_buffer(comp_buffer.ptr(),read_blocks[read_block].csize);
|
||||
Compression::decompress(buffer.ptr(),read_blocks.size()==1?read_total:block_size,comp_buffer.ptr(),read_blocks[read_block].csize,cmode);
|
||||
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size;
|
||||
read_pos=0;
|
||||
|
||||
} else {
|
||||
read_block--;
|
||||
at_end = true;
|
||||
at_end=true;
|
||||
ret =0;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const {
|
||||
|
||||
ERR_FAIL_COND_V(writing, 0);
|
||||
ERR_FAIL_COND_V(!f, 0);
|
||||
}
|
||||
int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const{
|
||||
|
||||
ERR_FAIL_COND_V(writing,0);
|
||||
ERR_FAIL_COND_V(!f,0);
|
||||
|
||||
if (at_end) {
|
||||
read_eof = true;
|
||||
read_eof=true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < p_length; i++) {
|
||||
|
||||
p_dst[i] = read_ptr[read_pos];
|
||||
for(int i=0;i<p_length;i++) {
|
||||
|
||||
|
||||
p_dst[i]=read_ptr[read_pos];
|
||||
read_pos++;
|
||||
if (read_pos >= read_block_size) {
|
||||
if (read_pos>=read_block_size) {
|
||||
read_block++;
|
||||
|
||||
if (read_block < read_block_count) {
|
||||
if (read_block<read_block_count) {
|
||||
//read another block of compressed data
|
||||
f->get_buffer(comp_buffer.ptrw(), read_blocks[read_block].csize);
|
||||
Compression::decompress(buffer.ptrw(), read_blocks.size() == 1 ? read_total : block_size, comp_buffer.ptr(), read_blocks[read_block].csize, cmode);
|
||||
read_block_size = read_block == read_block_count - 1 ? read_total % block_size : block_size;
|
||||
read_pos = 0;
|
||||
f->get_buffer(comp_buffer.ptr(),read_blocks[read_block].csize);
|
||||
Compression::decompress(buffer.ptr(),read_blocks.size()==1?read_total:block_size,comp_buffer.ptr(),read_blocks[read_block].csize,cmode);
|
||||
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size;
|
||||
read_pos=0;
|
||||
|
||||
} else {
|
||||
read_block--;
|
||||
at_end = true;
|
||||
if (i < p_length - 1)
|
||||
read_eof = true;
|
||||
at_end=true;
|
||||
if (i<p_length-1)
|
||||
read_eof=true;
|
||||
return i;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return p_length;
|
||||
|
||||
}
|
||||
|
||||
Error FileAccessCompressed::get_error() const {
|
||||
Error FileAccessCompressed::get_error() const{
|
||||
|
||||
return read_eof ? ERR_FILE_EOF : OK;
|
||||
return read_eof?ERR_FILE_EOF:OK;
|
||||
}
|
||||
|
||||
void FileAccessCompressed::flush() {
|
||||
ERR_FAIL_COND(!f);
|
||||
ERR_FAIL_COND(!writing);
|
||||
|
||||
// compressed files keep data in memory till close()
|
||||
}
|
||||
|
||||
void FileAccessCompressed::store_8(uint8_t p_dest) {
|
||||
void FileAccessCompressed::store_8(uint8_t p_dest){
|
||||
|
||||
ERR_FAIL_COND(!f);
|
||||
ERR_FAIL_COND(!writing);
|
||||
|
||||
WRITE_FIT(1);
|
||||
write_ptr[write_pos++] = p_dest;
|
||||
write_ptr[write_pos++]=p_dest;
|
||||
|
||||
}
|
||||
|
||||
bool FileAccessCompressed::file_exists(const String &p_name) {
|
||||
bool FileAccessCompressed::file_exists(const String& p_name){
|
||||
|
||||
FileAccess *fa = FileAccess::open(p_name, FileAccess::READ);
|
||||
FileAccess *fa = FileAccess::open(p_name,FileAccess::READ);
|
||||
if (!fa)
|
||||
return false;
|
||||
memdelete(fa);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t FileAccessCompressed::_get_modified_time(const String &p_file) {
|
||||
uint64_t FileAccessCompressed::_get_modified_time(const String& p_file) {
|
||||
|
||||
if (f)
|
||||
return f->get_modified_time(p_file);
|
||||
@ -373,26 +393,29 @@ uint64_t FileAccessCompressed::_get_modified_time(const String &p_file) {
|
||||
|
||||
FileAccessCompressed::FileAccessCompressed() {
|
||||
|
||||
f = NULL;
|
||||
magic = "GCMP";
|
||||
cmode = Compression::MODE_ZSTD;
|
||||
writing = false;
|
||||
write_ptr = 0;
|
||||
write_buffer_size = 0;
|
||||
write_max = 0;
|
||||
block_size = 0;
|
||||
read_eof = false;
|
||||
at_end = false;
|
||||
read_total = 0;
|
||||
read_ptr = NULL;
|
||||
read_block = 0;
|
||||
read_block_count = 0;
|
||||
read_block_size = 0;
|
||||
read_pos = 0;
|
||||
f=NULL;
|
||||
magic="GCMP";
|
||||
block_size=16384;
|
||||
cmode=Compression::MODE_DEFLATE;
|
||||
writing=false;
|
||||
write_ptr=0;
|
||||
write_buffer_size=0;
|
||||
write_max=0;
|
||||
block_size=0;
|
||||
read_eof=false;
|
||||
at_end=false;
|
||||
read_total=0;
|
||||
read_ptr=NULL;
|
||||
read_block=0;
|
||||
read_block_count=0;
|
||||
read_block_size=0;
|
||||
read_pos=0;
|
||||
|
||||
}
|
||||
|
||||
FileAccessCompressed::~FileAccessCompressed() {
|
||||
FileAccessCompressed::~FileAccessCompressed(){
|
||||
|
||||
if (f)
|
||||
close();
|
||||
|
||||
}
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,7 +26,6 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef FILE_ACCESS_COMPRESSED_H
|
||||
#define FILE_ACCESS_COMPRESSED_H
|
||||
|
||||
@ -38,11 +36,11 @@ class FileAccessCompressed : public FileAccess {
|
||||
|
||||
Compression::Mode cmode;
|
||||
bool writing;
|
||||
uint32_t write_pos;
|
||||
uint8_t *write_ptr;
|
||||
uint32_t write_buffer_size;
|
||||
uint32_t write_max;
|
||||
uint32_t block_size;
|
||||
int write_pos;
|
||||
uint8_t*write_ptr;
|
||||
int write_buffer_size;
|
||||
int write_max;
|
||||
int block_size;
|
||||
mutable bool read_eof;
|
||||
mutable bool at_end;
|
||||
|
||||
@ -58,24 +56,27 @@ class FileAccessCompressed : public FileAccess {
|
||||
mutable int read_block_size;
|
||||
mutable int read_pos;
|
||||
Vector<ReadBlock> read_blocks;
|
||||
uint32_t read_total;
|
||||
int read_total;
|
||||
|
||||
|
||||
|
||||
|
||||
String magic;
|
||||
mutable Vector<uint8_t> buffer;
|
||||
FileAccess *f;
|
||||
|
||||
public:
|
||||
void configure(const String &p_magic, Compression::Mode p_mode = Compression::MODE_ZSTD, int p_block_size = 4096);
|
||||
|
||||
void configure(const String& p_magic, Compression::Mode p_mode=Compression::MODE_FASTLZ, int p_block_size=4096);
|
||||
|
||||
Error open_after_magic(FileAccess *p_base);
|
||||
|
||||
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
|
||||
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
|
||||
virtual void close(); ///< close a file
|
||||
virtual bool is_open() const; ///< true when file is open
|
||||
|
||||
virtual void seek(size_t p_position); ///< seek to a given position
|
||||
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
|
||||
virtual size_t get_position() const; ///< get position in the file
|
||||
virtual void seek_end(int64_t p_position=0); ///< seek from the end of file
|
||||
virtual size_t get_pos() const; ///< get position in the file
|
||||
virtual size_t get_len() const; ///< get size of the file
|
||||
|
||||
virtual bool eof_reached() const; ///< reading passed EOF
|
||||
@ -85,15 +86,16 @@ public:
|
||||
|
||||
virtual Error get_error() const; ///< get last error
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_dest); ///< store a byte
|
||||
|
||||
virtual bool file_exists(const String &p_name); ///< return true if a file exists
|
||||
virtual bool file_exists(const String& p_name); ///< return true if a file exists
|
||||
|
||||
virtual uint64_t _get_modified_time(const String& p_file);
|
||||
|
||||
virtual uint64_t _get_modified_time(const String &p_file);
|
||||
|
||||
FileAccessCompressed();
|
||||
virtual ~FileAccessCompressed();
|
||||
|
||||
};
|
||||
|
||||
#endif // FILE_ACCESS_COMPRESSED_H
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,69 +26,65 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "file_access_encrypted.h"
|
||||
|
||||
#include "core/variant.h"
|
||||
#include "aes256.h"
|
||||
#include "md5.h"
|
||||
#include "os/copymem.h"
|
||||
#include "print_string.h"
|
||||
|
||||
#include "thirdparty/misc/aes256.h"
|
||||
#include "thirdparty/misc/md5.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define COMP_MAGIC 0x43454447
|
||||
|
||||
Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8_t> &p_key, Mode p_mode) {
|
||||
#include "core/variant.h"
|
||||
#include <stdio.h>
|
||||
|
||||
Error FileAccessEncrypted::open_and_parse(FileAccess *p_base,const Vector<uint8_t>& p_key,Mode p_mode) {
|
||||
|
||||
//print_line("open and parse!");
|
||||
ERR_FAIL_COND_V(file != NULL, ERR_ALREADY_IN_USE);
|
||||
ERR_FAIL_COND_V(p_key.size() != 32, ERR_INVALID_PARAMETER);
|
||||
ERR_FAIL_COND_V(file!=NULL,ERR_ALREADY_IN_USE);
|
||||
ERR_FAIL_COND_V(p_key.size()!=32,ERR_INVALID_PARAMETER);
|
||||
|
||||
pos = 0;
|
||||
eofed = false;
|
||||
pos=0;
|
||||
eofed=false;
|
||||
|
||||
if (p_mode == MODE_WRITE_AES256) {
|
||||
if (p_mode==MODE_WRITE_AES256) {
|
||||
|
||||
data.clear();
|
||||
writing = true;
|
||||
file = p_base;
|
||||
mode = p_mode;
|
||||
key = p_key;
|
||||
writing=true;
|
||||
file=p_base;
|
||||
mode=p_mode;
|
||||
key=p_key;
|
||||
|
||||
} else if (p_mode == MODE_READ) {
|
||||
} else if (p_mode==MODE_READ) {
|
||||
|
||||
writing = false;
|
||||
key = p_key;
|
||||
writing=false;
|
||||
key=p_key;
|
||||
uint32_t magic = p_base->get_32();
|
||||
ERR_FAIL_COND_V(magic != COMP_MAGIC, ERR_FILE_UNRECOGNIZED);
|
||||
|
||||
mode = Mode(p_base->get_32());
|
||||
ERR_FAIL_INDEX_V(mode, MODE_MAX, ERR_FILE_CORRUPT);
|
||||
ERR_FAIL_COND_V(mode == 0, ERR_FILE_CORRUPT);
|
||||
|
||||
print_line("MAGIC: "+itos(magic));
|
||||
ERR_FAIL_COND_V(magic!=COMP_MAGIC,ERR_FILE_UNRECOGNIZED);
|
||||
mode=Mode(p_base->get_32());
|
||||
ERR_FAIL_INDEX_V(mode,MODE_MAX,ERR_FILE_CORRUPT);
|
||||
ERR_FAIL_COND_V(mode==0,ERR_FILE_CORRUPT);
|
||||
print_line("MODE: "+itos(mode));
|
||||
unsigned char md5d[16];
|
||||
p_base->get_buffer(md5d, 16);
|
||||
length = p_base->get_64();
|
||||
base = p_base->get_position();
|
||||
ERR_FAIL_COND_V(p_base->get_len() < base + length, ERR_FILE_CORRUPT);
|
||||
uint32_t ds = length;
|
||||
p_base->get_buffer(md5d,16);
|
||||
length=p_base->get_64();
|
||||
base=p_base->get_pos();
|
||||
ERR_FAIL_COND_V(p_base->get_len() < base+length, ERR_FILE_CORRUPT );
|
||||
int ds = length;
|
||||
if (ds % 16) {
|
||||
ds += 16 - (ds % 16);
|
||||
ds+=16-(ds % 16);
|
||||
}
|
||||
|
||||
data.resize(ds);
|
||||
|
||||
uint32_t blen = p_base->get_buffer(data.ptrw(), ds);
|
||||
ERR_FAIL_COND_V(blen != ds, ERR_FILE_CORRUPT);
|
||||
int blen = p_base->get_buffer(data.ptr(),ds);
|
||||
ERR_FAIL_COND_V(blen!=ds,ERR_FILE_CORRUPT);
|
||||
|
||||
aes256_context ctx;
|
||||
aes256_init(&ctx, key.ptrw());
|
||||
aes256_init(&ctx,key.ptr());
|
||||
|
||||
for (size_t i = 0; i < ds; i += 16) {
|
||||
for(size_t i=0;i<ds;i+=16) {
|
||||
|
||||
aes256_decrypt_ecb(&ctx, &data[i]);
|
||||
aes256_decrypt_ecb(&ctx,&data[i]);
|
||||
}
|
||||
|
||||
aes256_done(&ctx);
|
||||
@ -98,32 +93,37 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8
|
||||
|
||||
MD5_CTX md5;
|
||||
MD5Init(&md5);
|
||||
MD5Update(&md5, (uint8_t *)data.ptr(), data.size());
|
||||
MD5Update(&md5,data.ptr(),data.size());
|
||||
MD5Final(&md5);
|
||||
|
||||
ERR_FAIL_COND_V(String::md5(md5.digest) != String::md5(md5d), ERR_FILE_CORRUPT);
|
||||
|
||||
file = p_base;
|
||||
ERR_FAIL_COND_V(String::md5(md5.digest)!=String::md5(md5d),ERR_FILE_CORRUPT) ;
|
||||
|
||||
|
||||
file=p_base;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
Error FileAccessEncrypted::open_and_parse_password(FileAccess *p_base, const String &p_key, Mode p_mode) {
|
||||
Error FileAccessEncrypted::open_and_parse_password(FileAccess *p_base,const String& p_key,Mode p_mode){
|
||||
|
||||
|
||||
String cs = p_key.md5_text();
|
||||
ERR_FAIL_COND_V(cs.length() != 32, ERR_INVALID_PARAMETER);
|
||||
ERR_FAIL_COND_V(cs.length()!=32,ERR_INVALID_PARAMETER);
|
||||
Vector<uint8_t> key;
|
||||
key.resize(32);
|
||||
for (int i = 0; i < 32; i++) {
|
||||
for(int i=0;i<32;i++) {
|
||||
|
||||
key[i] = cs[i];
|
||||
key[i]=cs[i];
|
||||
}
|
||||
|
||||
return open_and_parse(p_base, key, p_mode);
|
||||
return open_and_parse(p_base,key,p_mode);
|
||||
}
|
||||
|
||||
Error FileAccessEncrypted::_open(const String &p_path, int p_mode_flags) {
|
||||
|
||||
|
||||
Error FileAccessEncrypted::_open(const String& p_path, int p_mode_flags) {
|
||||
|
||||
return OK;
|
||||
}
|
||||
@ -137,26 +137,26 @@ void FileAccessEncrypted::close() {
|
||||
Vector<uint8_t> compressed;
|
||||
size_t len = data.size();
|
||||
if (len % 16) {
|
||||
len += 16 - (len % 16);
|
||||
len+=16-(len % 16);
|
||||
}
|
||||
|
||||
MD5_CTX md5;
|
||||
MD5Init(&md5);
|
||||
MD5Update(&md5, (uint8_t *)data.ptr(), data.size());
|
||||
MD5Update(&md5,data.ptr(),data.size());
|
||||
MD5Final(&md5);
|
||||
|
||||
compressed.resize(len);
|
||||
zeromem(compressed.ptrw(), len);
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
compressed[i] = data[i];
|
||||
zeromem( compressed.ptr(), len );
|
||||
for(int i=0;i<data.size();i++) {
|
||||
compressed[i]=data[i];
|
||||
}
|
||||
|
||||
aes256_context ctx;
|
||||
aes256_init(&ctx, key.ptrw());
|
||||
aes256_init(&ctx,key.ptr());
|
||||
|
||||
for (size_t i = 0; i < len; i += 16) {
|
||||
for(size_t i=0;i<len;i+=16) {
|
||||
|
||||
aes256_encrypt_ecb(&ctx, &compressed[i]);
|
||||
aes256_encrypt_ecb(&ctx,&compressed[i]);
|
||||
}
|
||||
|
||||
aes256_done(&ctx);
|
||||
@ -164,13 +164,14 @@ void FileAccessEncrypted::close() {
|
||||
file->store_32(COMP_MAGIC);
|
||||
file->store_32(mode);
|
||||
|
||||
file->store_buffer(md5.digest, 16);
|
||||
|
||||
file->store_buffer(md5.digest,16);
|
||||
file->store_64(data.size());
|
||||
|
||||
file->store_buffer(compressed.ptr(), compressed.size());
|
||||
file->store_buffer(compressed.ptr(),compressed.size());
|
||||
file->close();
|
||||
memdelete(file);
|
||||
file = NULL;
|
||||
file=NULL;
|
||||
data.clear();
|
||||
|
||||
} else {
|
||||
@ -178,139 +179,143 @@ void FileAccessEncrypted::close() {
|
||||
file->close();
|
||||
memdelete(file);
|
||||
data.clear();
|
||||
file = NULL;
|
||||
file=NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool FileAccessEncrypted::is_open() const {
|
||||
bool FileAccessEncrypted::is_open() const{
|
||||
|
||||
return file != NULL;
|
||||
return file!=NULL;
|
||||
}
|
||||
|
||||
void FileAccessEncrypted::seek(size_t p_position) {
|
||||
void FileAccessEncrypted::seek(size_t p_position){
|
||||
|
||||
if (p_position > (size_t)data.size())
|
||||
p_position = data.size();
|
||||
p_position=data.size();
|
||||
|
||||
pos=p_position;
|
||||
eofed=false;
|
||||
|
||||
pos = p_position;
|
||||
eofed = false;
|
||||
}
|
||||
|
||||
void FileAccessEncrypted::seek_end(int64_t p_position) {
|
||||
|
||||
seek(data.size() + p_position);
|
||||
void FileAccessEncrypted::seek_end(int64_t p_position){
|
||||
|
||||
seek( data.size() + p_position );
|
||||
}
|
||||
size_t FileAccessEncrypted::get_position() const {
|
||||
size_t FileAccessEncrypted::get_pos() const{
|
||||
|
||||
return pos;
|
||||
}
|
||||
size_t FileAccessEncrypted::get_len() const {
|
||||
size_t FileAccessEncrypted::get_len() const{
|
||||
|
||||
return data.size();
|
||||
}
|
||||
|
||||
bool FileAccessEncrypted::eof_reached() const {
|
||||
bool FileAccessEncrypted::eof_reached() const{
|
||||
|
||||
return eofed;
|
||||
}
|
||||
|
||||
uint8_t FileAccessEncrypted::get_8() const {
|
||||
uint8_t FileAccessEncrypted::get_8() const{
|
||||
|
||||
ERR_FAIL_COND_V(writing, 0);
|
||||
if (pos >= data.size()) {
|
||||
eofed = true;
|
||||
ERR_FAIL_COND_V(writing,0);
|
||||
if (pos>=data.size()) {
|
||||
eofed=true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t b = data[pos];
|
||||
pos++;
|
||||
return b;
|
||||
|
||||
}
|
||||
int FileAccessEncrypted::get_buffer(uint8_t *p_dst, int p_length) const {
|
||||
int FileAccessEncrypted::get_buffer(uint8_t *p_dst, int p_length) const{
|
||||
|
||||
ERR_FAIL_COND_V(writing, 0);
|
||||
ERR_FAIL_COND_V(writing,0);
|
||||
|
||||
int to_copy = MIN(p_length, data.size() - pos);
|
||||
for (int i = 0; i < to_copy; i++) {
|
||||
int to_copy=MIN(p_length,data.size()-pos);
|
||||
for(int i=0;i<to_copy;i++) {
|
||||
|
||||
p_dst[i] = data[pos++];
|
||||
p_dst[i]=data[pos++];
|
||||
}
|
||||
|
||||
if (to_copy < p_length) {
|
||||
eofed = true;
|
||||
if (to_copy<p_length) {
|
||||
eofed=true;
|
||||
}
|
||||
|
||||
|
||||
return to_copy;
|
||||
}
|
||||
|
||||
Error FileAccessEncrypted::get_error() const {
|
||||
Error FileAccessEncrypted::get_error() const{
|
||||
|
||||
return eofed ? ERR_FILE_EOF : OK;
|
||||
return eofed?ERR_FILE_EOF:OK;
|
||||
}
|
||||
|
||||
void FileAccessEncrypted::store_buffer(const uint8_t *p_src, int p_length) {
|
||||
void FileAccessEncrypted::store_buffer(const uint8_t *p_src,int p_length) {
|
||||
|
||||
ERR_FAIL_COND(!writing);
|
||||
|
||||
if (pos < data.size()) {
|
||||
if (pos<data.size()) {
|
||||
|
||||
for (int i = 0; i < p_length; i++) {
|
||||
for(int i=0;i<p_length;i++) {
|
||||
|
||||
store_8(p_src[i]);
|
||||
}
|
||||
} else if (pos == data.size()) {
|
||||
} else if (pos==data.size()) {
|
||||
|
||||
data.resize(pos + p_length);
|
||||
for (int i = 0; i < p_length; i++) {
|
||||
data.resize(pos+p_length);
|
||||
for(int i=0;i<p_length;i++) {
|
||||
|
||||
data[pos + i] = p_src[i];
|
||||
data[pos+i]=p_src[i];
|
||||
}
|
||||
pos += p_length;
|
||||
pos+=p_length;
|
||||
}
|
||||
}
|
||||
|
||||
void FileAccessEncrypted::flush() {
|
||||
ERR_FAIL_COND(!writing);
|
||||
|
||||
// encrypted files keep data in memory till close()
|
||||
}
|
||||
|
||||
void FileAccessEncrypted::store_8(uint8_t p_dest) {
|
||||
void FileAccessEncrypted::store_8(uint8_t p_dest){
|
||||
|
||||
ERR_FAIL_COND(!writing);
|
||||
|
||||
if (pos < data.size()) {
|
||||
data[pos] = p_dest;
|
||||
if (pos<data.size()) {
|
||||
data[pos]=p_dest;
|
||||
pos++;
|
||||
} else if (pos == data.size()) {
|
||||
} else if (pos==data.size()){
|
||||
data.push_back(p_dest);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
bool FileAccessEncrypted::file_exists(const String &p_name) {
|
||||
bool FileAccessEncrypted::file_exists(const String& p_name){
|
||||
|
||||
FileAccess *fa = FileAccess::open(p_name, FileAccess::READ);
|
||||
FileAccess *fa = FileAccess::open(p_name,FileAccess::READ);
|
||||
if (!fa)
|
||||
return false;
|
||||
memdelete(fa);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t FileAccessEncrypted::_get_modified_time(const String &p_file) {
|
||||
uint64_t FileAccessEncrypted::_get_modified_time(const String& p_file){
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FileAccessEncrypted::FileAccessEncrypted() {
|
||||
|
||||
file = NULL;
|
||||
pos = 0;
|
||||
eofed = false;
|
||||
mode = MODE_MAX;
|
||||
writing = false;
|
||||
file=NULL;
|
||||
pos=0;
|
||||
eofed=false;
|
||||
mode=MODE_MAX;
|
||||
writing=false;
|
||||
}
|
||||
|
||||
|
||||
FileAccessEncrypted::~FileAccessEncrypted() {
|
||||
|
||||
if (file)
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,14 +26,15 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef FILE_ACCESS_ENCRYPTED_H
|
||||
#define FILE_ACCESS_ENCRYPTED_H
|
||||
|
||||
|
||||
#include "os/file_access.h"
|
||||
|
||||
class FileAccessEncrypted : public FileAccess {
|
||||
public:
|
||||
|
||||
enum Mode {
|
||||
MODE_READ,
|
||||
MODE_WRITE_AES256,
|
||||
@ -42,6 +42,8 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
|
||||
Mode mode;
|
||||
Vector<uint8_t> key;
|
||||
bool writing;
|
||||
@ -49,20 +51,25 @@ private:
|
||||
size_t base;
|
||||
size_t length;
|
||||
Vector<uint8_t> data;
|
||||
mutable int pos;
|
||||
mutable size_t pos;
|
||||
mutable bool eofed;
|
||||
|
||||
public:
|
||||
Error open_and_parse(FileAccess *p_base, const Vector<uint8_t> &p_key, Mode p_mode);
|
||||
Error open_and_parse_password(FileAccess *p_base, const String &p_key, Mode p_mode);
|
||||
|
||||
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
|
||||
public:
|
||||
|
||||
|
||||
|
||||
|
||||
Error open_and_parse(FileAccess *p_base,const Vector<uint8_t>& p_key,Mode p_mode);
|
||||
Error open_and_parse_password(FileAccess *p_base,const String& p_key,Mode p_mode);
|
||||
|
||||
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
|
||||
virtual void close(); ///< close a file
|
||||
virtual bool is_open() const; ///< true when file is open
|
||||
|
||||
virtual void seek(size_t p_position); ///< seek to a given position
|
||||
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
|
||||
virtual size_t get_position() const; ///< get position in the file
|
||||
virtual void seek_end(int64_t p_position=0); ///< seek from the end of file
|
||||
virtual size_t get_pos() const; ///< get position in the file
|
||||
virtual size_t get_len() const; ///< get size of the file
|
||||
|
||||
virtual bool eof_reached() const; ///< reading passed EOF
|
||||
@ -72,13 +79,12 @@ public:
|
||||
|
||||
virtual Error get_error() const; ///< get last error
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_dest); ///< store a byte
|
||||
virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes
|
||||
virtual void store_buffer(const uint8_t *p_src,int p_length); ///< store an array of bytes
|
||||
|
||||
virtual bool file_exists(const String &p_name); ///< return true if a file exists
|
||||
virtual bool file_exists(const String& p_name); ///< return true if a file exists
|
||||
|
||||
virtual uint64_t _get_modified_time(const String &p_file);
|
||||
virtual uint64_t _get_modified_time(const String& p_file);
|
||||
|
||||
FileAccessEncrypted();
|
||||
~FileAccessEncrypted();
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,15 +26,14 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "file_access_memory.h"
|
||||
|
||||
#include "map.h"
|
||||
#include "os/copymem.h"
|
||||
#include "os/dir_access.h"
|
||||
#include "project_settings.h"
|
||||
#include "os/copymem.h"
|
||||
#include "globals.h"
|
||||
#include "map.h"
|
||||
|
||||
static Map<String, Vector<uint8_t> > *files = NULL;
|
||||
static Map<String, Vector<uint8_t> >* files = NULL;
|
||||
|
||||
void FileAccessMemory::register_file(String p_name, Vector<uint8_t> p_data) {
|
||||
|
||||
@ -44,8 +42,8 @@ void FileAccessMemory::register_file(String p_name, Vector<uint8_t> p_data) {
|
||||
}
|
||||
|
||||
String name;
|
||||
if (ProjectSettings::get_singleton())
|
||||
name = ProjectSettings::get_singleton()->globalize_path(p_name);
|
||||
if (Globals::get_singleton())
|
||||
name = Globals::get_singleton()->globalize_path(p_name);
|
||||
else
|
||||
name = p_name;
|
||||
//name = DirAccess::normalize_path(name);
|
||||
@ -61,35 +59,37 @@ void FileAccessMemory::cleanup() {
|
||||
memdelete(files);
|
||||
}
|
||||
|
||||
FileAccess *FileAccessMemory::create() {
|
||||
|
||||
FileAccess* FileAccessMemory::create() {
|
||||
|
||||
return memnew(FileAccessMemory);
|
||||
}
|
||||
|
||||
bool FileAccessMemory::file_exists(const String &p_name) {
|
||||
bool FileAccessMemory::file_exists(const String& p_name) {
|
||||
|
||||
String name = fix_path(p_name);
|
||||
//name = DirAccess::normalize_path(name);
|
||||
// name = DirAccess::normalize_path(name);
|
||||
|
||||
return files && (files->find(name) != NULL);
|
||||
}
|
||||
|
||||
Error FileAccessMemory::open_custom(const uint8_t *p_data, int p_len) {
|
||||
|
||||
data = (uint8_t *)p_data;
|
||||
length = p_len;
|
||||
pos = 0;
|
||||
Error FileAccessMemory::open_custom(const uint8_t* p_data, int p_len) {
|
||||
|
||||
data=(uint8_t*)p_data;
|
||||
length=p_len;
|
||||
pos=0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
Error FileAccessMemory::_open(const String &p_path, int p_mode_flags) {
|
||||
Error FileAccessMemory::_open(const String& p_path, int p_mode_flags) {
|
||||
|
||||
ERR_FAIL_COND_V(!files, ERR_FILE_NOT_FOUND);
|
||||
|
||||
String name = fix_path(p_path);
|
||||
//name = DirAccess::normalize_path(name);
|
||||
// name = DirAccess::normalize_path(name);
|
||||
|
||||
Map<String, Vector<uint8_t> >::Element *E = files->find(name);
|
||||
Map<String, Vector<uint8_t> >::Element* E = files->find(name);
|
||||
ERR_FAIL_COND_V(!E, ERR_FILE_NOT_FOUND);
|
||||
|
||||
data = &(E->get()[0]);
|
||||
@ -121,7 +121,7 @@ void FileAccessMemory::seek_end(int64_t p_position) {
|
||||
pos = length + p_position;
|
||||
}
|
||||
|
||||
size_t FileAccessMemory::get_position() const {
|
||||
size_t FileAccessMemory::get_pos() const {
|
||||
|
||||
ERR_FAIL_COND_V(!data, 0);
|
||||
return pos;
|
||||
@ -149,7 +149,7 @@ uint8_t FileAccessMemory::get_8() const {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int FileAccessMemory::get_buffer(uint8_t *p_dst, int p_length) const {
|
||||
int FileAccessMemory::get_buffer(uint8_t *p_dst,int p_length) const {
|
||||
|
||||
ERR_FAIL_COND_V(!data, -1);
|
||||
|
||||
@ -171,10 +171,6 @@ Error FileAccessMemory::get_error() const {
|
||||
return pos >= length ? ERR_FILE_EOF : OK;
|
||||
}
|
||||
|
||||
void FileAccessMemory::flush() {
|
||||
ERR_FAIL_COND(!data);
|
||||
}
|
||||
|
||||
void FileAccessMemory::store_8(uint8_t p_byte) {
|
||||
|
||||
ERR_FAIL_COND(!data);
|
||||
@ -182,7 +178,7 @@ void FileAccessMemory::store_8(uint8_t p_byte) {
|
||||
data[pos++] = p_byte;
|
||||
}
|
||||
|
||||
void FileAccessMemory::store_buffer(const uint8_t *p_src, int p_length) {
|
||||
void FileAccessMemory::store_buffer(const uint8_t *p_src,int p_length) {
|
||||
|
||||
int left = length - pos;
|
||||
int write = MIN(p_length, left);
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,7 +26,6 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef FILE_ACCESS_MEMORY_H
|
||||
#define FILE_ACCESS_MEMORY_H
|
||||
|
||||
@ -35,41 +33,43 @@
|
||||
|
||||
class FileAccessMemory : public FileAccess {
|
||||
|
||||
uint8_t *data;
|
||||
uint8_t* data;
|
||||
int length;
|
||||
mutable int pos;
|
||||
|
||||
static FileAccess *create();
|
||||
static FileAccess* create();
|
||||
|
||||
public:
|
||||
|
||||
static void register_file(String p_name, Vector<uint8_t> p_data);
|
||||
static void cleanup();
|
||||
|
||||
virtual Error open_custom(const uint8_t *p_data, int p_len); ///< open a file
|
||||
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
|
||||
virtual Error open_custom(const uint8_t* p_data, int p_len); ///< open a file
|
||||
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
|
||||
virtual void close(); ///< close a file
|
||||
virtual bool is_open() const; ///< true when file is open
|
||||
|
||||
virtual void seek(size_t p_position); ///< seek to a given position
|
||||
virtual void seek_end(int64_t p_position); ///< seek from the end of file
|
||||
virtual size_t get_position() const; ///< get position in the file
|
||||
virtual size_t get_pos() const; ///< get position in the file
|
||||
virtual size_t get_len() const; ///< get size of the file
|
||||
|
||||
virtual bool eof_reached() const; ///< reading passed EOF
|
||||
|
||||
virtual uint8_t get_8() const; ///< get a byte
|
||||
|
||||
virtual int get_buffer(uint8_t *p_dst, int p_length) const; ///< get an array of bytes
|
||||
virtual int get_buffer(uint8_t *p_dst,int p_length) const; ///< get an array of bytes
|
||||
|
||||
virtual Error get_error() const; ///< get last error
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_byte); ///< store a byte
|
||||
virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes
|
||||
virtual void store_8(uint8_t p_dest); ///< store a byte
|
||||
virtual void store_buffer(const uint8_t *p_src,int p_length); ///< store an array of bytes
|
||||
|
||||
virtual bool file_exists(const String& p_name); ///< return true if a file exists
|
||||
|
||||
virtual uint64_t _get_modified_time(const String& p_file) { return 0; }
|
||||
|
||||
virtual bool file_exists(const String &p_name); ///< return true if a file exists
|
||||
|
||||
virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
|
||||
|
||||
FileAccessMemory();
|
||||
};
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,18 +26,20 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "file_access_network.h"
|
||||
#include "io/ip.h"
|
||||
#include "marshalls.h"
|
||||
#include "globals.h"
|
||||
#include "os/os.h"
|
||||
#include "project_settings.h"
|
||||
#include "io/ip.h"
|
||||
|
||||
|
||||
|
||||
//#define DEBUG_PRINT(m_p) print_line(m_p)
|
||||
//#define DEBUG_TIME(m_what) printf("MS: %s - %lli\n",m_what,OS::get_singleton()->get_ticks_usec());
|
||||
#define DEBUG_PRINT(m_p)
|
||||
#define DEBUG_TIME(m_what)
|
||||
|
||||
|
||||
void FileAccessNetworkClient::lock_mutex() {
|
||||
|
||||
mutex->lock();
|
||||
@ -49,57 +50,59 @@ void FileAccessNetworkClient::unlock_mutex() {
|
||||
|
||||
lockcount--;
|
||||
mutex->unlock();
|
||||
|
||||
}
|
||||
|
||||
void FileAccessNetworkClient::put_32(int p_32) {
|
||||
|
||||
uint8_t buf[4];
|
||||
encode_uint32(p_32, buf);
|
||||
client->put_data(buf, 4);
|
||||
DEBUG_PRINT("put32: " + itos(p_32));
|
||||
encode_uint32(p_32,buf);
|
||||
client->put_data(buf,4);
|
||||
DEBUG_PRINT("put32: "+itos(p_32));
|
||||
}
|
||||
|
||||
void FileAccessNetworkClient::put_64(int64_t p_64) {
|
||||
|
||||
uint8_t buf[8];
|
||||
encode_uint64(p_64, buf);
|
||||
client->put_data(buf, 8);
|
||||
DEBUG_PRINT("put64: " + itos(p_64));
|
||||
encode_uint64(p_64,buf);
|
||||
client->put_data(buf,8);
|
||||
DEBUG_PRINT("put64: "+itos(p_64));
|
||||
|
||||
}
|
||||
|
||||
int FileAccessNetworkClient::get_32() {
|
||||
|
||||
uint8_t buf[4];
|
||||
client->get_data(buf, 4);
|
||||
client->get_data(buf,4);
|
||||
return decode_uint32(buf);
|
||||
|
||||
}
|
||||
|
||||
int64_t FileAccessNetworkClient::get_64() {
|
||||
|
||||
uint8_t buf[8];
|
||||
client->get_data(buf, 8);
|
||||
client->get_data(buf,8);
|
||||
return decode_uint64(buf);
|
||||
|
||||
}
|
||||
|
||||
void FileAccessNetworkClient::_thread_func() {
|
||||
|
||||
client->set_no_delay(true);
|
||||
while (!quit) {
|
||||
client->set_nodelay(true);
|
||||
while(!quit) {
|
||||
|
||||
DEBUG_PRINT("SEM WAIT - " + itos(sem->get()));
|
||||
DEBUG_PRINT("SEM WAIT - "+itos(sem->get()));
|
||||
Error err = sem->wait();
|
||||
if (err != OK)
|
||||
ERR_PRINT("sem->wait() failed");
|
||||
DEBUG_TIME("sem_unlock");
|
||||
//DEBUG_PRINT("semwait returned "+itos(werr));
|
||||
DEBUG_PRINT("MUTEX LOCK " + itos(lockcount));
|
||||
DEBUG_PRINT("MUTEX LOCK "+itos(lockcount));
|
||||
DEBUG_PRINT("POPO");
|
||||
DEBUG_PRINT("PEPE");
|
||||
lock_mutex();
|
||||
DEBUG_PRINT("MUTEX PASS");
|
||||
|
||||
blockrequest_mutex->lock();
|
||||
while (block_requests.size()) {
|
||||
while(block_requests.size()) {
|
||||
put_32(block_requests.front()->get().id);
|
||||
put_32(FileAccessNetwork::COMMAND_READ_BLOCK);
|
||||
put_64(block_requests.front()->get().offset);
|
||||
@ -114,32 +117,35 @@ void FileAccessNetworkClient::_thread_func() {
|
||||
int id = get_32();
|
||||
|
||||
int response = get_32();
|
||||
DEBUG_PRINT("GET RESPONSE: " + itos(response));
|
||||
DEBUG_PRINT("GET RESPONSE: "+itos(response));
|
||||
|
||||
FileAccessNetwork *fa = NULL;
|
||||
FileAccessNetwork *fa=NULL;
|
||||
|
||||
if (response != FileAccessNetwork::RESPONSE_DATA) {
|
||||
if (response!=FileAccessNetwork::RESPONSE_DATA) {
|
||||
ERR_FAIL_COND(!accesses.has(id));
|
||||
}
|
||||
|
||||
if (accesses.has(id))
|
||||
fa = accesses[id];
|
||||
fa=accesses[id];
|
||||
|
||||
switch (response) {
|
||||
|
||||
switch(response) {
|
||||
|
||||
case FileAccessNetwork::RESPONSE_OPEN: {
|
||||
|
||||
|
||||
DEBUG_TIME("sem_open");
|
||||
int status = get_32();
|
||||
if (status != OK) {
|
||||
fa->_respond(0, Error(status));
|
||||
if (status!=OK) {
|
||||
fa->_respond(0,Error(status));
|
||||
} else {
|
||||
uint64_t len = get_64();
|
||||
fa->_respond(len, Error(status));
|
||||
fa->_respond(len,Error(status));
|
||||
}
|
||||
|
||||
fa->sem->post();
|
||||
|
||||
|
||||
} break;
|
||||
case FileAccessNetwork::RESPONSE_DATA: {
|
||||
|
||||
@ -148,95 +154,104 @@ void FileAccessNetworkClient::_thread_func() {
|
||||
|
||||
Vector<uint8_t> block;
|
||||
block.resize(len);
|
||||
client->get_data(block.ptrw(), len);
|
||||
client->get_data(block.ptr(),len);
|
||||
|
||||
if (fa) //may have been queued
|
||||
fa->_set_block(offset, block);
|
||||
fa->_set_block(offset,block);
|
||||
|
||||
} break;
|
||||
case FileAccessNetwork::RESPONSE_FILE_EXISTS: {
|
||||
|
||||
|
||||
int status = get_32();
|
||||
fa->exists_modtime = status != 0;
|
||||
fa->exists_modtime=status!=0;
|
||||
fa->sem->post();
|
||||
|
||||
|
||||
|
||||
} break;
|
||||
case FileAccessNetwork::RESPONSE_GET_MODTIME: {
|
||||
|
||||
|
||||
uint64_t status = get_64();
|
||||
fa->exists_modtime = status;
|
||||
fa->exists_modtime=status;
|
||||
fa->sem->post();
|
||||
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
unlock_mutex();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void FileAccessNetworkClient::_thread_func(void *s) {
|
||||
|
||||
FileAccessNetworkClient *self = (FileAccessNetworkClient *)s;
|
||||
FileAccessNetworkClient *self =(FileAccessNetworkClient*)s;
|
||||
|
||||
self->_thread_func();
|
||||
|
||||
}
|
||||
|
||||
Error FileAccessNetworkClient::connect(const String &p_host, int p_port, const String &p_password) {
|
||||
Error FileAccessNetworkClient::connect(const String& p_host,int p_port,const String& p_password) {
|
||||
|
||||
IP_Address ip;
|
||||
|
||||
if (p_host.is_valid_ip_address()) {
|
||||
ip = p_host;
|
||||
ip=p_host;
|
||||
} else {
|
||||
ip = IP::get_singleton()->resolve_hostname(p_host);
|
||||
ip=IP::get_singleton()->resolve_hostname(p_host);
|
||||
}
|
||||
|
||||
DEBUG_PRINT("IP: " + String(ip) + " port " + itos(p_port));
|
||||
Error err = client->connect_to_host(ip, p_port);
|
||||
ERR_FAIL_COND_V(err, err);
|
||||
while (client->get_status() == StreamPeerTCP::STATUS_CONNECTING) {
|
||||
//DEBUG_PRINT("trying to connect....");
|
||||
DEBUG_PRINT("IP: "+String(ip)+" port "+itos(p_port));
|
||||
Error err = client->connect(ip,p_port);
|
||||
ERR_FAIL_COND_V(err,err);
|
||||
while(client->get_status()==StreamPeerTCP::STATUS_CONNECTING) {
|
||||
//DEBUG_PRINT("trying to connect....");
|
||||
OS::get_singleton()->delay_usec(1000);
|
||||
}
|
||||
|
||||
if (client->get_status() != StreamPeerTCP::STATUS_CONNECTED) {
|
||||
if (client->get_status()!=StreamPeerTCP::STATUS_CONNECTED) {
|
||||
return ERR_CANT_CONNECT;
|
||||
}
|
||||
|
||||
CharString cs = p_password.utf8();
|
||||
put_32(cs.length());
|
||||
client->put_data((const uint8_t *)cs.ptr(), cs.length());
|
||||
client->put_data((const uint8_t*)cs.ptr(),cs.length());
|
||||
|
||||
int e = get_32();
|
||||
|
||||
if (e != OK) {
|
||||
if (e!=OK) {
|
||||
return ERR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
thread = Thread::create(_thread_func, this);
|
||||
thread = Thread::create(_thread_func,this);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
FileAccessNetworkClient *FileAccessNetworkClient::singleton = NULL;
|
||||
FileAccessNetworkClient *FileAccessNetworkClient::singleton=NULL;
|
||||
|
||||
|
||||
FileAccessNetworkClient::FileAccessNetworkClient() {
|
||||
|
||||
thread = NULL;
|
||||
thread=NULL;
|
||||
mutex = Mutex::create();
|
||||
blockrequest_mutex = Mutex::create();
|
||||
quit = false;
|
||||
singleton = this;
|
||||
last_id = 0;
|
||||
client = Ref<StreamPeerTCP>(StreamPeerTCP::create_ref());
|
||||
sem = Semaphore::create();
|
||||
lockcount = 0;
|
||||
quit=false;
|
||||
singleton=this;
|
||||
last_id=0;
|
||||
client = Ref<StreamPeerTCP>( StreamPeerTCP::create_ref() );
|
||||
sem=Semaphore::create();
|
||||
lockcount=0;
|
||||
}
|
||||
|
||||
FileAccessNetworkClient::~FileAccessNetworkClient() {
|
||||
|
||||
if (thread) {
|
||||
quit = true;
|
||||
quit=true;
|
||||
sem->post();
|
||||
Thread::wait_to_finish(thread);
|
||||
memdelete(thread);
|
||||
@ -245,64 +260,72 @@ FileAccessNetworkClient::~FileAccessNetworkClient() {
|
||||
memdelete(blockrequest_mutex);
|
||||
memdelete(mutex);
|
||||
memdelete(sem);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void FileAccessNetwork::_set_block(int p_offset, const Vector<uint8_t> &p_block) {
|
||||
void FileAccessNetwork::_set_block(size_t p_offset,const Vector<uint8_t>& p_block) {
|
||||
|
||||
int page = p_offset / page_size;
|
||||
ERR_FAIL_INDEX(page, pages.size());
|
||||
if (page < pages.size() - 1) {
|
||||
ERR_FAIL_COND(p_block.size() != page_size);
|
||||
|
||||
int page = p_offset/page_size;
|
||||
ERR_FAIL_INDEX(page,pages.size());
|
||||
if (page<pages.size()-1) {
|
||||
ERR_FAIL_COND(p_block.size()!=page_size);
|
||||
} else {
|
||||
ERR_FAIL_COND((p_block.size() != (int)(total_size % page_size)));
|
||||
ERR_FAIL_COND( (p_block.size() != (total_size%page_size)));
|
||||
}
|
||||
|
||||
buffer_mutex->lock();
|
||||
pages[page].buffer = p_block;
|
||||
pages[page].queued = false;
|
||||
pages[page].buffer=p_block;
|
||||
pages[page].queued=false;
|
||||
buffer_mutex->unlock();
|
||||
|
||||
if (waiting_on_page == page) {
|
||||
waiting_on_page = -1;
|
||||
if (waiting_on_page==page) {
|
||||
waiting_on_page=-1;
|
||||
page_sem->post();
|
||||
}
|
||||
}
|
||||
|
||||
void FileAccessNetwork::_respond(size_t p_len, Error p_status) {
|
||||
|
||||
DEBUG_PRINT("GOT RESPONSE - len: " + itos(p_len) + " status: " + itos(p_status));
|
||||
response = p_status;
|
||||
if (response != OK)
|
||||
void FileAccessNetwork::_respond(size_t p_len,Error p_status) {
|
||||
|
||||
DEBUG_PRINT("GOT RESPONSE - len: "+itos(p_len)+" status: "+itos(p_status));
|
||||
response=p_status;
|
||||
if (response!=OK)
|
||||
return;
|
||||
opened = true;
|
||||
total_size = p_len;
|
||||
int pc = ((total_size - 1) / page_size) + 1;
|
||||
opened=true;
|
||||
total_size=p_len;
|
||||
int pc = ((total_size-1)/page_size)+1;
|
||||
pages.resize(pc);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Error FileAccessNetwork::_open(const String &p_path, int p_mode_flags) {
|
||||
Error FileAccessNetwork::_open(const String& p_path, int p_mode_flags) {
|
||||
|
||||
ERR_FAIL_COND_V(p_mode_flags != READ, ERR_UNAVAILABLE);
|
||||
ERR_FAIL_COND_V(p_mode_flags!=READ,ERR_UNAVAILABLE);
|
||||
if (opened)
|
||||
close();
|
||||
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
|
||||
DEBUG_PRINT("open: " + p_path);
|
||||
DEBUG_PRINT("open: "+p_path);
|
||||
|
||||
DEBUG_TIME("open_begin");
|
||||
|
||||
nc->lock_mutex();
|
||||
nc->put_32(id);
|
||||
nc->accesses[id] = this;
|
||||
nc->accesses[id]=this;
|
||||
nc->put_32(COMMAND_OPEN_FILE);
|
||||
CharString cs = p_path.utf8();
|
||||
CharString cs =p_path.utf8();
|
||||
nc->put_32(cs.length());
|
||||
nc->client->put_data((const uint8_t *)cs.ptr(), cs.length());
|
||||
pos = 0;
|
||||
eof_flag = false;
|
||||
last_page = -1;
|
||||
last_page_buff = NULL;
|
||||
nc->client->put_data((const uint8_t*)cs.ptr(),cs.length());
|
||||
pos=0;
|
||||
eof_flag=false;
|
||||
last_page=-1;
|
||||
last_page_buff=NULL;
|
||||
|
||||
//buffers.clear();
|
||||
// buffers.clear();
|
||||
nc->unlock_mutex();
|
||||
DEBUG_PRINT("OPEN POST");
|
||||
DEBUG_TIME("open_post");
|
||||
@ -315,7 +338,7 @@ Error FileAccessNetwork::_open(const String &p_path, int p_mode_flags) {
|
||||
return response;
|
||||
}
|
||||
|
||||
void FileAccessNetwork::close() {
|
||||
void FileAccessNetwork::close(){
|
||||
|
||||
if (!opened)
|
||||
return;
|
||||
@ -327,101 +350,110 @@ void FileAccessNetwork::close() {
|
||||
nc->put_32(id);
|
||||
nc->put_32(COMMAND_CLOSE);
|
||||
pages.clear();
|
||||
opened = false;
|
||||
opened=false;
|
||||
nc->unlock_mutex();
|
||||
|
||||
|
||||
}
|
||||
bool FileAccessNetwork::is_open() const {
|
||||
bool FileAccessNetwork::is_open() const{
|
||||
|
||||
return opened;
|
||||
}
|
||||
|
||||
void FileAccessNetwork::seek(size_t p_position) {
|
||||
void FileAccessNetwork::seek(size_t p_position){
|
||||
|
||||
ERR_FAIL_COND(!opened);
|
||||
eof_flag = p_position > total_size;
|
||||
eof_flag=p_position>total_size;
|
||||
|
||||
if (p_position >= total_size) {
|
||||
p_position = total_size;
|
||||
if (p_position>=total_size) {
|
||||
p_position=total_size;
|
||||
}
|
||||
|
||||
pos = p_position;
|
||||
pos=p_position;
|
||||
}
|
||||
|
||||
void FileAccessNetwork::seek_end(int64_t p_position) {
|
||||
void FileAccessNetwork::seek_end(int64_t p_position){
|
||||
|
||||
seek(total_size+p_position);
|
||||
|
||||
seek(total_size + p_position);
|
||||
}
|
||||
size_t FileAccessNetwork::get_position() const {
|
||||
size_t FileAccessNetwork::get_pos() const{
|
||||
|
||||
ERR_FAIL_COND_V(!opened, 0);
|
||||
ERR_FAIL_COND_V(!opened,0);
|
||||
return pos;
|
||||
}
|
||||
size_t FileAccessNetwork::get_len() const {
|
||||
size_t FileAccessNetwork::get_len() const{
|
||||
|
||||
ERR_FAIL_COND_V(!opened, 0);
|
||||
ERR_FAIL_COND_V(!opened,0);
|
||||
return total_size;
|
||||
}
|
||||
|
||||
bool FileAccessNetwork::eof_reached() const {
|
||||
bool FileAccessNetwork::eof_reached() const{
|
||||
|
||||
ERR_FAIL_COND_V(!opened, false);
|
||||
ERR_FAIL_COND_V(!opened,false);
|
||||
return eof_flag;
|
||||
}
|
||||
|
||||
uint8_t FileAccessNetwork::get_8() const {
|
||||
uint8_t FileAccessNetwork::get_8() const{
|
||||
|
||||
uint8_t v;
|
||||
get_buffer(&v, 1);
|
||||
get_buffer(&v,1);
|
||||
return v;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void FileAccessNetwork::_queue_page(int p_page) const {
|
||||
|
||||
if (p_page >= pages.size())
|
||||
if (p_page>=pages.size())
|
||||
return;
|
||||
if (pages[p_page].buffer.empty() && !pages[p_page].queued) {
|
||||
|
||||
|
||||
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
|
||||
|
||||
nc->blockrequest_mutex->lock();
|
||||
FileAccessNetworkClient::BlockRequest br;
|
||||
br.id = id;
|
||||
br.offset = size_t(p_page) * page_size;
|
||||
br.size = page_size;
|
||||
br.id=id;
|
||||
br.offset=size_t(p_page)*page_size;
|
||||
br.size=page_size;
|
||||
nc->block_requests.push_back(br);
|
||||
pages[p_page].queued = true;
|
||||
pages[p_page].queued=true;
|
||||
nc->blockrequest_mutex->unlock();
|
||||
DEBUG_PRINT("QUEUE PAGE POST");
|
||||
nc->sem->post();
|
||||
DEBUG_PRINT("queued " + itos(p_page));
|
||||
DEBUG_PRINT("queued "+itos(p_page));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const {
|
||||
int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const{
|
||||
|
||||
//bool eof=false;
|
||||
if (pos + p_length > total_size) {
|
||||
eof_flag = true;
|
||||
if (pos+p_length>total_size) {
|
||||
eof_flag=true;
|
||||
}
|
||||
if (pos + p_length >= total_size) {
|
||||
p_length = total_size - pos;
|
||||
if (pos+p_length>=total_size) {
|
||||
p_length=total_size-pos;
|
||||
}
|
||||
|
||||
//FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
|
||||
// FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
|
||||
|
||||
uint8_t *buff = last_page_buff;
|
||||
uint8_t *buff=last_page_buff;
|
||||
|
||||
for (int i = 0; i < p_length; i++) {
|
||||
for(int i=0;i<p_length;i++) {
|
||||
|
||||
int page = pos / page_size;
|
||||
int page=pos/page_size;
|
||||
|
||||
if (page != last_page) {
|
||||
if (page!=last_page) {
|
||||
buffer_mutex->lock();
|
||||
if (pages[page].buffer.empty()) {
|
||||
waiting_on_page = page;
|
||||
for (int j = 0; j < read_ahead; j++) {
|
||||
//fuck
|
||||
|
||||
_queue_page(page + j);
|
||||
waiting_on_page=page;
|
||||
for(int j=0;j<read_ahead;j++) {
|
||||
|
||||
_queue_page(page+j);
|
||||
}
|
||||
buffer_mutex->unlock();
|
||||
DEBUG_PRINT("wait");
|
||||
@ -429,34 +461,30 @@ int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const {
|
||||
DEBUG_PRINT("done");
|
||||
} else {
|
||||
|
||||
for (int j = 0; j < read_ahead; j++) {
|
||||
for(int j=0;j<read_ahead;j++) {
|
||||
|
||||
_queue_page(page + j);
|
||||
_queue_page(page+j);
|
||||
}
|
||||
buff = pages[page].buffer.ptrw();
|
||||
buff=pages[page].buffer.ptr();
|
||||
//queue pages
|
||||
buffer_mutex->unlock();
|
||||
}
|
||||
|
||||
buff = pages[page].buffer.ptrw();
|
||||
last_page_buff = buff;
|
||||
last_page = page;
|
||||
buff=pages[page].buffer.ptr();
|
||||
last_page_buff=buff;
|
||||
last_page=page;
|
||||
}
|
||||
|
||||
p_dst[i] = buff[pos - uint64_t(page) * page_size];
|
||||
p_dst[i]=buff[pos-uint64_t(page)*page_size];
|
||||
pos++;
|
||||
}
|
||||
|
||||
return p_length;
|
||||
}
|
||||
|
||||
Error FileAccessNetwork::get_error() const {
|
||||
Error FileAccessNetwork::get_error() const{
|
||||
|
||||
return pos == total_size ? ERR_FILE_EOF : OK;
|
||||
}
|
||||
|
||||
void FileAccessNetwork::flush() {
|
||||
ERR_FAIL();
|
||||
return pos==total_size?ERR_FILE_EOF:OK;
|
||||
}
|
||||
|
||||
void FileAccessNetwork::store_8(uint8_t p_dest) {
|
||||
@ -464,66 +492,63 @@ void FileAccessNetwork::store_8(uint8_t p_dest) {
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
bool FileAccessNetwork::file_exists(const String &p_path) {
|
||||
bool FileAccessNetwork::file_exists(const String& p_path){
|
||||
|
||||
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
|
||||
nc->lock_mutex();
|
||||
nc->put_32(id);
|
||||
nc->put_32(COMMAND_FILE_EXISTS);
|
||||
CharString cs = p_path.utf8();
|
||||
CharString cs=p_path.utf8();
|
||||
nc->put_32(cs.length());
|
||||
nc->client->put_data((const uint8_t *)cs.ptr(), cs.length());
|
||||
nc->client->put_data((const uint8_t*)cs.ptr(),cs.length());
|
||||
nc->unlock_mutex();
|
||||
DEBUG_PRINT("FILE EXISTS POST");
|
||||
nc->sem->post();
|
||||
sem->wait();
|
||||
|
||||
return exists_modtime != 0;
|
||||
return exists_modtime!=0;
|
||||
|
||||
}
|
||||
|
||||
uint64_t FileAccessNetwork::_get_modified_time(const String &p_file) {
|
||||
uint64_t FileAccessNetwork::_get_modified_time(const String& p_file){
|
||||
|
||||
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
|
||||
nc->lock_mutex();
|
||||
nc->put_32(id);
|
||||
nc->put_32(COMMAND_GET_MODTIME);
|
||||
CharString cs = p_file.utf8();
|
||||
CharString cs=p_file.utf8();
|
||||
nc->put_32(cs.length());
|
||||
nc->client->put_data((const uint8_t *)cs.ptr(), cs.length());
|
||||
nc->client->put_data((const uint8_t*)cs.ptr(),cs.length());
|
||||
nc->unlock_mutex();
|
||||
DEBUG_PRINT("MODTIME POST");
|
||||
nc->sem->post();
|
||||
sem->wait();
|
||||
|
||||
return exists_modtime;
|
||||
}
|
||||
|
||||
void FileAccessNetwork::configure() {
|
||||
|
||||
GLOBAL_DEF("network/remote_fs/page_size", 65536);
|
||||
GLOBAL_DEF("network/remote_fs/page_read_ahead", 4);
|
||||
GLOBAL_DEF("network/remote_fs/max_pages", 20);
|
||||
}
|
||||
|
||||
FileAccessNetwork::FileAccessNetwork() {
|
||||
|
||||
eof_flag = false;
|
||||
opened = false;
|
||||
pos = 0;
|
||||
sem = Semaphore::create();
|
||||
page_sem = Semaphore::create();
|
||||
buffer_mutex = Mutex::create();
|
||||
eof_flag=false;
|
||||
opened=false;
|
||||
pos=0;
|
||||
sem=Semaphore::create();
|
||||
page_sem=Semaphore::create();
|
||||
buffer_mutex=Mutex::create();
|
||||
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
|
||||
nc->lock_mutex();
|
||||
id = nc->last_id++;
|
||||
nc->accesses[id] = this;
|
||||
id=nc->last_id++;
|
||||
nc->accesses[id]=this;
|
||||
nc->unlock_mutex();
|
||||
page_size = GLOBAL_GET("network/remote_fs/page_size");
|
||||
read_ahead = GLOBAL_GET("network/remote_fs/page_read_ahead");
|
||||
max_pages = GLOBAL_GET("network/remote_fs/max_pages");
|
||||
last_activity_val = 0;
|
||||
waiting_on_page = -1;
|
||||
last_page = -1;
|
||||
page_size = GLOBAL_DEF("remote_fs/page_size",65536);
|
||||
read_ahead = GLOBAL_DEF("remote_fs/page_read_ahead",4);
|
||||
max_pages = GLOBAL_DEF("remote_fs/max_pages",20);
|
||||
last_activity_val=0;
|
||||
waiting_on_page=-1;
|
||||
last_page=-1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
FileAccessNetwork::~FileAccessNetwork() {
|
||||
@ -535,7 +560,8 @@ FileAccessNetwork::~FileAccessNetwork() {
|
||||
|
||||
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
|
||||
nc->lock_mutex();
|
||||
id = nc->last_id++;
|
||||
id=nc->last_id++;
|
||||
nc->accesses.erase(id);
|
||||
nc->unlock_mutex();
|
||||
|
||||
}
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,19 +26,19 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef FILE_ACCESS_NETWORK_H
|
||||
#define FILE_ACCESS_NETWORK_H
|
||||
|
||||
#include "io/stream_peer_tcp.h"
|
||||
#include "os/file_access.h"
|
||||
#include "os/semaphore.h"
|
||||
#include "os/thread.h"
|
||||
#include "io/stream_peer_tcp.h"
|
||||
|
||||
class FileAccessNetwork;
|
||||
|
||||
class FileAccessNetworkClient {
|
||||
|
||||
|
||||
struct BlockRequest {
|
||||
|
||||
int id;
|
||||
@ -56,7 +55,7 @@ class FileAccessNetworkClient {
|
||||
bool quit;
|
||||
Mutex *mutex;
|
||||
Mutex *blockrequest_mutex;
|
||||
Map<int, FileAccessNetwork *> accesses;
|
||||
Map<int,FileAccessNetwork*> accesses;
|
||||
Ref<StreamPeerTCP> client;
|
||||
int last_id;
|
||||
|
||||
@ -73,16 +72,18 @@ class FileAccessNetworkClient {
|
||||
void lock_mutex();
|
||||
void unlock_mutex();
|
||||
|
||||
friend class FileAccessNetwork;
|
||||
friend class FileAccessNetwork;
|
||||
static FileAccessNetworkClient *singleton;
|
||||
|
||||
public:
|
||||
|
||||
static FileAccessNetworkClient *get_singleton() { return singleton; }
|
||||
|
||||
Error connect(const String &p_host, int p_port, const String &p_password = "");
|
||||
Error connect(const String& p_host,int p_port,const String& p_password="");
|
||||
|
||||
FileAccessNetworkClient();
|
||||
~FileAccessNetworkClient();
|
||||
|
||||
};
|
||||
|
||||
class FileAccessNetwork : public FileAccess {
|
||||
@ -98,7 +99,7 @@ class FileAccessNetwork : public FileAccess {
|
||||
mutable int last_page;
|
||||
mutable uint8_t *last_page_buff;
|
||||
|
||||
int page_size;
|
||||
uint32_t page_size;
|
||||
int read_ahead;
|
||||
int max_pages;
|
||||
|
||||
@ -108,23 +109,21 @@ class FileAccessNetwork : public FileAccess {
|
||||
int activity;
|
||||
bool queued;
|
||||
Vector<uint8_t> buffer;
|
||||
Page() {
|
||||
activity = 0;
|
||||
queued = false;
|
||||
}
|
||||
Page() { activity=0; queued=false; }
|
||||
};
|
||||
|
||||
mutable Vector<Page> pages;
|
||||
mutable Vector< Page > pages;
|
||||
|
||||
mutable Error response;
|
||||
|
||||
uint64_t exists_modtime;
|
||||
friend class FileAccessNetworkClient;
|
||||
friend class FileAccessNetworkClient;
|
||||
void _queue_page(int p_page) const;
|
||||
void _respond(size_t p_len, Error p_status);
|
||||
void _set_block(int p_offset, const Vector<uint8_t> &p_block);
|
||||
void _respond(size_t p_len,Error p_status);
|
||||
void _set_block(size_t p_offset,const Vector<uint8_t>& p_block);
|
||||
|
||||
public:
|
||||
|
||||
enum Command {
|
||||
COMMAND_OPEN_FILE,
|
||||
COMMAND_READ_BLOCK,
|
||||
@ -140,13 +139,14 @@ public:
|
||||
RESPONSE_GET_MODTIME,
|
||||
};
|
||||
|
||||
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
|
||||
|
||||
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
|
||||
virtual void close(); ///< close a file
|
||||
virtual bool is_open() const; ///< true when file is open
|
||||
|
||||
virtual void seek(size_t p_position); ///< seek to a given position
|
||||
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
|
||||
virtual size_t get_position() const; ///< get position in the file
|
||||
virtual void seek_end(int64_t p_position=0); ///< seek from the end of file
|
||||
virtual size_t get_pos() const; ///< get position in the file
|
||||
virtual size_t get_len() const; ///< get size of the file
|
||||
|
||||
virtual bool eof_reached() const; ///< reading passed EOF
|
||||
@ -156,14 +156,11 @@ public:
|
||||
|
||||
virtual Error get_error() const; ///< get last error
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_dest); ///< store a byte
|
||||
|
||||
virtual bool file_exists(const String &p_path); ///< return true if a file exists
|
||||
virtual bool file_exists(const String& p_path); ///< return true if a file exists
|
||||
|
||||
virtual uint64_t _get_modified_time(const String &p_file);
|
||||
|
||||
static void configure();
|
||||
virtual uint64_t _get_modified_time(const String& p_file);
|
||||
|
||||
FileAccessNetwork();
|
||||
~FileAccessNetwork();
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,17 +26,16 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "file_access_pack.h"
|
||||
#include "version.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define PACK_VERSION 1
|
||||
#define PACK_VERSION 0
|
||||
|
||||
Error PackedData::add_pack(const String &p_path) {
|
||||
Error PackedData::add_pack(const String& p_path) {
|
||||
|
||||
for (int i = 0; i < sources.size(); i++) {
|
||||
for (int i=0; i<sources.size(); i++) {
|
||||
|
||||
if (sources[i]->try_open_pack(p_path)) {
|
||||
|
||||
@ -48,7 +46,7 @@ Error PackedData::add_pack(const String &p_path) {
|
||||
return ERR_FILE_UNRECOGNIZED;
|
||||
};
|
||||
|
||||
void PackedData::add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src) {
|
||||
void PackedData::add_path(const String& pkg_path, const String& path, uint64_t ofs, uint64_t size,const uint8_t* p_md5, PackSource* p_src) {
|
||||
|
||||
PathMD5 pmd5(path.md5_buffer());
|
||||
//printf("adding path %ls, %lli, %lli\n", path.c_str(), pmd5.a, pmd5.b);
|
||||
@ -56,43 +54,39 @@ void PackedData::add_path(const String &pkg_path, const String &path, uint64_t o
|
||||
bool exists = files.has(pmd5);
|
||||
|
||||
PackedFile pf;
|
||||
pf.pack = pkg_path;
|
||||
pf.offset = ofs;
|
||||
pf.size = size;
|
||||
for (int i = 0; i < 16; i++)
|
||||
pf.md5[i] = p_md5[i];
|
||||
pf.pack=pkg_path;
|
||||
pf.offset=ofs;
|
||||
pf.size=size;
|
||||
for(int i=0;i<16;i++)
|
||||
pf.md5[i]=p_md5[i];
|
||||
pf.src = p_src;
|
||||
|
||||
files[pmd5] = pf;
|
||||
files[pmd5]=pf;
|
||||
|
||||
if (!exists) {
|
||||
//search for dir
|
||||
String p = path.replace_first("res://", "");
|
||||
PackedDir *cd = root;
|
||||
String p = path.replace_first("res://","");
|
||||
PackedDir *cd=root;
|
||||
|
||||
if (p.find("/") != -1) { //in a subdir
|
||||
if (p.find("/")!=-1) { //in a subdir
|
||||
|
||||
Vector<String> ds = p.get_base_dir().split("/");
|
||||
Vector<String> ds=p.get_base_dir().split("/");
|
||||
|
||||
for (int j = 0; j < ds.size(); j++) {
|
||||
for(int j=0;j<ds.size();j++) {
|
||||
|
||||
if (!cd->subdirs.has(ds[j])) {
|
||||
|
||||
PackedDir *pd = memnew(PackedDir);
|
||||
pd->name = ds[j];
|
||||
pd->parent = cd;
|
||||
cd->subdirs[pd->name] = pd;
|
||||
cd = pd;
|
||||
PackedDir *pd = memnew( PackedDir );
|
||||
pd->name=ds[j];
|
||||
pd->parent=cd;
|
||||
cd->subdirs[pd->name]=pd;
|
||||
cd=pd;
|
||||
} else {
|
||||
cd = cd->subdirs[ds[j]];
|
||||
cd=cd->subdirs[ds[j]];
|
||||
}
|
||||
}
|
||||
}
|
||||
String filename = path.get_file();
|
||||
// Don't add as a file if the path points to a directoryy
|
||||
if (!filename.empty()) {
|
||||
cd->files.insert(filename);
|
||||
}
|
||||
cd->files.insert(path.get_file());
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,59 +97,61 @@ void PackedData::add_pack_source(PackSource *p_source) {
|
||||
}
|
||||
};
|
||||
|
||||
PackedData *PackedData::singleton = NULL;
|
||||
PackedData *PackedData::singleton=NULL;
|
||||
|
||||
PackedData::PackedData() {
|
||||
|
||||
singleton = this;
|
||||
root = memnew(PackedDir);
|
||||
root->parent = NULL;
|
||||
disabled = false;
|
||||
singleton=this;
|
||||
root=memnew(PackedDir);
|
||||
root->parent=NULL;
|
||||
disabled=false;
|
||||
|
||||
add_pack_source(memnew(PackedSourcePCK));
|
||||
}
|
||||
|
||||
void PackedData::_free_packed_dirs(PackedDir *p_dir) {
|
||||
|
||||
for (Map<String, PackedDir *>::Element *E = p_dir->subdirs.front(); E; E = E->next())
|
||||
for (Map<String,PackedDir*>::Element *E=p_dir->subdirs.front();E;E=E->next())
|
||||
_free_packed_dirs(E->get());
|
||||
memdelete(p_dir);
|
||||
}
|
||||
|
||||
PackedData::~PackedData() {
|
||||
|
||||
for (int i = 0; i < sources.size(); i++) {
|
||||
for(int i=0;i<sources.size();i++) {
|
||||
memdelete(sources[i]);
|
||||
}
|
||||
_free_packed_dirs(root);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
bool PackedSourcePCK::try_open_pack(const String &p_path) {
|
||||
bool PackedSourcePCK::try_open_pack(const String& p_path) {
|
||||
|
||||
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
|
||||
FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
//printf("try open %ls!\n", p_path.c_str());
|
||||
|
||||
uint32_t magic = f->get_32();
|
||||
uint32_t magic= f->get_32();
|
||||
|
||||
if (magic != 0x43504447) {
|
||||
//maybe at he end.... self contained exe
|
||||
f->seek_end();
|
||||
f->seek(f->get_position() - 4);
|
||||
f->seek( f->get_pos() -4 );
|
||||
magic = f->get_32();
|
||||
if (magic != 0x43504447) {
|
||||
|
||||
memdelete(f);
|
||||
return false;
|
||||
}
|
||||
f->seek(f->get_position() - 12);
|
||||
f->seek( f->get_pos() -12 );
|
||||
|
||||
|
||||
uint64_t ds = f->get_64();
|
||||
f->seek(f->get_position() - ds - 8);
|
||||
f->seek( f->get_pos() -ds-8 );
|
||||
|
||||
magic = f->get_32();
|
||||
if (magic != 0x43504447) {
|
||||
@ -163,6 +159,7 @@ bool PackedSourcePCK::try_open_pack(const String &p_path) {
|
||||
memdelete(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint32_t version = f->get_32();
|
||||
@ -170,25 +167,25 @@ bool PackedSourcePCK::try_open_pack(const String &p_path) {
|
||||
uint32_t ver_minor = f->get_32();
|
||||
uint32_t ver_rev = f->get_32();
|
||||
|
||||
ERR_EXPLAIN("Pack version unsupported: " + itos(version));
|
||||
ERR_FAIL_COND_V(version != PACK_VERSION, false);
|
||||
ERR_EXPLAIN("Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor) + "." + itos(ver_rev));
|
||||
ERR_FAIL_COND_V(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), false);
|
||||
ERR_EXPLAIN("Pack version newer than supported by engine: "+itos(version));
|
||||
ERR_FAIL_COND_V( version > PACK_VERSION, ERR_INVALID_DATA);
|
||||
ERR_EXPLAIN("Pack created with a newer version of the engine: "+itos(ver_major)+"."+itos(ver_minor)+"."+itos(ver_rev));
|
||||
ERR_FAIL_COND_V( ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), ERR_INVALID_DATA);
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
for(int i=0;i<16;i++) {
|
||||
//reserved
|
||||
f->get_32();
|
||||
}
|
||||
|
||||
int file_count = f->get_32();
|
||||
|
||||
for (int i = 0; i < file_count; i++) {
|
||||
for(int i=0;i<file_count;i++) {
|
||||
|
||||
uint32_t sl = f->get_32();
|
||||
CharString cs;
|
||||
cs.resize(sl + 1);
|
||||
f->get_buffer((uint8_t *)cs.ptr(), sl);
|
||||
cs[sl] = 0;
|
||||
cs.resize(sl+1);
|
||||
f->get_buffer((uint8_t*)cs.ptr(),sl);
|
||||
cs[sl]=0;
|
||||
|
||||
String path;
|
||||
path.parse_utf8(cs.ptr());
|
||||
@ -196,21 +193,22 @@ bool PackedSourcePCK::try_open_pack(const String &p_path) {
|
||||
uint64_t ofs = f->get_64();
|
||||
uint64_t size = f->get_64();
|
||||
uint8_t md5[16];
|
||||
f->get_buffer(md5, 16);
|
||||
PackedData::get_singleton()->add_path(p_path, path, ofs, size, md5, this);
|
||||
f->get_buffer(md5,16);
|
||||
PackedData::get_singleton()->add_path(p_path, path, ofs, size, md5,this);
|
||||
};
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
FileAccess *PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile *p_file) {
|
||||
FileAccess* PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile* p_file) {
|
||||
|
||||
return memnew(FileAccessPack(p_path, *p_file));
|
||||
return memnew( FileAccessPack(p_path, *p_file));
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
Error FileAccessPack::_open(const String &p_path, int p_mode_flags) {
|
||||
|
||||
Error FileAccessPack::_open(const String& p_path, int p_mode_flags) {
|
||||
|
||||
ERR_FAIL_V(ERR_UNAVAILABLE);
|
||||
return ERR_UNAVAILABLE;
|
||||
@ -221,44 +219,45 @@ void FileAccessPack::close() {
|
||||
f->close();
|
||||
}
|
||||
|
||||
bool FileAccessPack::is_open() const {
|
||||
bool FileAccessPack::is_open() const{
|
||||
|
||||
return f->is_open();
|
||||
}
|
||||
|
||||
void FileAccessPack::seek(size_t p_position) {
|
||||
void FileAccessPack::seek(size_t p_position){
|
||||
|
||||
if (p_position > pf.size) {
|
||||
eof = true;
|
||||
if (p_position>pf.size) {
|
||||
eof=true;
|
||||
} else {
|
||||
eof = false;
|
||||
eof=false;
|
||||
}
|
||||
|
||||
f->seek(pf.offset + p_position);
|
||||
pos = p_position;
|
||||
f->seek(pf.offset+p_position);
|
||||
pos=p_position;
|
||||
}
|
||||
void FileAccessPack::seek_end(int64_t p_position) {
|
||||
void FileAccessPack::seek_end(int64_t p_position){
|
||||
|
||||
seek(pf.size+p_position);
|
||||
|
||||
seek(pf.size + p_position);
|
||||
}
|
||||
size_t FileAccessPack::get_position() const {
|
||||
size_t FileAccessPack::get_pos() const {
|
||||
|
||||
return pos;
|
||||
}
|
||||
size_t FileAccessPack::get_len() const {
|
||||
size_t FileAccessPack::get_len() const{
|
||||
|
||||
return pf.size;
|
||||
}
|
||||
|
||||
bool FileAccessPack::eof_reached() const {
|
||||
bool FileAccessPack::eof_reached() const{
|
||||
|
||||
return eof;
|
||||
}
|
||||
|
||||
uint8_t FileAccessPack::get_8() const {
|
||||
|
||||
if (pos >= pf.size) {
|
||||
eof = true;
|
||||
if (pos>=pf.size) {
|
||||
eof=true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -266,22 +265,23 @@ uint8_t FileAccessPack::get_8() const {
|
||||
return f->get_8();
|
||||
}
|
||||
|
||||
int FileAccessPack::get_buffer(uint8_t *p_dst, int p_length) const {
|
||||
|
||||
int FileAccessPack::get_buffer(uint8_t *p_dst,int p_length) const {
|
||||
|
||||
if (eof)
|
||||
return 0;
|
||||
|
||||
int64_t to_read = p_length;
|
||||
if (to_read + pos > pf.size) {
|
||||
eof = true;
|
||||
to_read = int64_t(pf.size) - int64_t(pos);
|
||||
int64_t to_read=p_length;
|
||||
if (to_read+pos > pf.size) {
|
||||
eof=true;
|
||||
to_read=int64_t(pf.size)-int64_t(pos);
|
||||
}
|
||||
|
||||
pos += p_length;
|
||||
pos+=p_length;
|
||||
|
||||
if (to_read <= 0)
|
||||
if (to_read<=0)
|
||||
return 0;
|
||||
f->get_buffer(p_dst, to_read);
|
||||
f->get_buffer(p_dst,to_read);
|
||||
|
||||
return to_read;
|
||||
}
|
||||
@ -298,36 +298,35 @@ Error FileAccessPack::get_error() const {
|
||||
return OK;
|
||||
}
|
||||
|
||||
void FileAccessPack::flush() {
|
||||
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
void FileAccessPack::store_8(uint8_t p_dest) {
|
||||
|
||||
ERR_FAIL();
|
||||
|
||||
}
|
||||
|
||||
void FileAccessPack::store_buffer(const uint8_t *p_src, int p_length) {
|
||||
void FileAccessPack::store_buffer(const uint8_t *p_src,int p_length) {
|
||||
|
||||
ERR_FAIL();
|
||||
|
||||
}
|
||||
|
||||
bool FileAccessPack::file_exists(const String &p_name) {
|
||||
bool FileAccessPack::file_exists(const String& p_name) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file) :
|
||||
pf(p_file),
|
||||
f(FileAccess::open(pf.pack, FileAccess::READ)) {
|
||||
|
||||
FileAccessPack::FileAccessPack(const String& p_path, const PackedData::PackedFile& p_file) {
|
||||
|
||||
pf=p_file;
|
||||
f=FileAccess::open(pf.pack,FileAccess::READ);
|
||||
if (!f) {
|
||||
ERR_EXPLAIN("Can't open pack-referenced file: " + String(pf.pack));
|
||||
ERR_EXPLAIN("Can't open pack-referenced file: "+String(pf.pack));
|
||||
ERR_FAIL_COND(!f);
|
||||
}
|
||||
f->seek(pf.offset);
|
||||
pos = 0;
|
||||
eof = false;
|
||||
pos=0;
|
||||
eof=false;
|
||||
}
|
||||
|
||||
FileAccessPack::~FileAccessPack() {
|
||||
@ -335,37 +334,40 @@ FileAccessPack::~FileAccessPack() {
|
||||
memdelete(f);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// DIR ACCESS
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Error DirAccessPack::list_dir_begin() {
|
||||
|
||||
bool DirAccessPack::list_dir_begin() {
|
||||
|
||||
|
||||
list_dirs.clear();
|
||||
list_files.clear();
|
||||
|
||||
for (Map<String, PackedData::PackedDir *>::Element *E = current->subdirs.front(); E; E = E->next()) {
|
||||
for (Map<String,PackedData::PackedDir*>::Element *E=current->subdirs.front();E;E=E->next()) {
|
||||
|
||||
list_dirs.push_back(E->key());
|
||||
}
|
||||
|
||||
for (Set<String>::Element *E = current->files.front(); E; E = E->next()) {
|
||||
for (Set<String>::Element *E=current->files.front();E;E=E->next()) {
|
||||
|
||||
list_files.push_back(E->get());
|
||||
}
|
||||
|
||||
return OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
String DirAccessPack::get_next() {
|
||||
String DirAccessPack::get_next(){
|
||||
|
||||
if (list_dirs.size()) {
|
||||
cdir = true;
|
||||
cdir=true;
|
||||
String d = list_dirs.front()->get();
|
||||
list_dirs.pop_front();
|
||||
return d;
|
||||
} else if (list_files.size()) {
|
||||
cdir = false;
|
||||
cdir=false;
|
||||
String f = list_files.front()->get();
|
||||
list_files.pop_front();
|
||||
return f;
|
||||
@ -373,11 +375,11 @@ String DirAccessPack::get_next() {
|
||||
return String();
|
||||
}
|
||||
}
|
||||
bool DirAccessPack::current_is_dir() const {
|
||||
bool DirAccessPack::current_is_dir() const{
|
||||
|
||||
return cdir;
|
||||
}
|
||||
bool DirAccessPack::current_is_hidden() const {
|
||||
bool DirAccessPack::current_is_hidden() const{
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -398,20 +400,18 @@ String DirAccessPack::get_drive(int p_drive) {
|
||||
|
||||
Error DirAccessPack::change_dir(String p_dir) {
|
||||
|
||||
String nd = p_dir.replace("\\", "/");
|
||||
bool absolute = false;
|
||||
String nd = p_dir.replace("\\","/");
|
||||
bool absolute=false;
|
||||
if (nd.begins_with("res://")) {
|
||||
nd = nd.replace_first("res://", "");
|
||||
absolute = true;
|
||||
nd=nd.replace_first("res://","");
|
||||
absolute=true;
|
||||
}
|
||||
|
||||
nd = nd.simplify_path();
|
||||
|
||||
if (nd == "") nd = ".";
|
||||
nd=nd.simplify_path();
|
||||
|
||||
if (nd.begins_with("/")) {
|
||||
nd = nd.replace_first("/", "");
|
||||
absolute = true;
|
||||
nd=nd.replace_first("/","") ;
|
||||
absolute=true;
|
||||
}
|
||||
|
||||
Vector<String> paths = nd.split("/");
|
||||
@ -423,18 +423,18 @@ Error DirAccessPack::change_dir(String p_dir) {
|
||||
else
|
||||
pd = current;
|
||||
|
||||
for (int i = 0; i < paths.size(); i++) {
|
||||
for(int i=0;i<paths.size();i++) {
|
||||
|
||||
String p = paths[i];
|
||||
if (p == ".") {
|
||||
if (p==".") {
|
||||
continue;
|
||||
} else if (p == "..") {
|
||||
} else if (p=="..") {
|
||||
if (pd->parent) {
|
||||
pd = pd->parent;
|
||||
pd=pd->parent;
|
||||
}
|
||||
} else if (pd->subdirs.has(p)) {
|
||||
|
||||
pd = pd->subdirs[p];
|
||||
pd=pd->subdirs[p];
|
||||
|
||||
} else {
|
||||
|
||||
@ -442,25 +442,29 @@ Error DirAccessPack::change_dir(String p_dir) {
|
||||
}
|
||||
}
|
||||
|
||||
current = pd;
|
||||
current=pd;
|
||||
|
||||
return OK;
|
||||
|
||||
|
||||
}
|
||||
|
||||
String DirAccessPack::get_current_dir() {
|
||||
|
||||
String p;
|
||||
PackedData::PackedDir *pd = current;
|
||||
String p = current->name;
|
||||
while(pd->parent) {
|
||||
|
||||
while (pd->parent) {
|
||||
pd = pd->parent;
|
||||
p = pd->name + "/" + p;
|
||||
if (pd!=current)
|
||||
p="/"+p;
|
||||
p=p+pd->name;
|
||||
}
|
||||
|
||||
return "res://" + p;
|
||||
return "res://"+p;
|
||||
|
||||
}
|
||||
|
||||
bool DirAccessPack::file_exists(String p_file) {
|
||||
bool DirAccessPack::file_exists(String p_file){
|
||||
|
||||
return current->files.has(p_file);
|
||||
}
|
||||
@ -470,30 +474,36 @@ bool DirAccessPack::dir_exists(String p_dir) {
|
||||
return current->subdirs.has(p_dir);
|
||||
}
|
||||
|
||||
Error DirAccessPack::make_dir(String p_dir) {
|
||||
Error DirAccessPack::make_dir(String p_dir){
|
||||
|
||||
return ERR_UNAVAILABLE;
|
||||
}
|
||||
|
||||
Error DirAccessPack::rename(String p_from, String p_to) {
|
||||
Error DirAccessPack::rename(String p_from, String p_to){
|
||||
|
||||
return ERR_UNAVAILABLE;
|
||||
|
||||
}
|
||||
Error DirAccessPack::remove(String p_name) {
|
||||
Error DirAccessPack::remove(String p_name){
|
||||
|
||||
return ERR_UNAVAILABLE;
|
||||
|
||||
}
|
||||
|
||||
size_t DirAccessPack::get_space_left() {
|
||||
size_t DirAccessPack::get_space_left(){
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DirAccessPack::DirAccessPack() {
|
||||
|
||||
current = PackedData::get_singleton()->root;
|
||||
cdir = false;
|
||||
current=PackedData::get_singleton()->root;
|
||||
cdir=false;
|
||||
}
|
||||
|
||||
DirAccessPack::~DirAccessPack() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,22 +26,21 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef FILE_ACCESS_PACK_H
|
||||
#define FILE_ACCESS_PACK_H
|
||||
|
||||
#include "list.h"
|
||||
#include "map.h"
|
||||
#include "os/dir_access.h"
|
||||
#include "os/file_access.h"
|
||||
#include "os/dir_access.h"
|
||||
#include "map.h"
|
||||
#include "list.h"
|
||||
#include "print_string.h"
|
||||
|
||||
class PackSource;
|
||||
|
||||
class PackedData {
|
||||
friend class FileAccessPack;
|
||||
friend class DirAccessPack;
|
||||
friend class PackSource;
|
||||
friend class FileAccessPack;
|
||||
friend class DirAccessPack;
|
||||
friend class PackSource;
|
||||
|
||||
public:
|
||||
struct PackedFile {
|
||||
@ -51,21 +49,21 @@ public:
|
||||
uint64_t offset; //if offset is ZERO, the file was ERASED
|
||||
uint64_t size;
|
||||
uint8_t md5[16];
|
||||
PackSource *src;
|
||||
PackSource* src;
|
||||
};
|
||||
|
||||
private:
|
||||
struct PackedDir {
|
||||
PackedDir *parent;
|
||||
String name;
|
||||
Map<String, PackedDir *> subdirs;
|
||||
Map<String,PackedDir*> subdirs;
|
||||
Set<String> files;
|
||||
};
|
||||
|
||||
struct PathMD5 {
|
||||
uint64_t a;
|
||||
uint64_t b;
|
||||
bool operator<(const PathMD5 &p_md5) const {
|
||||
bool operator < (const PathMD5& p_md5) const {
|
||||
|
||||
if (p_md5.a == a) {
|
||||
return b < p_md5.b;
|
||||
@ -74,7 +72,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const PathMD5 &p_md5) const {
|
||||
bool operator == (const PathMD5& p_md5) const {
|
||||
return a == p_md5.a && b == p_md5.b;
|
||||
};
|
||||
|
||||
@ -83,14 +81,14 @@ private:
|
||||
};
|
||||
|
||||
PathMD5(const Vector<uint8_t> p_buf) {
|
||||
a = *((uint64_t *)&p_buf[0]);
|
||||
b = *((uint64_t *)&p_buf[8]);
|
||||
a = *((uint64_t*)&p_buf[0]);
|
||||
b = *((uint64_t*)&p_buf[8]);
|
||||
};
|
||||
};
|
||||
|
||||
Map<PathMD5, PackedFile> files;
|
||||
Map<PathMD5,PackedFile> files;
|
||||
|
||||
Vector<PackSource *> sources;
|
||||
Vector<PackSource*> sources;
|
||||
|
||||
PackedDir *root;
|
||||
//Map<String,PackedDir*> dirs;
|
||||
@ -101,17 +99,18 @@ private:
|
||||
void _free_packed_dirs(PackedDir *p_dir);
|
||||
|
||||
public:
|
||||
void add_pack_source(PackSource *p_source);
|
||||
void add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src); // for PackSource
|
||||
|
||||
void set_disabled(bool p_disabled) { disabled = p_disabled; }
|
||||
void add_pack_source(PackSource* p_source);
|
||||
void add_path(const String& pkg_path, const String& path, uint64_t ofs, uint64_t size,const uint8_t* p_md5, PackSource* p_src); // for PackSource
|
||||
|
||||
void set_disabled(bool p_disabled) { disabled=p_disabled; }
|
||||
_FORCE_INLINE_ bool is_disabled() const { return disabled; }
|
||||
|
||||
static PackedData *get_singleton() { return singleton; }
|
||||
Error add_pack(const String &p_path);
|
||||
Error add_pack(const String& p_path);
|
||||
|
||||
_FORCE_INLINE_ FileAccess *try_open_path(const String &p_path);
|
||||
_FORCE_INLINE_ bool has_path(const String &p_path);
|
||||
_FORCE_INLINE_ FileAccess *try_open_path(const String& p_path);
|
||||
_FORCE_INLINE_ bool has_path(const String& p_path);
|
||||
|
||||
PackedData();
|
||||
~PackedData();
|
||||
@ -120,18 +119,21 @@ public:
|
||||
class PackSource {
|
||||
|
||||
public:
|
||||
virtual bool try_open_pack(const String &p_path) = 0;
|
||||
virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file) = 0;
|
||||
|
||||
virtual bool try_open_pack(const String& p_path)=0;
|
||||
virtual FileAccess* get_file(const String& p_path, PackedData::PackedFile* p_file)=0;
|
||||
virtual ~PackSource() {}
|
||||
};
|
||||
|
||||
class PackedSourcePCK : public PackSource {
|
||||
|
||||
public:
|
||||
|
||||
virtual bool try_open_pack(const String &p_path);
|
||||
virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file);
|
||||
virtual FileAccess* get_file(const String& p_path, PackedData::PackedFile* p_file);
|
||||
};
|
||||
|
||||
|
||||
class FileAccessPack : public FileAccess {
|
||||
|
||||
PackedData::PackedFile pf;
|
||||
@ -140,59 +142,65 @@ class FileAccessPack : public FileAccess {
|
||||
mutable bool eof;
|
||||
|
||||
FileAccess *f;
|
||||
virtual Error _open(const String &p_path, int p_mode_flags);
|
||||
virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
|
||||
virtual Error _open(const String& p_path, int p_mode_flags);
|
||||
virtual uint64_t _get_modified_time(const String& p_file) { return 0; }
|
||||
|
||||
public:
|
||||
|
||||
|
||||
virtual void close();
|
||||
virtual bool is_open() const;
|
||||
|
||||
virtual void seek(size_t p_position);
|
||||
virtual void seek_end(int64_t p_position = 0);
|
||||
virtual size_t get_position() const;
|
||||
virtual void seek_end(int64_t p_position=0);
|
||||
virtual size_t get_pos() const;
|
||||
virtual size_t get_len() const;
|
||||
|
||||
virtual bool eof_reached() const;
|
||||
|
||||
virtual uint8_t get_8() const;
|
||||
|
||||
virtual int get_buffer(uint8_t *p_dst, int p_length) const;
|
||||
|
||||
virtual int get_buffer(uint8_t *p_dst,int p_length) const;
|
||||
|
||||
virtual void set_endian_swap(bool p_swap);
|
||||
|
||||
virtual Error get_error() const;
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_dest);
|
||||
|
||||
virtual void store_buffer(const uint8_t *p_src, int p_length);
|
||||
virtual void store_buffer(const uint8_t *p_src,int p_length);
|
||||
|
||||
virtual bool file_exists(const String &p_name);
|
||||
virtual bool file_exists(const String& p_name);
|
||||
|
||||
FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file);
|
||||
|
||||
FileAccessPack(const String& p_path, const PackedData::PackedFile& p_file);
|
||||
~FileAccessPack();
|
||||
};
|
||||
|
||||
FileAccess *PackedData::try_open_path(const String &p_path) {
|
||||
|
||||
FileAccess *PackedData::try_open_path(const String& p_path) {
|
||||
|
||||
//print_line("try open path " + p_path);
|
||||
PathMD5 pmd5(p_path.md5_buffer());
|
||||
Map<PathMD5, PackedFile>::Element *E = files.find(pmd5);
|
||||
Map<PathMD5,PackedFile>::Element *E=files.find(pmd5);
|
||||
if (!E)
|
||||
return NULL; //not found
|
||||
if (E->get().offset == 0)
|
||||
if (E->get().offset==0)
|
||||
return NULL; //was erased
|
||||
|
||||
return E->get().src->get_file(p_path, &E->get());
|
||||
}
|
||||
|
||||
bool PackedData::has_path(const String &p_path) {
|
||||
bool PackedData::has_path(const String& p_path) {
|
||||
|
||||
return files.has(PathMD5(p_path.md5_buffer()));
|
||||
}
|
||||
|
||||
|
||||
class DirAccessPack : public DirAccess {
|
||||
|
||||
|
||||
PackedData::PackedDir *current;
|
||||
|
||||
List<String> list_dirs;
|
||||
@ -200,7 +208,8 @@ class DirAccessPack : public DirAccess {
|
||||
bool cdir;
|
||||
|
||||
public:
|
||||
virtual Error list_dir_begin();
|
||||
|
||||
virtual bool list_dir_begin();
|
||||
virtual String get_next();
|
||||
virtual bool current_is_dir() const;
|
||||
virtual bool current_is_hidden() const;
|
||||
@ -212,6 +221,7 @@ public:
|
||||
virtual Error change_dir(String p_dir);
|
||||
virtual String get_current_dir();
|
||||
|
||||
|
||||
virtual bool file_exists(String p_file);
|
||||
virtual bool dir_exists(String p_dir);
|
||||
|
||||
@ -224,6 +234,8 @@ public:
|
||||
|
||||
DirAccessPack();
|
||||
~DirAccessPack();
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // FILE_ACCESS_PACK_H
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,80 +26,82 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef MINIZIP_ENABLED
|
||||
|
||||
#include "file_access_zip.h"
|
||||
|
||||
#include "core/os/copymem.h"
|
||||
#include "core/os/file_access.h"
|
||||
#include "core/os/copymem.h"
|
||||
|
||||
ZipArchive *ZipArchive::instance = NULL;
|
||||
ZipArchive* ZipArchive::instance = NULL;
|
||||
|
||||
extern "C" {
|
||||
|
||||
static void *godot_open(void *data, const char *p_fname, int mode) {
|
||||
static void* godot_open(void* data, const char* p_fname, int mode) {
|
||||
|
||||
if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
|
||||
return NULL;
|
||||
};
|
||||
|
||||
FileAccess *f = (FileAccess *)data;
|
||||
FileAccess* f = (FileAccess*)data;
|
||||
f->open(p_fname, FileAccess::READ);
|
||||
|
||||
return f->is_open() ? data : NULL;
|
||||
return f->is_open()?data:NULL;
|
||||
|
||||
};
|
||||
|
||||
static uLong godot_read(void *data, void *fdata, void *buf, uLong size) {
|
||||
static uLong godot_read(void* data, void* fdata, void* buf, uLong size) {
|
||||
|
||||
FileAccess *f = (FileAccess *)data;
|
||||
f->get_buffer((uint8_t *)buf, size);
|
||||
FileAccess* f = (FileAccess*)data;
|
||||
f->get_buffer((uint8_t*)buf, size);
|
||||
return size;
|
||||
};
|
||||
|
||||
static uLong godot_write(voidpf opaque, voidpf stream, const void *buf, uLong size) {
|
||||
static uLong godot_write(voidpf opaque, voidpf stream, const void* buf, uLong size) {
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static long godot_tell(voidpf opaque, voidpf stream) {
|
||||
|
||||
FileAccess *f = (FileAccess *)opaque;
|
||||
return f->get_position();
|
||||
static long godot_tell (voidpf opaque, voidpf stream) {
|
||||
|
||||
FileAccess* f = (FileAccess*)opaque;
|
||||
return f->get_pos();
|
||||
};
|
||||
|
||||
static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
|
||||
|
||||
FileAccess *f = (FileAccess *)opaque;
|
||||
FileAccess* f = (FileAccess*)opaque;
|
||||
|
||||
int pos = offset;
|
||||
switch (origin) {
|
||||
|
||||
case ZLIB_FILEFUNC_SEEK_CUR:
|
||||
pos = f->get_position() + offset;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_END:
|
||||
pos = f->get_len() + offset;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_CUR:
|
||||
pos = f->get_pos() + offset;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_END:
|
||||
pos = f->get_len() + offset;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
f->seek(pos);
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
static int godot_close(voidpf opaque, voidpf stream) {
|
||||
|
||||
FileAccess *f = (FileAccess *)opaque;
|
||||
FileAccess* f = (FileAccess*)opaque;
|
||||
f->close();
|
||||
return 0;
|
||||
};
|
||||
|
||||
static int godot_testerror(voidpf opaque, voidpf stream) {
|
||||
|
||||
FileAccess *f = (FileAccess *)opaque;
|
||||
return f->get_error() != OK ? 1 : 0;
|
||||
FileAccess* f = (FileAccess*)opaque;
|
||||
return f->get_error()!=OK?1:0;
|
||||
};
|
||||
|
||||
static voidpf godot_alloc(voidpf opaque, uInt items, uInt size) {
|
||||
@ -118,7 +119,7 @@ static void godot_free(voidpf opaque, voidpf address) {
|
||||
void ZipArchive::close_handle(unzFile p_file) const {
|
||||
|
||||
ERR_FAIL_COND(!p_file);
|
||||
FileAccess *f = (FileAccess *)unzGetOpaque(p_file);
|
||||
FileAccess* f = (FileAccess*)unzGetOpaque(p_file);
|
||||
unzCloseCurrentFile(p_file);
|
||||
unzClose(p_file);
|
||||
memdelete(f);
|
||||
@ -129,7 +130,7 @@ unzFile ZipArchive::get_file_handle(String p_file) const {
|
||||
ERR_FAIL_COND_V(!file_exists(p_file), NULL);
|
||||
File file = files[p_file];
|
||||
|
||||
FileAccess *f = FileAccess::open(packages[file.package].filename, FileAccess::READ);
|
||||
FileAccess* f = FileAccess::open(packages[file.package].filename, FileAccess::READ);
|
||||
ERR_FAIL_COND_V(!f, NULL);
|
||||
|
||||
zlib_filefunc_def io;
|
||||
@ -151,7 +152,8 @@ unzFile ZipArchive::get_file_handle(String p_file) const {
|
||||
unzFile pkg = unzOpen2(packages[file.package].filename.utf8().get_data(), &io);
|
||||
ERR_FAIL_COND_V(!pkg, NULL);
|
||||
int unz_err = unzGoToFilePos(pkg, &file.file_pos);
|
||||
if (unz_err != UNZ_OK || unzOpenCurrentFile(pkg) != UNZ_OK) {
|
||||
ERR_FAIL_COND_V(unz_err != UNZ_OK, NULL);
|
||||
if (unzOpenCurrentFile(pkg) != UNZ_OK) {
|
||||
|
||||
unzClose(pkg);
|
||||
ERR_FAIL_V(NULL);
|
||||
@ -160,15 +162,15 @@ unzFile ZipArchive::get_file_handle(String p_file) const {
|
||||
return pkg;
|
||||
};
|
||||
|
||||
bool ZipArchive::try_open_pack(const String &p_path) {
|
||||
bool ZipArchive::try_open_pack(const String& p_name) {
|
||||
|
||||
//printf("opening zip pack %ls, %i, %i\n", p_name.c_str(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz"));
|
||||
if (p_path.get_extension().nocasecmp_to("zip") != 0 && p_path.get_extension().nocasecmp_to("pcz") != 0)
|
||||
if (p_name.extension().nocasecmp_to("zip") != 0 && p_name.extension().nocasecmp_to("pcz") != 0)
|
||||
return false;
|
||||
|
||||
zlib_filefunc_def io;
|
||||
|
||||
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
|
||||
FileAccess* f = FileAccess::open(p_name, FileAccess::READ);
|
||||
if (!f)
|
||||
return false;
|
||||
io.opaque = f;
|
||||
@ -181,25 +183,25 @@ bool ZipArchive::try_open_pack(const String &p_path) {
|
||||
io.zclose_file = godot_close;
|
||||
io.zerror_file = godot_testerror;
|
||||
|
||||
unzFile zfile = unzOpen2(p_path.utf8().get_data(), &io);
|
||||
unzFile zfile = unzOpen2(p_name.utf8().get_data(), &io);
|
||||
ERR_FAIL_COND_V(!zfile, false);
|
||||
|
||||
unz_global_info64 gi;
|
||||
int err = unzGetGlobalInfo64(zfile, &gi);
|
||||
ERR_FAIL_COND_V(err != UNZ_OK, false);
|
||||
ERR_FAIL_COND_V(err!=UNZ_OK, false);
|
||||
|
||||
Package pkg;
|
||||
pkg.filename = p_path;
|
||||
pkg.filename = p_name;
|
||||
pkg.zfile = zfile;
|
||||
packages.push_back(pkg);
|
||||
int pkg_num = packages.size() - 1;
|
||||
int pkg_num = packages.size()-1;
|
||||
|
||||
for (unsigned int i = 0; i < gi.number_entry; i++) {
|
||||
for (unsigned int i=0;i<gi.number_entry;i++) {
|
||||
|
||||
char filename_inzip[256];
|
||||
|
||||
unz_file_info64 file_info;
|
||||
err = unzGetCurrentFileInfo64(zfile, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0);
|
||||
err = unzGetCurrentFileInfo64(zfile,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
|
||||
ERR_CONTINUE(err != UNZ_OK);
|
||||
|
||||
File f;
|
||||
@ -209,11 +211,11 @@ bool ZipArchive::try_open_pack(const String &p_path) {
|
||||
String fname = String("res://") + filename_inzip;
|
||||
files[fname] = f;
|
||||
|
||||
uint8_t md5[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
PackedData::get_singleton()->add_path(p_path, fname, 1, 0, md5, this);
|
||||
uint8_t md5[16]={0,0,0,0,0,0,0,0 , 0,0,0,0,0,0,0,0};
|
||||
PackedData::get_singleton()->add_path(p_name, fname, 1, 0, md5, this);
|
||||
//printf("packed data add path %ls, %ls\n", p_name.c_str(), fname.c_str());
|
||||
|
||||
if ((i + 1) < gi.number_entry) {
|
||||
if ((i+1)<gi.number_entry) {
|
||||
unzGoToNextFile(zfile);
|
||||
};
|
||||
};
|
||||
@ -226,12 +228,13 @@ bool ZipArchive::file_exists(String p_name) const {
|
||||
return files.has(p_name);
|
||||
};
|
||||
|
||||
FileAccess *ZipArchive::get_file(const String &p_path, PackedData::PackedFile *p_file) {
|
||||
FileAccess* ZipArchive::get_file(const String& p_path, PackedData::PackedFile* p_file) {
|
||||
|
||||
return memnew(FileAccessZip(p_path, *p_file));
|
||||
};
|
||||
|
||||
ZipArchive *ZipArchive::get_singleton() {
|
||||
|
||||
ZipArchive* ZipArchive::get_singleton() {
|
||||
|
||||
if (instance == NULL) {
|
||||
instance = memnew(ZipArchive);
|
||||
@ -248,9 +251,9 @@ ZipArchive::ZipArchive() {
|
||||
|
||||
ZipArchive::~ZipArchive() {
|
||||
|
||||
for (int i = 0; i < packages.size(); i++) {
|
||||
for (int i=0; i<packages.size(); i++) {
|
||||
|
||||
FileAccess *f = (FileAccess *)unzGetOpaque(packages[i].zfile);
|
||||
FileAccess* f = (FileAccess*)unzGetOpaque(packages[i].zfile);
|
||||
unzClose(packages[i].zfile);
|
||||
memdelete(f);
|
||||
};
|
||||
@ -258,17 +261,18 @@ ZipArchive::~ZipArchive() {
|
||||
packages.clear();
|
||||
};
|
||||
|
||||
Error FileAccessZip::_open(const String &p_path, int p_mode_flags) {
|
||||
|
||||
Error FileAccessZip::_open(const String& p_path, int p_mode_flags) {
|
||||
|
||||
close();
|
||||
|
||||
ERR_FAIL_COND_V(p_mode_flags & FileAccess::WRITE, FAILED);
|
||||
ZipArchive *arch = ZipArchive::get_singleton();
|
||||
ZipArchive* arch = ZipArchive::get_singleton();
|
||||
ERR_FAIL_COND_V(!arch, FAILED);
|
||||
zfile = arch->get_file_handle(p_path);
|
||||
ERR_FAIL_COND_V(!zfile, FAILED);
|
||||
|
||||
int err = unzGetCurrentFileInfo64(zfile, &file_info, NULL, 0, NULL, 0, NULL, 0);
|
||||
int err = unzGetCurrentFileInfo64(zfile,&file_info,NULL,0,NULL,0,NULL,0);
|
||||
ERR_FAIL_COND_V(err != UNZ_OK, FAILED);
|
||||
|
||||
return OK;
|
||||
@ -279,7 +283,7 @@ void FileAccessZip::close() {
|
||||
if (!zfile)
|
||||
return;
|
||||
|
||||
ZipArchive *arch = ZipArchive::get_singleton();
|
||||
ZipArchive* arch = ZipArchive::get_singleton();
|
||||
ERR_FAIL_COND(!arch);
|
||||
arch->close_handle(zfile);
|
||||
zfile = NULL;
|
||||
@ -302,7 +306,7 @@ void FileAccessZip::seek_end(int64_t p_position) {
|
||||
unzSeekCurrentFile(zfile, get_len() + p_position);
|
||||
};
|
||||
|
||||
size_t FileAccessZip::get_position() const {
|
||||
size_t FileAccessZip::get_pos() const {
|
||||
|
||||
ERR_FAIL_COND_V(!zfile, 0);
|
||||
return unztell(zfile);
|
||||
@ -328,7 +332,7 @@ uint8_t FileAccessZip::get_8() const {
|
||||
return ret;
|
||||
};
|
||||
|
||||
int FileAccessZip::get_buffer(uint8_t *p_dst, int p_length) const {
|
||||
int FileAccessZip::get_buffer(uint8_t *p_dst,int p_length) const {
|
||||
|
||||
ERR_FAIL_COND_V(!zfile, -1);
|
||||
at_eof = unzeof(zfile);
|
||||
@ -354,22 +358,18 @@ Error FileAccessZip::get_error() const {
|
||||
return OK;
|
||||
};
|
||||
|
||||
void FileAccessZip::flush() {
|
||||
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
void FileAccessZip::store_8(uint8_t p_dest) {
|
||||
|
||||
ERR_FAIL();
|
||||
};
|
||||
|
||||
bool FileAccessZip::file_exists(const String &p_name) {
|
||||
bool FileAccessZip::file_exists(const String& p_name) {
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
FileAccessZip::FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file) {
|
||||
|
||||
FileAccessZip::FileAccessZip(const String& p_path, const PackedData::PackedFile& p_file) {
|
||||
|
||||
zfile = NULL;
|
||||
_open(p_path, FileAccess::READ);
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,22 +26,20 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef MINIZIP_ENABLED
|
||||
|
||||
#ifndef FILE_ACCESS_ZIP_H
|
||||
#define FILE_ACCESS_ZIP_H
|
||||
|
||||
#include "core/io/file_access_pack.h"
|
||||
#include "map.h"
|
||||
|
||||
#include "thirdparty/minizip/unzip.h"
|
||||
#ifndef FILE_ACCESS_Zip_H
|
||||
#define FILE_ACCESS_Zip_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "core/io/file_access_pack.h"
|
||||
#include "unzip.h"
|
||||
#include "map.h"
|
||||
|
||||
class ZipArchive : public PackSource {
|
||||
|
||||
public:
|
||||
|
||||
struct File {
|
||||
|
||||
int package;
|
||||
@ -53,20 +50,23 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
struct Package {
|
||||
String filename;
|
||||
unzFile zfile;
|
||||
};
|
||||
Vector<Package> packages;
|
||||
|
||||
Map<String, File> files;
|
||||
Map<String,File> files;
|
||||
|
||||
static ZipArchive *instance;
|
||||
static ZipArchive* instance;
|
||||
|
||||
FileAccess::CreateFunc fa_create_func;
|
||||
|
||||
public:
|
||||
|
||||
void close_handle(unzFile p_file) const;
|
||||
unzFile get_file_handle(String p_file) const;
|
||||
|
||||
@ -74,51 +74,52 @@ public:
|
||||
|
||||
bool file_exists(String p_name) const;
|
||||
|
||||
virtual bool try_open_pack(const String &p_path);
|
||||
FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file);
|
||||
virtual bool try_open_pack(const String& p_path);
|
||||
FileAccess* get_file(const String& p_path, PackedData::PackedFile* p_file);
|
||||
|
||||
static ZipArchive *get_singleton();
|
||||
static ZipArchive* get_singleton();
|
||||
|
||||
ZipArchive();
|
||||
~ZipArchive();
|
||||
};
|
||||
|
||||
|
||||
class FileAccessZip : public FileAccess {
|
||||
|
||||
unzFile zfile;
|
||||
unz_file_info64 file_info;
|
||||
unz_file_info64 file_info;
|
||||
|
||||
mutable bool at_eof;
|
||||
|
||||
ZipArchive *archive;
|
||||
ZipArchive* archive;
|
||||
|
||||
public:
|
||||
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
|
||||
|
||||
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
|
||||
virtual void close(); ///< close a file
|
||||
virtual bool is_open() const; ///< true when file is open
|
||||
|
||||
virtual void seek(size_t p_position); ///< seek to a given position
|
||||
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
|
||||
virtual size_t get_position() const; ///< get position in the file
|
||||
virtual void seek_end(int64_t p_position=0); ///< seek from the end of file
|
||||
virtual size_t get_pos() const; ///< get position in the file
|
||||
virtual size_t get_len() const; ///< get size of the file
|
||||
|
||||
virtual bool eof_reached() const; ///< reading passed EOF
|
||||
|
||||
virtual uint8_t get_8() const; ///< get a byte
|
||||
virtual int get_buffer(uint8_t *p_dst, int p_length) const;
|
||||
virtual int get_buffer(uint8_t *p_dst,int p_length) const;
|
||||
|
||||
virtual Error get_error() const; ///< get last error
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_dest); ///< store a byte
|
||||
virtual bool file_exists(const String &p_name); ///< return true if a file exists
|
||||
virtual bool file_exists(const String& p_name); ///< return true if a file exists
|
||||
|
||||
virtual uint64_t _get_modified_time(const String &p_file) { return 0; } // todo
|
||||
virtual uint64_t _get_modified_time(const String& p_file) { return 0; } // todo
|
||||
|
||||
FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file);
|
||||
FileAccessZip(const String& p_path, const PackedData::PackedFile& p_file);
|
||||
~FileAccessZip();
|
||||
};
|
||||
|
||||
#endif // FILE_ACCESS_ZIP_H
|
||||
|
||||
#endif // MINIZIP_ENABLED
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,20 +26,20 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef HTTP_CLIENT_H
|
||||
#define HTTP_CLIENT_H
|
||||
|
||||
#include "io/ip.h"
|
||||
#include "io/stream_peer.h"
|
||||
#include "io/stream_peer_tcp.h"
|
||||
#include "io/ip.h"
|
||||
#include "reference.h"
|
||||
|
||||
|
||||
class HTTPClient : public Reference {
|
||||
|
||||
GDCLASS(HTTPClient, Reference);
|
||||
|
||||
OBJ_TYPE(HTTPClient,Reference);
|
||||
public:
|
||||
|
||||
enum ResponseCode {
|
||||
|
||||
// 1xx informational
|
||||
@ -57,7 +56,6 @@ public:
|
||||
RESPONSE_RESET_CONTENT = 205,
|
||||
RESPONSE_PARTIAL_CONTENT = 206,
|
||||
RESPONSE_MULTI_STATUS = 207,
|
||||
RESPONSE_ALREADY_REPORTED = 208,
|
||||
RESPONSE_IM_USED = 226,
|
||||
|
||||
// 3xx redirection
|
||||
@ -67,9 +65,7 @@ public:
|
||||
RESPONSE_SEE_OTHER = 303,
|
||||
RESPONSE_NOT_MODIFIED = 304,
|
||||
RESPONSE_USE_PROXY = 305,
|
||||
RESPONSE_SWITCH_PROXY = 306,
|
||||
RESPONSE_TEMPORARY_REDIRECT = 307,
|
||||
RESPONSE_PERMANENT_REDIRECT = 308,
|
||||
|
||||
// 4xx client error
|
||||
RESPONSE_BAD_REQUEST = 400,
|
||||
@ -90,16 +86,10 @@ public:
|
||||
RESPONSE_UNSUPPORTED_MEDIA_TYPE = 415,
|
||||
RESPONSE_REQUESTED_RANGE_NOT_SATISFIABLE = 416,
|
||||
RESPONSE_EXPECTATION_FAILED = 417,
|
||||
RESPONSE_IM_A_TEAPOT = 418,
|
||||
RESPONSE_MISDIRECTED_REQUEST = 421,
|
||||
RESPONSE_UNPROCESSABLE_ENTITY = 422,
|
||||
RESPONSE_LOCKED = 423,
|
||||
RESPONSE_FAILED_DEPENDENCY = 424,
|
||||
RESPONSE_UPGRADE_REQUIRED = 426,
|
||||
RESPONSE_PRECONDITION_REQUIRED = 428,
|
||||
RESPONSE_TOO_MANY_REQUESTS = 429,
|
||||
RESPONSE_REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
|
||||
RESPONSE_UNAVAILABLE_FOR_LEGAL_REASONS = 451,
|
||||
|
||||
// 5xx server error
|
||||
RESPONSE_INTERNAL_SERVER_ERROR = 500,
|
||||
@ -108,11 +98,8 @@ public:
|
||||
RESPONSE_SERVICE_UNAVAILABLE = 503,
|
||||
RESPONSE_GATEWAY_TIMEOUT = 504,
|
||||
RESPONSE_HTTP_VERSION_NOT_SUPPORTED = 505,
|
||||
RESPONSE_VARIANT_ALSO_NEGOTIATES = 506,
|
||||
RESPONSE_INSUFFICIENT_STORAGE = 507,
|
||||
RESPONSE_LOOP_DETECTED = 508,
|
||||
RESPONSE_NOT_EXTENDED = 510,
|
||||
RESPONSE_NETWORK_AUTH_REQUIRED = 511,
|
||||
|
||||
};
|
||||
|
||||
@ -126,38 +113,26 @@ public:
|
||||
METHOD_OPTIONS,
|
||||
METHOD_TRACE,
|
||||
METHOD_CONNECT,
|
||||
METHOD_PATCH,
|
||||
METHOD_MAX
|
||||
|
||||
};
|
||||
|
||||
enum Status {
|
||||
|
||||
STATUS_DISCONNECTED,
|
||||
STATUS_RESOLVING, // Resolving hostname (if passed a hostname)
|
||||
STATUS_RESOLVING, //resolving hostname (if passed a hostname)
|
||||
STATUS_CANT_RESOLVE,
|
||||
STATUS_CONNECTING, // Connecting to IP
|
||||
STATUS_CONNECTING, //connecting to ip
|
||||
STATUS_CANT_CONNECT,
|
||||
STATUS_CONNECTED, // Connected, requests can be made
|
||||
STATUS_REQUESTING, // Request in progress
|
||||
STATUS_BODY, // Request resulted in body, which must be read
|
||||
STATUS_CONNECTED, //connected, requests only accepted here
|
||||
STATUS_REQUESTING, // request in progress
|
||||
STATUS_BODY, // request resulted in body, which must be read
|
||||
STATUS_CONNECTION_ERROR,
|
||||
STATUS_SSL_HANDSHAKE_ERROR,
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
static const char *_methods[METHOD_MAX];
|
||||
static const int HOST_MIN_LEN = 4;
|
||||
|
||||
enum Port {
|
||||
|
||||
PORT_HTTP = 80,
|
||||
PORT_HTTPS = 443,
|
||||
|
||||
};
|
||||
|
||||
#ifndef JAVASCRIPT_ENABLED
|
||||
IP::Type ip_type;
|
||||
Status status;
|
||||
IP::ResolverID resolving;
|
||||
int conn_port;
|
||||
@ -179,27 +154,28 @@ private:
|
||||
|
||||
int response_num;
|
||||
Vector<String> response_headers;
|
||||
int read_chunk_size;
|
||||
|
||||
Error _get_http_data(uint8_t *p_buffer, int p_bytes, int &r_received);
|
||||
|
||||
#else
|
||||
#include "platform/javascript/http_client.h.inc"
|
||||
#endif
|
||||
|
||||
PoolStringArray _get_response_headers();
|
||||
Dictionary _get_response_headers_as_dictionary();
|
||||
|
||||
static void _bind_methods();
|
||||
StringArray _get_response_headers();
|
||||
Dictionary _get_response_headers_as_dictionary();
|
||||
int read_chunk_size;
|
||||
|
||||
Error _get_http_data(uint8_t* p_buffer, int p_bytes,int &r_received);
|
||||
|
||||
public:
|
||||
Error connect_to_host(const String &p_host, int p_port = -1, bool p_ssl = false, bool p_verify_host = true);
|
||||
|
||||
void set_connection(const Ref<StreamPeer> &p_connection);
|
||||
|
||||
void set_ip_type(IP::Type p_type);
|
||||
//Error connect_and_get(const String& p_url,bool p_verify_host=true); //connects to a full url and perform request
|
||||
Error connect(const String &p_host,int p_port,bool p_ssl=false,bool p_verify_host=true);
|
||||
|
||||
void set_connection(const Ref<StreamPeer>& p_connection);
|
||||
Ref<StreamPeer> get_connection() const;
|
||||
|
||||
Error request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body);
|
||||
Error request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body = String());
|
||||
Error request_raw( Method p_method, const String& p_url, const Vector<String>& p_headers,const DVector<uint8_t>& p_body);
|
||||
Error request( Method p_method, const String& p_url, const Vector<String>& p_headers,const String& p_body=String());
|
||||
Error send_body_text(const String& p_body);
|
||||
Error send_body_data(const ByteArray& p_body);
|
||||
|
||||
void close();
|
||||
|
||||
@ -211,22 +187,21 @@ public:
|
||||
Error get_response_headers(List<String> *r_response);
|
||||
int get_response_body_length() const;
|
||||
|
||||
PoolByteArray read_response_body_chunk(); // Can't get body as partial text because of most encodings UTF8, gzip, etc.
|
||||
ByteArray read_response_body_chunk(); // can't get body as partial text because of most encodings UTF8, gzip, etc.
|
||||
|
||||
void set_blocking_mode(bool p_enable); // Useful mostly if running in a thread
|
||||
void set_blocking_mode(bool p_enable); //useful mostly if running in a thread
|
||||
bool is_blocking_mode_enabled() const;
|
||||
|
||||
void set_read_chunk_size(int p_size);
|
||||
|
||||
Error poll();
|
||||
|
||||
String query_string_from_dict(const Dictionary &p_dict);
|
||||
String query_string_from_dict(const Dictionary& p_dict);
|
||||
|
||||
HTTPClient();
|
||||
~HTTPClient();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(HTTPClient::ResponseCode)
|
||||
VARIANT_ENUM_CAST(HTTPClient::Method);
|
||||
VARIANT_ENUM_CAST(HTTPClient::Status);
|
||||
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
@ -27,83 +26,93 @@
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "image_loader.h"
|
||||
|
||||
#include "print_string.h"
|
||||
bool ImageFormatLoader::recognize(const String &p_extension) const {
|
||||
bool ImageFormatLoader::recognize(const String& p_extension) const {
|
||||
|
||||
|
||||
List<String> extensions;
|
||||
get_recognized_extensions(&extensions);
|
||||
for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
|
||||
for (List<String>::Element *E=extensions.front();E;E=E->next()) {
|
||||
|
||||
if (E->get().nocasecmp_to(p_extension) == 0)
|
||||
if (E->get().nocasecmp_to(p_extension.extension())==0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Error ImageLoader::load_image(String p_file, Ref<Image> p_image, FileAccess *p_custom, bool p_force_linear, float p_scale) {
|
||||
ERR_FAIL_COND_V(p_image.is_null(), ERR_INVALID_PARAMETER);
|
||||
Error ImageLoader::load_image(String p_file,Image *p_image, FileAccess *p_custom) {
|
||||
|
||||
FileAccess *f = p_custom;
|
||||
|
||||
FileAccess *f=p_custom;
|
||||
if (!f) {
|
||||
Error err;
|
||||
f = FileAccess::open(p_file, FileAccess::READ, &err);
|
||||
f=FileAccess::open(p_file,FileAccess::READ,&err);
|
||||
if (!f) {
|
||||
ERR_PRINTS("Error opening file: " + p_file);
|
||||
ERR_PRINTS("Error opening file: "+p_file);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
String extension = p_file.get_extension();
|
||||
String extension = p_file.extension();
|
||||
|
||||
for (int i = 0; i < loader_count; i++) {
|
||||
|
||||
for (int i=0;i<loader_count;i++) {
|
||||
|
||||
if (!loader[i]->recognize(extension))
|
||||
continue;
|
||||
Error err = loader[i]->load_image(p_image, f, p_force_linear, p_scale);
|
||||
Error err = loader[i]->load_image(p_image,f);
|
||||
|
||||
if (err!=ERR_FILE_UNRECOGNIZED) {
|
||||
|
||||
if (err != ERR_FILE_UNRECOGNIZED) {
|
||||
|
||||
if (!p_custom)
|
||||
memdelete(f);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (!p_custom)
|
||||
memdelete(f);
|
||||
|
||||
return ERR_FILE_UNRECOGNIZED;
|
||||
|
||||
}
|
||||
|
||||
void ImageLoader::get_recognized_extensions(List<String> *p_extensions) {
|
||||
|
||||
for (int i = 0; i < loader_count; i++) {
|
||||
for (int i=0;i<loader_count;i++) {
|
||||
|
||||
loader[i]->get_recognized_extensions(p_extensions);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageLoader::recognize(const String &p_extension) {
|
||||
bool ImageLoader::recognize(const String& p_extension) {
|
||||
|
||||
for (int i = 0; i < loader_count; i++) {
|
||||
for (int i=0;i<loader_count;i++) {
|
||||
|
||||
if (loader[i]->recognize(p_extension))
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ImageFormatLoader *ImageLoader::loader[MAX_LOADERS];
|
||||
int ImageLoader::loader_count = 0;
|
||||
int ImageLoader::loader_count=0;
|
||||
|
||||
void ImageLoader::add_image_format_loader(ImageFormatLoader *p_loader) {
|
||||
|
||||
ERR_FAIL_COND(loader_count >= MAX_LOADERS);
|
||||
loader[loader_count++] = p_loader;
|
||||
ERR_FAIL_COND(loader_count >=MAX_LOADERS );
|
||||
loader[loader_count++]=p_loader;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user