Compare commits

..

177 Commits

Author SHA1 Message Date
8ea709a7a9 Update the changelog for 3.0.1 2018-02-26 20:35:13 +01:00
f2e19a26f5 Add a project changelog
(cherry picked from commit f00b2dfc55)
2018-02-25 15:32:08 +01:00
be771e7165 Fix version.txt validation logic for export templates .tpz
It assumed that the version would always be `x.y-status`,
with no dot possible in `status`, so:
- It would not work for 3.0.1-stable (nor 3.0.1.stable with new version logic)
- It would not support Mono templates when we provide them

The validation it did was not really useful anyway, so we just use the raw
string.

(cherry picked from commit eec9261a75)
2018-02-25 15:29:28 +01:00
cb65617897 Revert "Bump to version 3.0.2-devel"
This reverts commit bcbe7a8a6f.

Need to push a fix and retag 3.0.1-stable, sorry.
2018-02-25 14:09:38 +01:00
bcbe7a8a6f Bump to version 3.0.2-devel
The start of the next patch release. Wooooooooooo
2018-02-24 20:08:32 +01:00
ae540c2efe Bump version to 3.0.1-stable
Thanks everyone for all your amazing work getting our first stable patch
release out for the 3.0 series. I'd particularly like to thank @fales
and @fire for their work on the server platform.

Onwards to 3.0.2!
2018-02-24 19:21:52 +01:00
5f15642fde Update doc version strings to 3.0.1 2018-02-24 18:59:38 +01:00
17d7084780 Correct version number for 3.0.1 in the manpage 2018-02-24 18:37:01 +01:00
fe38b648b0 [DOCS] clarify that OS.get_user_data_dir needs project name
[ci skip]

(cherry picked from commit 2c22c9dcfb)
2018-02-24 18:33:43 +01:00
ad325be5a0 Add --quit option to help output and update manpage
(cherry picked from commit 95b8984d5f)
2018-02-24 18:32:22 +01:00
d69d58deea Fix Windows file case changing
Windows APIs don't really provide a way to change a filename case. This
implements a little juggling to make this work. We first create a
guaranteed unique temporary file, we then replace the original file with
the temporary file and we finally rename it to the desired filename
case.
2018-02-24 17:37:07 +01:00
34591f9451 Fixes collisions shape selection
(cherry picked from commit c250a9a9f9)
2018-02-24 10:53:10 +01:00
d79a7a2773 Refactor version macros and fix related bugs
The previous logic with VERSION_MKSTRING was a bit unwieldy, so there were
several places hardcoding their own variant of the version string, potentially
with bugs (e.g. forgetting the patch number when defined).

The new logic defines:

- VERSION_BRANCH, the main 'major.minor' version (e.g. 3.1)
- VERSION_NUMBER, which can be 'major.minor' or 'major.minor.patch',
  depending on whether the latter is defined (e.g. 3.1.4)
- VERSION_FULL_CONFIG, which contains the version status (e.g. stable)
  and the module-specific suffix (e.g. mono)
- VERSION_FULL_BUILD, same as above but with build/reference name
  (e.g. official, custom_build, mageia, etc.)
  Note: Slight change here, as the previous format had the build name
  *before* the module-specific suffix; now it's after
- VERSION_FULL_NAME, same as before, so VERSION_FULL_BUILD prefixed
  with "Godot v" for readability

Bugs fixed thanks to that:

- Export templates version matching now properly takes VERSION_PATCH
  into account by relying on VERSION_FULL_CONFIG.
- ClassDB hash no longer takes the build name into account, but limits
  itself to VERSION_FULL_CONFIG (build name is cosmetic, not relevant
  for the API hash).
- Docs XML no longer hardcode the VERSION_STATUS, this was annoying.
- Small cleanup in Windows .rc file thanks to new macros.

(cherry picked from commit 23ebae01dc)
2018-02-24 01:34:34 +01:00
05fec82f31 Merge pull request #16934 from anakimluke/fix_space_around_args
Removed whitespaces around arguments of functions.
2018-02-24 01:32:59 +01:00
370f84f41c Removed whitespaces around arguments of functions.
Functions automatically generated by conneting
signals via GUI put whitespaces around the
arguments of the generated function. This is
inconsistent with the style guide.

This commit fixes that.
2018-02-22 19:41:37 -03:00
689dfcd9ec server: Add support for statically linking libgcc and libstdc++
(cherry picked from commit be7bfdfac3)
2018-02-22 19:06:36 +01:00
46b594054c doc: Sync classref with current source 2018-02-22 19:02:37 +01:00
07e2461995 i18n: Sync translation templates with current source 2018-02-22 18:47:07 +01:00
ca5f3b9f8d i18n: Sync translations with Weblate
(cherry picked from commit 661ab3c88e)
2018-02-22 18:42:25 +01:00
3d804778fd Fix quotation in string
fix for #16404

(cherry picked from commit f38e819fc1)
2018-02-22 13:23:44 +01:00
3e8c214a19 Delete all selected lines using the delete line shortcut in script editor
(cherry picked from commit 7368978a48)
2018-02-22 13:09:02 +01:00
e9d8dfbf0e Ignore tools CLI flags in non-tools builds.
Some flags were still parsed but either did nothing or broke everything.

No reason to parse them.

(cherry picked from commit dd19826277)
2018-02-22 13:08:03 +01:00
3687faa78f Enforce insert_final_newline in the editorconfig.
(cherry picked from commit 6861886f70)
2018-02-22 13:06:25 +01:00
eacd66e784 Clean up some bad words from code comments
(cherry picked from commit d35e486228)
2018-02-22 12:22:41 +01:00
b5f8c1a53b Fix timer second not zero padded when < 10
Also RTR "Time Left:"

(cherry picked from commit d2e3607fa0)
2018-02-22 12:20:23 +01:00
f04cd405ac Fix loading project.binary from PCK file
Regression introduced in #16825.
My logic was correct, but not the error code I was expecting.
The error reporting in FileAccess likely needs a review too.

(cherry picked from commit 57d562b394)
2018-02-22 12:19:43 +01:00
f55b376d78 Improve error reporting of ProjectSettings::setup()
And use it to better report errors in the console and project manager
when a project.godot file is corrupted.

Fixes #14963.

(cherry picked from commit 7839076f95)
2018-02-22 12:19:28 +01:00
fdac09a0aa Made the Debugger's Stack Frames items reselectable.
(cherry picked from commit 32e3f257ac)
2018-02-22 12:18:45 +01:00
751806b5c7 Fix typos with codespell
Found via `codespell -q 3 --skip="./thirdparty,./editor/translations" -I ../godot-word-whitelist.txt`
Whitelist consists of:
```
ang
doubleclick
lod
nd
que
te
unselect
```

(cherry picked from commit 612ab4bbc6)
2018-02-22 12:17:06 +01:00
40018e995c Color:fix setting V switch S to old V value
(cherry picked from commit f4f92b55e1)
2018-02-22 12:07:07 +01:00
be6323d848 Added documentation for VehicleBody
(cherry picked from commit 234b86e6b2)
2018-02-22 12:03:10 +01:00
29089b715d Insert proper copy icon to debugger
(cherry picked from commit db2a1544c0)
2018-02-22 12:02:41 +01:00
7e89cc46dd Icons update
includes new enum, MeshInstance2D, Skeleton2D, Cut, Copy and Paste icons.

(cherry picked from commit cecf274364)
2018-02-22 12:02:02 +01:00
a86829211a Added missing shader functions
(cherry picked from commit 8f04a13c98)
2018-02-22 00:02:52 +01:00
f01821b60a Force controls to save rect_clip_content since they do not all default to false.
(cherry picked from commit cc902cf9ab)
2018-02-22 00:01:33 +01:00
245c11be08 Change function signature from float to double to match type get_doubleCloses #16160
(cherry picked from commit d2f1c87063)
2018-02-21 23:59:15 +01:00
fa98637aca Fixes wrong vertical font layout in RichTextLabel
(cherry picked from commit 77b1320fb4)
2018-02-21 23:52:49 +01:00
Ian
723613dbc3 TextEdit folding over unindented comments
(cherry picked from commit d327f75392)
2018-02-21 23:51:45 +01:00
99efa7ce62 Revert "Fix wrong return type of xform functions"
As this will change bindings API this will have to wait for 3.1

This reverts commit 187c40d64d.
2018-02-21 23:47:04 +01:00
c7040f3218 Fixed sky reflection rendering when transparent BG
(cherry picked from commit c34f18acce)
2018-02-21 23:40:59 +01:00
5975b44ded Fixes gravity calculation for kinematic bodies in Bullet
(cherry picked from commit 5fb8a6a6c2)
2018-02-21 23:38:30 +01:00
8efb9c8cdd Actually fix the db/dc renaming mess
Local builds save lives :)
2018-02-21 23:21:21 +01:00
75289b4017 revert the renaming _tree_db_selected function 2018-02-21 22:57:50 +01:00
ccf27376a6 Update warning about C# support
(cherry picked from commit 24cf4fe062)
2018-02-21 22:55:46 +01:00
23b9f09c58 Fixed "Open" button being enabled when nothing is selected in a FileDialog while in "Open folder" mode.
(cherry picked from commit db80d56388)
2018-02-21 22:23:24 +01:00
e1fc7776f6 gltf: improve embedded data discovery
Some editors seems to use the image resource's mime type (e.g. "image/png") for data embedded uris instead of "application/octet-stream".

(cherry picked from commit 1abf464b59)
2018-02-21 22:17:09 +01:00
c6a96fc360 Enable snapping when control key pressed
(cherry picked from commit 24c170555d)
2018-02-21 22:16:20 +01:00
Max
4383fae5a4 Fixed disappearing text on filedialog buttons
(cherry picked from commit 6a48f952ca)
2018-02-21 22:15:05 +01:00
9cfcf102a0 [Mono] Fixed "expression did not evaluate to a constant" compiler error for visual studio.
(cherry picked from commit 72fe70272d)
2018-02-21 22:12:57 +01:00
8dc946c89c Fix a rendering bug with screen_texture
(cherry picked from commit ea57a19b34)
2018-02-21 22:11:47 +01:00
327fea741a using TIME in light shader enables uses_fragment_time
The GLES3 shader compiler performs certain checks to enable or disable
the usage of certain uniform variables (and with that the set-up of UBOs).

If the `TIME` variable gets used inside the `vertex` function then the
renderer knows that it has to insert that value into the UBO.
The same applies to the `fragment` function.

The `light` function gets executed inside the fragment shader for every
light source that is relevant to the current pixel. If the `TIME` variable
gets used in that function then it needs to be present in the fragment-UBO.
The check for this was missing, so if a shader uses `TIME` inside `light`
but not inside `fragment` then the uniform will not actually be set up.

(cherry picked from commit bb655856e2)
2018-02-21 22:10:28 +01:00
317cb336eb Keep to show current script when closing all docs
also fix error when removing multiple tabs from TabContainer at same frame.
like closing multiple docs at once.

Fix #16403

(cherry picked from commit df84290a7e)
2018-02-21 22:09:23 +01:00
83b76a8171 Added an auto quit and auto build flag to the command line options.
(cherry picked from commit 4bfb504c2f)
2018-02-21 21:56:37 +01:00
70b082c0d9 Create and return LightmapCapture.
(cherry picked from commit 2e66730061)
2018-02-21 21:49:16 +01:00
bbfec2a7cc Add dummy audio driver, fix dummy rasterizer
(cherry picked from commit 4e1923a931)
2018-02-21 21:49:10 +01:00
8849377f6d Fixes to OS_Server and DummyRasterizer to match new signatures
(cherry picked from commit 2de10aa467)
2018-02-21 21:48:58 +01:00
149ffcb1a4 server platform now compiles and run on linux.
Seems to also be able to do exports of some demos I tried.

(cherry picked from commit 6784d743f7)
2018-02-21 21:48:46 +01:00
fb4a784319 Add dummy Texture handling
(cherry picked from commit 72ef766dfa)
2018-02-21 21:48:33 +01:00
8f231d82bb Disable GLES builders and source from server compilation
(cherry picked from commit 8699f643c9)
2018-02-21 21:48:21 +01:00
cc280545dc Add dummy resterizer driver
(cherry picked from commit c0dce6e480)
2018-02-21 21:47:38 +01:00
fa02b58b46 Remove unused variable from plugin settings update
Fix #16199

(cherry picked from commit 9f0cce840d)
2018-02-19 23:15:56 +01:00
000caef623 Fixing folder/file case sensitive renaming issue
Example:
Could not rename "Objects" to "objects" or vice versa

(cherry picked from commit e790ca084d)
2018-02-19 22:47:39 +01:00
b7faa76485 fix spurious error messages during autocomplete and validate
_parse() caused resets on members like validating and
for_completion by calling clear().

(cherry picked from commit 48c9ed4545)
2018-02-19 22:46:49 +01:00
a76dfe9c72 Fix 2d collision body update on shape remove
(cherry picked from commit 3659df6624)
2018-02-19 22:43:33 +01:00
a423adbee6 Flush HTTPClient response data only on request/close in HTML5 platform
(cherry picked from commit 98039909f2)
2018-02-19 22:42:38 +01:00
c5b5fd61d4 Warn when polling HTTPClient synchronously in HTML5 platform
(cherry picked from commit ca9fa9cca8)
2018-02-19 22:42:31 +01:00
5bb269d01d Disable insecure HTTP methods CONNECT and TRACE in HTML5 platform
(cherry picked from commit 2cd7bc04ea)
2018-02-19 22:42:22 +01:00
d5535d9357 Fix HTML5 HTTPClient response header retrieval
(cherry picked from commit 8a21f27f54)
2018-02-19 22:42:08 +01:00
2714b851bf Fix HTML5 HTTPClient failure detection
(cherry picked from commit 9ea4452d21)
2018-02-19 22:42:01 +01:00
2abbdcaa20 Mono: Fix build status icons
(cherry picked from commit 8bd05f0c71)
2018-02-19 22:40:21 +01:00
9cba5ef772 implement signal related methods in csharp_script so signals can be used with emit
(cherry picked from commit cfbd7fd21e)
2018-02-19 22:39:51 +01:00
416cd9c8b8 add a [Signal] attribute to CSharpScripts
(cherry picked from commit efd52cd172)
2018-02-19 22:39:44 +01:00
7a20495a80 Direct to InputEventJoypadButton for using buttons
(cherry picked from commit 6af7dafd6c)
2018-02-19 22:37:09 +01:00
bafbd73b51 Remove window decorations for fullscreen on X11
(cherry picked from commit 935a99e758)
2018-02-19 22:36:20 +01:00
ac6811c4fa Gridmap editor now lists plane instead of floor when not horizontal.
Instead of gridmap editor calling grid as floor irrespective of the
orientation, it now calls the grid plane if it's vertical and floor
if horizontal.

Resolves: #14611
(cherry picked from commit 7c356a9c05)
2018-02-19 22:34:16 +01:00
8372a404bb X11: Link libgcc statically with use_static_cpp option
We were already linking libstdc++ statically for official binaries,
protecting us against most portability issues. But apparently since
we started using GCC 7 for official builds, we also need to link
libgcc statically for at least 32-bit builds to be portable.

Fixes #16409.

(cherry picked from commit b526088ae2)
2018-02-19 22:33:29 +01:00
5b04dcfabd Update CA certificates to latest Mozilla bundle
Copied from an up-to-date Fedora 27 install (ca-certificates-2018.2.22-1.0.fc27).

(cherry picked from commit 294af5617a)
2018-02-19 22:32:53 +01:00
4b581104e7 Makes project manager never initialize mono debug.
The heuristic whether we're in the project manager inside GDMono
didn't work if the project manager was launched by not having any path
to run.

This is fixed now by making a Main::is_project_manager().

(cherry picked from commit 1099838079)
2018-02-19 22:32:17 +01:00
f49601a934 Give C# NodePath a ToString().
It already had an implicit cast operator to string,
but this doesn't get used in say string formatting.

So now something like $"path: {GetPath()}" works.

(cherry picked from commit 3c1f8efd9e)
2018-02-19 22:31:33 +01:00
3e6ab9f3d5 Makes NodePath and RID follow PascalCase in C#.
Fixes #15685

(cherry picked from commit b1a81374d4)
2018-02-19 22:30:45 +01:00
9f9731da3a fix crash autotile edit mode
(cherry picked from commit cceb176be3)
2018-02-19 22:30:13 +01:00
18735ff6f2 Fixes OptionButton selection index being reset to zero at instanciation
Bug: engine tries to set selected item before items were added during save scene/run project, because of wrong properties order.
Fixes #10213.

(cherry picked from commit 66c39b1426)
2018-02-19 22:29:36 +01:00
237cf72f89 Made modifications to the RigidBody(2D) descriptions.
(cherry picked from commit 50e6b3c005)
2018-02-19 22:28:47 +01:00
5c2b2ca95b Documentation tool does not add escapes to code and codeblocks
Instead of adding the escapes to all * and _ the tool now excludes
the characters inside [code] and [codeblock].

Resolves: #15156
(cherry picked from commit 84e8c49f5d)
2018-02-19 22:28:03 +01:00
57f707f951 Add locale renames for Hebrew and Indonesian on Windows
Windows does not fully respect ISO 639-1 like other systems,
so we have to override its locale values for those languages.

Also added comments to document the locale provenance.

(cherry picked from commit 0c7bed45c4)
2018-02-19 22:27:19 +01:00
2f87e7ffe9 option to disable sort in script list
(cherry picked from commit e1778fb921)
2018-02-19 22:26:29 +01:00
12da8dcdeb PEP3101 applied with changing old type string formatting as new ones
(cherry picked from commit 78dba05fc0)
2018-02-19 22:25:41 +01:00
c5388fb0cf Fix for a possible compile error under OS X
(cherry picked from commit 621d28adef)
2018-02-19 22:24:57 +01:00
02e910275c Fixed small typos in the SConstruct file.
(cherry picked from commit b92c5669de)
2018-02-19 22:23:38 +01:00
285f47f037 Added return true o collide when no rusult is NULL
(cherry picked from commit f48845428d)
2018-02-19 22:21:58 +01:00
9fb843db06 Added "allow_reselect" property to ItemList and enabled it for the method/help lists.
(cherry picked from commit 4dbf6ac1b8)
2018-02-19 22:21:14 +01:00
4bdcee2b9d [X11] Improving error detection in move_to_trash
(cherry picked from commit 268d7c7c5b)
2018-02-19 22:20:06 +01:00
fd033473c7 Fix broken APK expansion due to missed option renames
Command line options were refactored for 3.0 to follow the common usage
of double-dashed long options, but `--main-pack` went through the cracks.

Fixes #16533.

(cherry picked from commit e3658a6464)
2018-02-19 22:19:08 +01:00
a39930c5b9 Add a function to remove controls from containers
Closes #5968

(cherry picked from commit da69a06253)
2018-02-19 22:18:22 +01:00
c94d8e6577 Fix #16543 (add button to copy error from debugger)
(cherry picked from commit b169b16f98)
2018-02-19 22:17:26 +01:00
eb5e5200cc Fix infinite recursion with editor import plugins
(cherry picked from commit 95f7879923)
2018-02-19 22:16:33 +01:00
d54ac732ae Expose priority and order for custom import plugins
(cherry picked from commit c68948fdfa)
2018-02-19 22:16:13 +01:00
62fcd772be Add Xbox One Elite and Xbox 360 Afterglow pads
(cherry picked from commit ae579a256e)
2018-02-19 22:15:05 +01:00
150423203b Added OS::center_window to center the window precisely on desktop platforms
(cherry picked from commit ea1d726a46)
2018-02-19 22:14:05 +01:00
ef60123938 Add import option "scale_mesh" to obj file importer
The new import option "scale_mesh" allows setting a scale that is applied to the mesh's vertices during import.

(cherry picked from commit 291c1d0f45)
2018-02-19 22:13:46 +01:00
0d03b5f162 Add and use mono build variables with cloned environment.
(cherry picked from commit 70d281b946)
2018-02-19 22:13:46 +01:00
148e059940 Fixed members overview not scrolling to correct line
(cherry picked from commit 4d92c5e1c3)
2018-02-19 22:13:46 +01:00
7af43c4ca3 Fix #16479 (deselect text when jumping to function)
(cherry picked from commit 3094e89782)
2018-02-19 22:13:46 +01:00
5b32be4701 Update an outdated method name in error message
set_enable_monitoring -> set_monitoring

(cherry picked from commit 5e8f7c9782)
2018-02-19 22:13:46 +01:00
47b49200b0 Fixed KinematicBody move_and_slide documentation naming
(cherry picked from commit da81d9f843)
2018-02-19 22:13:46 +01:00
a7d7f763d0 Remove debugging prints related to the asset library
(cherry picked from commit 5513e4e1f9)
2018-02-19 22:13:46 +01:00
eda94419df SpinBoxes calculate correctly their width before first redraw.
(cherry picked from commit fe1ca3c6e6)
2018-02-19 22:13:46 +01:00
e6252bda5e download templates to a file using separate thread
(cherry picked from commit b4f1a035e3)
2018-02-19 22:13:46 +01:00
069658f1be Fixed #15082: line edit emits two "text_changed" signals when pasting while text is selected
(cherry picked from commit 9cd3ed4ace)
2018-02-19 22:13:46 +01:00
a0e59a7259 Fix polygon triangulation failure.
The ear clipping algorithm used to triangulate polygons has a slightly too conservative point-in-triangle test which can, in some configurations prevent it from finding a possible tessellation. Relaxing the test by considering that points exactly on edges don't belong the triangle fixes the issue. Changing the semantic of the test is safe because no other code makes use of it. A more detailed explanation can be found in issue #16395.

Fixes #16395.

(cherry picked from commit 91215e1919)
2018-02-19 22:13:46 +01:00
82b9a13e0c Fix timeline track name overlapping keyframe area
(cherry picked from commit 398f5b74e3)
2018-02-19 22:13:46 +01:00
79ef5f92a9 Remove a few debugging prints
(cherry picked from commit 84267915f5)
2018-02-19 22:13:46 +01:00
5d7867082d Always detect and use hiDPI in the project manager if needed
This makes its hiDPI behavior consistent with the editor.

(cherry picked from commit 55a2bffac9)
2018-02-19 22:13:45 +01:00
fda35b3f42 Draw the Camera gizmo more accurately
The Camera gizmo no longer looks twice as wide as it actually is.
This fixes #16399.

(cherry picked from commit 0d7d293889)
2018-02-19 22:13:45 +01:00
a0e9d751a3 Fixed wrong example in JSONParseResult.
(cherry picked from commit 24e87f97c6)
2018-02-19 22:13:45 +01:00
d4a70c6c08 fix buffer write performance on Windows and Unix
(cherry picked from commit 8315aa40cc)
2018-02-19 22:13:45 +01:00
65aa9063c4 Fix spaces and quotes in external editor flags
(cherry picked from commit fb8d2420b5)
2018-02-19 22:13:45 +01:00
9eb546e7ff drop path text at mouse pos
(cherry picked from commit 06965f2770)
2018-02-19 22:13:45 +01:00
f031e2f665 disable scene tree shortcuts when in a textfield
(cherry picked from commit 4e96e04389)
2018-02-19 22:13:45 +01:00
4bed14f69b Gradient: fix wrong property type
(cherry picked from commit 4f9ef96b54)
2018-02-19 22:13:45 +01:00
91692ce72a Fix gradient texture preview
(cherry picked from commit 3ba43ac975)
2018-02-19 22:13:45 +01:00
05e97db6f2 Fix wrong property type for fixed icon size in ItemList
(cherry picked from commit 331cfc1d18)
2018-02-19 22:13:45 +01:00
617bcd1b91 Capitalized "View" menu options.
(cherry picked from commit b507eeddcc)
2018-02-19 22:13:45 +01:00
34d8625d82 Fix pkgconfig detection of mono
(cherry picked from commit 5920bc6f72)
2018-02-19 22:13:45 +01:00
79b931d093 Fix UX with project settings search functionality
(cherry picked from commit e7b98119df)
2018-02-19 22:13:45 +01:00
9173819b71 [Mono] Basis values now marshalled in the correct order.
(cherry picked from commit 0cc4de1f24)
2018-02-19 22:13:45 +01:00
8787850286 Fix gizmo solid box mesh being added twice
(cherry picked from commit d0a2931cd7)
2018-02-19 22:13:45 +01:00
2515d42a14 [DOCS] parse_json: Objects do not keep key order
Document JSON not guaranteeing key order.

(cherry picked from commit 82b8f1729d)
2018-02-19 22:13:44 +01:00
1a9a40fe31 Make parent folder selectable. Fix #16253
(cherry picked from commit 6e1c02b828)
2018-02-19 22:13:44 +01:00
eda3169cd1 Fixes open button not appearing with multiple selection
Fix #16231

(cherry picked from commit 09c277693e)
2018-02-19 22:13:44 +01:00
d7f73031fb Show default values in docs for GDScript built-in functions
(cherry picked from commit dca2ae78dd)
2018-02-19 22:13:44 +01:00
ba36ef5465 3DEditor: fix selecting node in viewport not update inspector
(cherry picked from commit cfac160f9f)
2018-02-19 22:13:44 +01:00
41f9904e71 3DEditor: fix multiple node selection crash the editor
I'm not sure about this fix. This seems to also fixes the weird
selection bug where when selecting node 1 to 3 it focuses on
2nd node.

(cherry picked from commit 25dd1f0681)
2018-02-19 22:13:44 +01:00
a206d3d2fc Fixes a Gridcontainer wrong children fitting with expanded+non-zero minisize
(cherry picked from commit d1f32708b7)
2018-02-19 22:13:44 +01:00
a6ca62ac79 Fixes a bas resizing with SplitContainer
(cherry picked from commit 30e1e42175)
2018-02-19 22:13:44 +01:00
85dedc09a8 Readd VS.sync and VS.draw to keep compatibility
Those are deprecated as VS.force_sync and VS.force_draw do the same and more explicitly,
but we cannot remove them without marking them as deprecated before that.

Fixes issue introduced in #15892.

(cherry picked from commit fd92e571ac)
2018-02-19 22:13:44 +01:00
9e7c3016d1 Added all missing VisualServer bindings
- Added bindings for multimesh, immediate, skeleton, light, reflection probe, gi probe, lightmap, particles, camera, environment, scenario, instance
- Removed draw and sync, were duplicates of force_* equivalents
- Bumped binders max arguments from 11 to 13
- Wrote some wrappers as not all methods were variant-friendly

(cherry picked from commit e415fd05bb)
2018-02-19 22:13:44 +01:00
906cf28dae Improved WASAPI driver so that it always uses the default audio device
(cherry picked from commit d5afcf7ab1)
2018-02-19 22:13:44 +01:00
801b544ee1 Windows: Fix case of imm32 for case-sensitive MinGW build
Fixes #16713.

(cherry picked from commit 4fa8987494)
2018-02-19 22:13:44 +01:00
097f95993f Windows: implement OS.get_unique_id and OS.set_ime_position
(cherry picked from commit 3be04f73f5)
2018-02-19 22:13:39 +01:00
c04d868476 Make KEY_ESCAPE close all output/debugger docks on bottom
(cherry picked from commit 2ae2735a7a)
2018-02-19 21:01:41 +01:00
50674dbe15 Expose 'lightmap_unwrap' method to the scripting engine.
(cherry picked from commit e3fdacdf90)
2018-02-19 20:57:40 +01:00
71607d9198 Fix bug when launching a game with no main scene
Check for a main scene after loading project settings and exit if there's none (except if launching in editor mode).

(cherry picked from commit 3f8a4cc719)
2018-02-19 20:56:54 +01:00
3548f71cc4 Display path to preloaded res + button to open it
(cherry picked from commit b766a849ad)
2018-02-19 20:56:16 +01:00
a1455f6a03 Change 'Build Project' button style in Mono panel
Address #15208

(cherry picked from commit 484f664331)
2018-02-19 20:50:39 +01:00
f64b68d870 Change primitive meshes acccuracy value
(cherry picked from commit b72c9b85d0)
2018-02-19 20:49:41 +01:00
f1d26c1c72 Re-enabled type icons.
(cherry picked from commit f7547a7f28)
2018-02-19 20:48:36 +01:00
7f5fde6459 Select root node if search_box is empty in create_dialog
(cherry picked from commit 586e735125)
2018-02-19 20:47:44 +01:00
611caa06a5 Fixed android arm64v8
(cherry picked from commit 853b1daa49)
2018-02-19 20:46:49 +01:00
3f6e8d70cf Added async and await as C# keywords.
(cherry picked from commit 3dcf0567a1)
2018-02-05 09:33:01 +01:00
40c779fb70 Mono: Remove automatic script multilevel calls
(cherry picked from commit 84437b4864)
2018-02-05 09:32:29 +01:00
532abf228c Fix texture import spelling
(cherry picked from commit d1a471f909)
2018-02-04 20:11:13 +01:00
248fea2a79 Small fixes for the Control description in the docs.
(cherry picked from commit 5e0821e867)
2018-02-04 20:10:45 +01:00
7de47fbabb Fix inconsistencies and typos in argument names
(cherry picked from commit 08d4bfacaf)
2018-02-04 20:10:13 +01:00
62dc7ba82f Expand project root directory on editor start
close #16232
Option for expanding all directories on start up is a bit tricky and buggy.

(cherry picked from commit 127d1241bd)
2018-02-04 20:09:26 +01:00
4a3a597377 Fix an infinite recursion in the Mathf.Decimals method when using floats.
(cherry picked from commit 2109bd3f97)
2018-02-04 20:08:26 +01:00
501880e9ba Hide button tree when file system dock isn't in split mode
(cherry picked from commit bb936b5503)
2018-02-04 20:07:56 +01:00
bd02969263 Errata fix on Image get_format() description
The description of this function seems to be duplicated from the preceding description.

(cherry picked from commit 9d735ffacb)
2018-02-04 20:07:19 +01:00
0fa4325153 Fix TextEdit current line highlight horizontal offset
(cherry picked from commit ba8c5bff69)
2018-02-04 20:06:46 +01:00
acf01c955f Expose a few GraphEdit methods to script languages
(cherry picked from commit b80bc73a17)
2018-02-04 20:05:47 +01:00
0a75a38db4 Add interface for plugins to enable/disable other plugins
(cherry picked from commit 87be0bc110)
2018-02-04 20:05:12 +01:00
845f44b976 ProjectSettings: Disallow adding properties without name.
(cherry picked from commit d664d6e634)
2018-02-04 20:04:31 +01:00
77ee4ced30 AudioEffectReverb: max predelay_feedback to 0.98
(cherry picked from commit 5a26e0786c)
2018-02-04 20:03:16 +01:00
780a7a281b Viewport doc improvements
(cherry picked from commit ffcbb0c358)
2018-02-04 20:02:38 +01:00
5481ece976 Display set_nodelay to GDScript
Pass enabled arg

Rename set_nodelay to set_no_delay

Add description to the method

Change description

(cherry picked from commit 87adf9cfba)
2018-02-04 20:02:04 +01:00
ef49c166f6 Allow focus on disabled buttons
This behavior better matches other gui toolkits. A selected disabled
button still can't be interacted with but it can now be selected. This
seems to be what QT and GTK do also.

This fixes #16131

(cherry picked from commit 713f190a30)
2018-02-04 20:00:23 +01:00
77cc0a023b attemp to fix #15870
(cherry picked from commit 517ff5c8d7)
2018-02-04 19:59:34 +01:00
1036a76bc5 Fix issue 15895, audio streams don't signalling finished after the first one
if the audio player is set to play again due to the order of calls in
_notification. First it emits the signal, and later it disable the internal
processing regardless what the callback did.

Changed to emit the signal at the end to ensure the changes done at callback
remains.

(cherry picked from commit d588fe2740)
2018-02-04 19:56:37 +01:00
e44bef4404 Update DONORS list
[ci skip]

(cherry picked from commit f13d034485)
2018-02-02 10:07:40 +01:00
c77047d6a3 Ability to import .escn files, which is just a .tscn but with forced import.
This works together with the new Blender to Godot exporter.

(cherry picked from commit 1322ca6fb2)
2018-01-31 01:15:00 +01:00
a34afa3820 Implement OS::get_processor_count() for Windows
Current this is hardcoded as '1' for any platform except Unix. The
little is_wow64() dance is required to get correct output on a 32bit
compiled godot running on 64bit Windows according to MSDN.

This code should be UWP safe but I have no way to test that so it's not
implemented for UWP yet.

(cherry picked from commit b4d369c887)
2018-01-30 20:56:53 +01:00
77d27053c3 [macOS] Strip executable when separate_debug_symbols is set to yes
(cherry picked from commit 9ef0315b06)
2018-01-30 20:56:16 +01:00
187c40d64d Fix wrong return type of xform functions
(cherry picked from commit ebe2337515)
2018-01-30 20:55:41 +01:00
e69b30b276 Fix Copy/Paste problems on X11
The target of the TARGETS type should be XA_ATOM and not XA_TARGETS when
requested. Since we are sending a number of ATOMS the size should be set
to the integer size and not the char size.

The size field of the atoms is also the number of atoms and not the size
of the array. This caused some clients to wrongly interpret the data and
read garbage in the X11 packet.

I also add the more modern representation for UTF-8 and clarify the
error message if a client attempts to request a type we don't know
about.

This fixes #10431

(cherry picked from commit fb60f2dbe6)
2018-01-30 20:55:11 +01:00
99e72894a2 Remote debugger send the real instance of WeakRef referenced to
(cherry picked from commit 10f0451cc2)
2018-01-30 20:54:25 +01:00
258119a9cf Expose audio streams get_length()
(cherry picked from commit 8a9f1c2a5d)
2018-01-30 20:53:37 +01:00
3f6694b894 Bump version to 3.0.1-devel
Onwards, but slowly, towards stability. And the stars.
2018-01-30 20:51:06 +01:00
6127 changed files with 727896 additions and 974614 deletions

View File

@ -4,7 +4,7 @@ environment:
HOME: "%HOMEDRIVE%%HOMEPATH%"
PYTHON: C:\Python27
SCONS_CACHE_ROOT: "%HOME%\\scons_cache"
SCONS_CACHE_LIMIT: 1024
SCONS_CACHE_LIMIT: 512
matrix:
- VS: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
GD_PLATFORM: windows
@ -12,16 +12,12 @@ environment:
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
- pip install --egg scons # it will fail on AppVeyor without --egg flag
- if defined VS call "%VS%" %ARCH% # if defined - so we can also use mingw
before_build:
@ -29,7 +25,7 @@ before_build:
- python --version
- scons --version
- cl.exe
- set "SCONS_CACHE=%SCONS_CACHE_ROOT%\%APPVEYOR_REPO_BRANCH%"
- SET "SCONS_CACHE=%SCONS_CACHE_ROOT%\master"
build_script:
- scons platform=%GD_PLATFORM% target=%TARGET% tools=%TOOLS% debug_symbols=no verbose=yes progress=no gdnative_wrapper=yes
- scons platform=%GD_PLATFORM% target=%TARGET% tools=%TOOLS% verbose=yes progress=no gdnative_wrapper=yes

View File

@ -1,6 +1,6 @@
# 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).
# chosen value in case the base style changes (last sync: Clang 5.0.0).
---
### General config, applies to all languages ###
BasedOnStyle: LLVM
@ -32,7 +32,6 @@ AllowShortIfStatementsOnASingleLine: true
# AfterObjCDeclaration: false
# AfterStruct: false
# AfterUnion: false
# AfterExternBlock: false
# BeforeCatch: false
# BeforeElse: false
# IndentBraces: false
@ -61,7 +60,6 @@ Cpp11BracedListStyle: false
# - foreach
# - Q_FOREACH
# - BOOST_FOREACH
# IncludeBlocks: Preserve
IncludeCategories:
- Regex: '".*"'
Priority: 1
@ -71,7 +69,6 @@ IncludeCategories:
Priority: 3
# IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: true
# IndentPPDirectives: None
IndentWidth: 4
# IndentWrappedFunctionNames: false
# JavaScriptQuotes: Leave
@ -89,10 +86,6 @@ IndentWidth: 4
# PenaltyExcessCharacter: 1000000
# PenaltyReturnTypeOnItsOwnLine: 60
# PointerAlignment: Right
# RawStringFormats:
# - Delimiter: pb
# Language: TextProto
# BasedOnStyle: google
# ReflowComments: true
# SortIncludes: true
# SortUsingDeclarations: true
@ -116,7 +109,6 @@ Standard: Cpp03
---
### ObjC specific config ###
Language: ObjC
Standard: Cpp03
ObjCBlockIndentWidth: 4
# ObjCSpaceAfterProperty: false
# ObjCSpaceBeforeProtocolList: true

View File

@ -9,7 +9,7 @@ insert_final_newline = true
[*.{cpp,hpp,c,h,mm}]
trim_trailing_whitespace = true
[{*.{py,cs},SCsub}]
[*.py]
indent_style = space
indent_size = 4

1
.gitattributes vendored
View File

@ -9,4 +9,3 @@ drivers/* linguist-vendored
*.py eol=lf
*.hpp eol=lf
*.xml eol=lf
*.natvis eol=lf

21
.gitignore vendored
View File

@ -17,8 +17,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
@ -46,7 +44,6 @@ gmon.out
# QT project files
*.config
*.creator
*.creator.*
*.files
*.includes
@ -91,9 +88,6 @@ bld/
*.debug
*.dSYM
# Visual Studio cache/options directory
.vs/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
@ -101,6 +95,9 @@ bld/
# Hints for improving IntelliSense, created together with VS project
cpp.hint
# Visualizers for the VS debugger
*.natvis
#NUNIT
*.VisualState.xml
TestResult.xml
@ -238,7 +235,6 @@ ClientBin/
*.pfx
*.publishsettings
node_modules/
__pycache__/
# KDE
.directory
@ -292,7 +288,6 @@ logo.h
TAGS
!TAGS/
tags
*.tags
!tags/
gtags.files
GTAGS
@ -311,15 +306,5 @@ platform/windows/godot_res.res
/.vs
/.vscode
# Visual Studio Code workspace file
*.code-workspace
# Scons progress indicator
.scons_node_count
# ccls cache (https://github.com/MaskRay/ccls)
.ccls-cache/
# compile commands (https://clang.llvm.org/docs/JSONCompilationDatabase.html)
compile_commands.json

106
.mailmap
View File

@ -1,115 +1,29 @@
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>
Andreas Haas <Hinsbart@users.noreply.github.com>
Andreas Haas <entenflugstuhl@gmail.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>
Ariel Manzur <ariel@okamstudio.com>
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>
Bernhard Liebl <poke1024@gmx.de>
Bernhard Liebl <poke1024@gmx.org>
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 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>
Juan Linietsky <juan@okamstudio.com>
Juan Linietsky <reduz@Juans-MBP.fibertel.com.ar>
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>
Leon Krause <eska@eska.me>
Leon Krause <eska@eska.me> <eska014@users.noreply.github.com>
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>

View File

@ -1,15 +1,13 @@
language: cpp
# OS config, depends on actual 'os' in build matrix
dist: xenial
dist: trusty
sudo: false
env:
global:
- SCONS_CACHE=$HOME/.scons_cache/$TRAVIS_BRANCH
- SCONS_CACHE=$HOME/.scons_cache
- SCONS_CACHE_LIMIT=1024
- OPTIONS="debug_symbols=no verbose=yes progress=no"
- secure: "uch9QszCgsl1qVbuzY41P7S2hWL2IiNFV4SbAYRCdi0oJ9MIu+pVyrQdpf3+jG4rH6j4Rffl+sN17Zz4dIDDioFL1JwqyCqyCyswR8uACC0Rr8gr4Mi3+HIRbv+2s2P4cIQq41JM8FJe84k9jLEMGCGh69w+ibCWoWs74CokYVA="
cache:
directories:
@ -18,96 +16,72 @@ cache:
matrix:
include:
- env: STATIC_CHECKS=yes
os: linux
compiler: gcc
addons:
apt:
sources:
- llvm-toolchain-xenial-6.0
packages:
- clang-format-6.0
- env: PLATFORM=x11 TOOLS=yes TARGET=debug CACHE_NAME=${PLATFORM}-tools-mono-gcc-8 MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" EXTRA_ARGS="module_mono_enabled=yes mono_glue=no warnings=extra werror=yes"
os: linux
compiler: gcc-8
addons:
apt:
sources:
- mono
- ubuntu-toolchain-r-test
packages:
- &gcc8_deps [gcc-8, g++-8]
- &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, nuget]
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
- env: PLATFORM=x11 TOOLS=no TARGET=release CACHE_NAME=${PLATFORM}-clang EXTRA_ARGS="warnings=extra werror=yes"
os: linux
compiler: clang
addons:
apt:
packages:
- *linux_deps
- env: PLATFORM=android TOOLS=no TARGET=release_debug CACHE_NAME=${PLATFORM}-clang EXTRA_ARGS="warnings=extra werror=yes"
os: linux
compiler: clang
- env: PLATFORM=osx TOOLS=yes TARGET=debug CACHE_NAME=${PLATFORM}-tools-clang
os: osx
compiler: clang
- env: PLATFORM=iphone TOOLS=no TARGET=debug CACHE_NAME=${PLATFORM}-clang
os: osx
compiler: clang
- env: PLATFORM=server TOOLS=yes TARGET=release_debug CACHE_NAME=${PLATFORM}-tools-gcc-8 MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" EXTRA_ARGS="warnings=extra werror=yes"
os: linux
compiler: gcc-8
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- *gcc8_deps
- *linux_deps
- env: PLATFORM=x11 TOOLS=no TARGET=release_debug CACHE_NAME=${PLATFORM}-gcc-5
- env: GODOT_TARGET=x11 TOOLS=yes CACHE_NAME=${GODOT_TARGET}-gcc-tools
os: linux
compiler: gcc
addons:
apt:
packages:
- *linux_deps
- env: GODOT_TARGET=x11 TOOLS=no CACHE_NAME=${GODOT_TARGET}-clang
os: linux
compiler: clang
#- env: GODOT_TARGET=windows TOOLS=yes CACHE_NAME=${GODOT_TARGET}-gcc-tools
# os: linux
# compiler: gcc
- env: GODOT_TARGET=android TOOLS=no CACHE_NAME=${GODOT_TARGET}-gcc
os: linux
compiler: gcc
#- env: GODOT_TARGET=osx TOOLS=yes CACHE_NAME=${GODOT_TARGET}-clang-tools
# os: osx
# compiler: clang
#- env: GODOT_TARGET=iphone TOOLS=no CACHE_NAME=${GODOT_TARGET}-clang
# os: osx
# compiler: clang
before_install:
- eval "${MATRIX_EVAL}"
- if [ "$STATIC_CHECKS" = "yes" ]; then
unset SCONS_CACHE;
fi
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-5.0
packages:
- build-essential
- scons
- pkg-config
- libx11-dev
- libxcursor-dev
- libxi-dev
- libxinerama-dev
- libxrandr-dev
- libgl1-mesa-dev
- libglu1-mesa-dev
- libasound2-dev
- libfreetype6-dev
- libssl-dev
# 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
# For style checks.
- clang-format-5.0
install:
- pip install --user scons;
- if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$PLATFORM" = "android" ]; then
- if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$GODOT_TARGET" = "android" ]; then
misc/travis/android-tools-linux.sh;
fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then
export PATH=${PATH}:/Users/travis/Library/Python/2.7/bin;
misc/travis/scons-local-osx.sh;
fi
- if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$PLATFORM" = "android" ]; then
- if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$GODOT_TARGET" = "android" ]; then
misc/travis/android-tools-osx.sh;
fi
before_script:
- if [ "$PLATFORM" = "android" ]; then
- 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;
fi
@ -116,5 +90,5 @@ script:
- if [ "$STATIC_CHECKS" = "yes" ]; then
sh ./misc/travis/clang-format.sh;
else
scons -j2 CC=$CC CXX=$CXX platform=$PLATFORM tools=$TOOLS target=$TARGET $OPTIONS $EXTRA_ARGS;
scons -j2 CC=$CC CXX=$CXX platform=$GODOT_TARGET TOOLS=$TOOLS verbose=yes progress=no openmp=no gdnative_wrapper=yes;
fi

View File

@ -25,144 +25,95 @@ name is available.
## Developers
(in alphabetical order, with over 10 commits excluding merges)
(in alphabetical order, with 10 commits or more excluding merges)
Aaron Franke (aaronfranke)
Alexander Holland (AlexHolly)
Alexey Velikiy (jonyrock)
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)
bruvzg
Cameron Reikes (creikey)
Camille Mohr-Daurat (pouleyKetchoupp)
Błażej Szczygieł (zaps166)
Carl Olsson (not-surt)
Carter Anderson (cart)
Chris Bradfield (cbscribe)
Clay John (clayjohn)
Dana Olson (adolson)
Daniel J. Ramirez (djrm)
Daniel Rakos (aqnuep)
David Sichma (DavidSichma)
Dharkael (lupoDharkael)
Dmitry Koteroff (Krakean)
DualMatrix
Emmanuel Barroga (codecustard)
Дмитрий Сальников (DmitriySalnikov)
Emmanuel Leblond (touilleMan)
Eric Lasota (elasota)
Erik Selecký (rxlecky)
est31
Fabian Mathews (supagu)
Fabio Alessandrelli (Faless)
Ferenc Arn (tagcup)
Franklin Sobrinho (TheHX)
Fredia Huya-Kouadio (m4gr3d)
Geequlim
Gen (dbsGen)
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)
Hein-Pieter van Braam-Stewart (hpvb)
Hein-Pieter van Braam (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)
Jérôme GULLY (Nutriz)
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
Marcelo Fernandez (marcelofg55)
Marc Gilleron (Zylann)
Marcin Zawiejski (dragmz)
Marcelo Fernandez (marcelofg55)
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
Michael Alexsander Silva Dias (YeldhamDev)
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)
Vinzenz Feenstra (vinzenz)
Wilhem Barbier (nounoursheureux)
Will Nations (willnationsdev)
Wilson E. Alvarez (Rubonnek)
Xavier Cho (mysticfall)
yg2f (SuperUserNameMan)
Yuri Roubinsky (Chaosus)
Yuri Roubinski (Chaosus)
Zher Huei Lee (leezh)
ZuBsPaCe
박한얼 (volzhs)
bruvzg
est31
m4nu3lf
marynate
mrezai
rraallvv
romulox-x
sersoong
yg2f (SuperUserNameMan)

View File

@ -4,264 +4,55 @@ 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.1] - 2019-03-13
## [3.0.1] - 2018-02-25
### Added
- OpenGL ES 2.0 renderer.
- [Visual shader editor.](https://godotengine.org/article/visual-shader-editor-back)
- New PBR output nodes.
- Conversion between Vector3 and scalar types is now automatic.
- Ability to create custom nodes via scripting.
- Ports can now be previewed.
- [3D soft body physics.](https://godotengine.org/article/soft-body)
- [3D ragdoll system.](https://godotengine.org/article/godot-ragdoll-system)
- [Constructive solid geometry in 3D.](https://godotengine.org/article/godot-gets-csg-support)
- [2D meshes and skeletal deformation.](https://godotengine.org/article/godot-gets-2d-skeletal-deform)
- [Various improvements to KinematicBody2D.](https://godotengine.org/article/godot-31-will-get-many-improvements-kinematicbody)
- Support for snapping the body to the floor.
- Support for RayCast shapes in kinematic bodies.
- Support for synchronizing kinematic movement to physics, avoiding an one-frame delay.
- WebSockets support using [libwebsockets](https://libwebsockets.org/).
- UPnP support using [MiniUPnP](http://miniupnp.free.fr).
- [Revamped inspector.](https://godotengine.org/article/godot-gets-new-inspector)
- Improved visualization and editing of numeric properties.
- Vector and matrix types can now be edited directly (no pop-ups).
- Subresources can now be edited directly within the same inspector.
- Layer names can now be displayed in the inspector.
- Proper editing of arrays and dictionaries.
- Ability to reset any property to its default value.
- [Improved animation editor.](https://godotengine.org/article/godot-gets-brand-new-animation-editor-cinematic-support)
- Simpler, less cluttered layout.
- New Bezier, Audio and Animation tracks.
- Several key types can be previewed directly in the track editor.
- Tracks can now be grouped and filtered on a per-node basis.
- Copying and pasting tracks between animations is now possible.
- New Capture mode to blend from a node's current value to the first key in a track.
- [Improved animation tree and new state machine.](https://godotengine.org/article/godot-gets-new-animation-tree-state-machine)
- More visual feedback in the blend tree editor.
- 1D and 2D blend spaces are now supported.
- Ability to write custom blending logic.
- Support for root motion.
- [New FileSystem dock.](https://godotengine.org/article/godot-gets-new-filesystem-dock-3-1)
- Unified view of folders and files in the same panel.
- Files can now be marked as favorites, not only folders.
- Files now have icons representing their type, or thumbnail previews when relevant.
- New search field to filter entries in the tree.
- [OpenSimplexNoise and NoiseTexture resources.](https://godotengine.org/article/simplex-noise-lands-godot-31)
- [Optional static typing in GDScript.](https://godotengine.org/article/optional-typing-gdscript)
- Does not currently improve performance, but helps write more robust code.
- Warning system in GDScript.
- Reports potential code issues such as:
- unused variables,
- standalone expressions,
- discarded return values from functions,
- unreachable code after a `return` statement,
-
- Warnings can be disabled in the Project Settings or by writing special comments.
- [GDScript keyword `class_name` to register scripts as classes.](http://docs.godotengine.org/en/latest/getting_started/step_by_step/scripting_continued.html#register-scripts-as-classes)
- Simple expression language independent from GDScript, used by inspector boxes that accept numeric values.
- Can also be used in projects.
- C# projects can now be exported for Windows, Linux, and macOS targets.
- The `server` platform is back as it was in Godot 2.1.
- It is now again possible to run a headless Godot instance on Linux.
- Support for BPTC texture compression on desktop platforms.
- New properties for SpatialMaterial.
- Dithering-based distance fade, for fading materials without making them transparent.
- Disable ambient light on a per-material basis.
- Option to link Mono statically on Windows.
- Unified class and reference search in the editor.
- Revamped TileSet editor with support for undo/redo operations.
- Various quality-of-life improvements to the Polygon2D and TextureRegion editors.
- RandomNumberGenerator class that allows for multiple instances at once.
- Array methods `min()` and `max()` to return the smallest and largest value respectively.
- Dictionary method `get(key[, default])` where `default` is returned if the key does not exist.
- Node method `print_tree_pretty()` to print a graphical view of the scene tree.
- String methods `trim_prefix()`, `trim_suffix()`, `lstrip()`, `rstrip()`.
- OS methods:
- `get_system_time_msecs()`: Return the system time with milliseconds.
- `get_audio_driver_name()` and `get_audio_driver_count()` to query audio driver information.
- `get_video_driver_count()` and `get_video_driver_name()` to query renderer information.
- `center_window()`: Center the window on the screen.
- `move_window_to_foreground()`: Move the window to the foreground.
- StreamPeerTCP method `set_no_delay()` to enable the `TCP_NODELAY` option.
- EditorPlugin method `remove_control_from_container()`.
- Ability to set Godot windows as "always on top".
- Ability to create windows with per-pixel transparency.
- New GLSL built-in functions in the shader language:
- `radians()`
- `degrees()`
- `asinh()`
- `acosh()`
- `atanh()`
- `exp2()`
- `log2()`
- `roundEven()`
- New command-line options:
- `--build-solutions`: Build C# solutions without starting the editor.
- `--print-fps`: Display frames per second to standard output.
- `--quit`: Quit the engine after the first main loop iteration.
- Debugger button to copy error messages.
- Support for `.escn` scenes has been added for use with the new Blender exporter.
- It is now possible to scale an OBJ mesh when importing.
- `popup_closed` signal for `ColorPickerButton`.
- Methods that are deprecated can now print warnings.
- Input actions can now provide an analog value.
- Input actions can now be mapped to either a specific device or all devices.
- DNS resolution for high-level networking.
- Servers can now kick/disconnect peers in high-level networking.
- Servers can now access IP and port information of peers in high-level networking.
- High-level multiplayer API decoupled from SceneTree (see `SceneTree.multiplayer_api`/`SceneTree.custom_multiplayer_api`), can now be extended.
- `Input.set_default_cursor_shape()` to change the default shape in the viewport.
- Custom cursors can now be as large as 256×256 (needed to be exactly 32×32 before).
- Support for radio-looking items with icon in `PopupMenu`s.
- Drag and drop to rearrange Editor docks.
- TileSet's `TileMode` is now exposed to GDScript.
- `OS.get_ticks_usec()` is now exposed to GDScript.
- Normals can now be flipped when generated via `SurfaceTool`.
- TextureProgress bars can now be bilinear (extending in both directions).
- The character used for masking secrets in LineEdit can now be changed.
- Improved DynamicFont:
- DynamicFonts can now use high-quality outlines generated by FreeType.
- DynamicFonts can now have their anti-aliasing disabled.
- DynamicFonts can now have their hinting tweaked ("Normal", "Light" or "None").
- Colored glyphs such as emoji are now supported.
- Universal translation of touch input to mouse input.
- AudioStreamPlayer, AudioStreamPlayer2D, and AudioStreamPlayer3D now have a pitch scale property.
- Support for MIDI input.
- Support for audio capture from microphones.
- `GROW_DIRECTION_BOTH` for Controls.
- Selected tiles can be moved in the tile map editor.
- The editor can now be configured to display the project window on the previous or next monitor (relative to the editor).
- If either end is reached, then the project will start on the last or first monitor (respectively).
- Signal in VideoPlayer to notify when the video finished playing.
- `Image.bumpmap_to_normalmap()` to convert bump maps to normal maps.
- `File.get_path()` and `File.get_path_absolute()`.
- Unselected tabs in the editor now have a subtle background for easier identification.
- The depth fog's end distance is now configurable independently of the far plane distance.
- The alpha component of the fog color can now be used to control fog density.
- The 3D editor's information panel now displays the camera's coordinates.
- New options to hide the origin and viewport in the 2D editor.
- Improved 3D editor grid:
- The grid size and number of subdivisions can now be configured.
- Its primary and secondary colors can now also be changed.
- <kbd>Ctrl</kbd> now toggles snapping in the 3D viewport.
- Find & replace in files (<kbd>Ctrl + Shift + F</kbd> by default).
- Batch node renaming tool (<kbd>Ctrl + F2</kbd> by default).
- More editor scaling options to support HiDPI displays.
- 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.
- Buttons in the editor to open common directories in the OS file manager:
- project data directory,
- user data directory,
- user settings directory.
- Projects can now be sorted by name or modification date in the project manager.
- Projects can now be imported from ZIP archives in the project manager.
- Improved autocompletion.
- Keywords are now present in autocompletion results.
- `editor` and `standalone` feature tags to check whether the project is running from an editor or non-editor binary.
- `android_add_asset_dir("...")` method to Android module Gradle build configuration.
- **iOS:** Support for exporting to the iPhone X.
- **iOS:** Readded support for in-app purchases.
### Changed
- [Built-in vector types now use copy-on-write mode as originally intended](https://godotengine.org/article/why-we-broke-your-pr), resulting in increased engine performance.
- The [mbedtls](https://tls.mbed.org/) library is now used instead of OpenSSL.
- [Renamed several core files](https://github.com/godotengine/godot/pull/25821).
- Third-party modules may have to be updated to reflect this.
- SSL certificates are now bundled in exported projects unless a custom bundle is specified.
- Improved buffer writing performance on Windows and Linux.
- Removed many debugging prints in the console.
- Export templates now display an error dialog if no project was found when starting.
- DynamicFont oversampling is now enabled by default.
- Nodes' internal logic now consistently use internal physics processing.
- Allow attaching and clearing scripts on multiple nodes at once.
- Default values are no longer saved in scene and resource files.
- The selection rectangle of 2D nodes is now hidden when not pertinent (no more rectangle for collision shapes).
- SSE2 is now enabled in libsquish, resulting in improved S3TC encoding performance.
- Tangent and binormal coordinates are now more consistent across mesh types (primitive/imported), resulting in more predictable normal map and depth map appearance.
- Better defaults for 3D scenes.
- The default procedural sky now has a more neutral blue tone.
- The default SpatialMaterial now has a roughness value of 1 and metallic value of 0.
- The fallback material now uses the same values as the default SpatialMaterial.
- Text editor themes are now sorted alphabetically in the selection dropdown.
- The 3D manipulator gizmo now has a smoother, more detailed appearance.
- The 3D viewport menu button now has a background to make it easier to read.
- QuadMeshes are now built using two triangles (6 vertices) instead of one quad (4 vertices).
- This was done because quads are deprecated in OpenGL.
- Controls inside containers are no longer movable or resizable but can still be selected.
- The `is` GDScript keyword can now be used to compare a value against built-in types.
- Exported variables with type hints are now always initialized.
- For example, `export(int) var a` will be initialized to `0`.
- Named enums in GDScript no longer create script constants.
- This means `enum Name { VALUE }` must now be accessed with `Name.VALUE` instead of `VALUE`.
- Cyclic references to other scripts with `preload()` are no longer allowed.
- `load()` should be used in at least one of the scripts instead.
- `switch`, `case` and `do` are no longer reserved identifiers in GDScript.
- Shadowing variables from parent scopes is no longer allowed in GDScript.
- Function parameters' default values can no longer depend on other parameters in GDScript.
- Indentation guides are now displayed in a more subtle way in the script editor.
- Indentation guides are now displayed when indenting using spaces.
- Multi-line strings are now highlighted as strings rather than as comments in the script editor.
- This is because GDScript does not officially support multiline comments.
- Increased the script editor's line spacing (4 pixels → 6 pixels).
- Increased the caret width in the script editor (1 pixel → 2 pixels).
- The project manager window is now resized to match the editor scale.
- The asset library now makes use of threading, making loading more responsive.
- Line spacing in the script editor, underlines and caret widths are now resized to match the editor scale.
- Replaced editor icons for checkboxes and radio buttons with simpler designs.
- Tweaked the editor's success, error, and warning text colors for better readability and consistency.
- **Android:** Custom permissions are now stored in an array and their amount is no longer limited to 20.
- Custom permissions will have to be redefined in projects imported from older versions.
- **Android:** Provide error details when an in-app purchase fails.
- **Linux:** `OS.alert()` now uses Zenity or KDialog if available instead of xmessage.
- **Mono:** Display stack traces for inner exceptions.
- **Mono:** Bundle `mscorlib.dll` with Godot to improve portability.
### Removed
- Removed the RtAudio backend on Windows in favor of WASAPI, which is the default since 3.0.
- **macOS:** Support for 32-bit and fat binaries.
- 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
- [`move_and_slide()` now behaves differently at low velocities](https://github.com/godotengine/godot/issues/21683), which makes it function as originally intended.
- AnimatedSprite2D's `animation_finished` signal is now triggered at the end of the animation, instead of as soon as the last frame displays.
- Audio buses can now be removed in the editor while they are used by AudioStreamPlayer2D/3D nodes.
- 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 a built-in GDScript file even if the filename suggested already exists.
- Show tooltips in the editor when physics object picking is disabled.
- Button shortcuts can now be triggered by gamepad buttons.
- Fix a serialization bug that could cause TSCN files to grow very large.
- Gizmos are now properly hidden on scene load if the object they control is hidden.
- Camera gizmos in the 3D viewport no longer look twice as wide as they actually are.
- Copy/pasting from the editor on X11 will now work more reliably.
- `libgcc_s` and `libstdc++` are now linked statically for better Linux binary portability.
- The FPS cap set by `force_fps` in the Project Settings is no longer applied to the editor.
- Low FPS caps no longer cause the editor to feel sluggish.
- hiDPI is now detected and used if needed in the project manager.
- The Visual Studio Code external editor option now recognizes more binary names such as `code-oss`, making detection more reliable.
- The `-ffast-math` flag is no longer used when compiling Godot, resulting in increased floating-point determinism.
- Fix spelling of `apply_torque_impulse()` and deprecate the misspelled method.
- Escape sequences like `\n` and `\t` are now recognized in CSV translation files.
- Remove spurious errors when using a PanoramaSky without textures.
- 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.
- Android exporter no longer writes unnecessary permissions to the exported APK.
- Debugger "focus stealing" now works more reliably.
- Subresources are now always saved when saving a scene.
- Many fixes related to importers (glTF, Collada, audio), physics (Bullet), Mono/C#, GDNative, Android/iOS.
- **Mono:** Many fixes and improvements to C# support (including a `[Signal]` attribute).
- **WebAssembly:** Supply proper CORS headers.
### Security
- Fixed a security issue relating to deserializing Variants.
## [3.0] - 2018-01-29
@ -306,7 +97,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
- 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/getting_started/workflow/export/feature_tags.html) in the Project Settings, for custom per-platform settings.
- [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.
@ -396,5 +187,4 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
- HTML5 export using asm.js.
- Only WebAssembly is supported now, since all browsers supporting WebGL 2.0 also support WebAssembly.
[Unreleased]: https://github.com/godotengine/godot/compare/3.0-stable...HEAD
[3.0]: https://github.com/godotengine/godot/compare/2.1-stable...3.0-stable

View File

@ -1,57 +0,0 @@
# Lines starting with '#' are comments.
# Each line is a file pattern followed by one or more owners.
# Owners can be @users, @org/teams or emails
/core/ @reduz
/doc/ @godotengine/documentation
doc_classes/* @godotengine/documentation
# Rendering
/drivers/gl_context/ @reduz
/drivers/gles2/ @reduz
/drivers/gles3/ @reduz
# Audio
/drivers/alsa/ @marcelofg55
/drivers/alsamidi/ @marcelofg55
/drivers/coreaudio/ @marcelofg55
/drivers/coremidi/ @marcelofg55
/drivers/pulseaudio/ @marcelofg55
/drivers/wasapi/ @marcelofg55
/drivers/winmidi/ @marcelofg55
/drivers/xaudio2/ @marcelofg55
# Porting
/drivers/unix/ @reduz @hpvb
/drivers/windows/ @reduz @hpvb
/editor/icons/ @djrm
/main/ @reduz
/misc/ @akien-mga
/modules/bullet/ @AndreaCatania
/modules/csg/ @reduz @BastiaanOlij
/modules/enet/ @godotengine/network
/modules/gdnative/ @karroffel
/modules/gdnative/*arvr/ @BastiaanOlij
/modules/gdscript/ @reduz @vnen @bojidar-bg
/modules/mbedtls/ @godotengine/network
/modules/mobile_vr/ @BastiaanOlij
/modules/mono/ @neikeq
/modules/opensimplex/ @JFonS
/modules/regex/ @LeeZH
/modules/upnp/ @godotengine/network
/modules/websocket/ @godotengine/network
/platform/javascript/ @eska014
/platform/uwp/ @vnen
/scene/main/ @reduz
/server/physics*/ @reduz @AndreaCatania
/server/visual*/ @reduz @karroffel
/thirdparty/ @akien-mga

View File

@ -59,8 +59,7 @@ by drag and dropping the file in the GitHub edition field.
If you want to add new engine functionalities, please make sure that:
* This functionality is desired, which means that it solves a common use case
that several users will need in their real-life projects.
* 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).
@ -71,23 +70,11 @@ 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.
[This blog post](https://godotengine.org/article/will-your-contribution-be-merged-heres-how-tell)
outlines the process used by core developers when assessing PRs. We strongly
recommend that you have a look at it to know what's important to take into
account for a PR to be considered for merging.
In addition to the following tips, also take a look at the
[Engine development guide](https://docs.godotengine.org/en/latest/development/cpp/)
for an introduction to developing on Godot.
The [Contributing docs](http://docs.godotengine.org/en/latest/community/contributing/index.html)
also have important information on the PR workflow and the code style we use.
#### 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
@ -102,9 +89,6 @@ Internet).
This git style guide has some good practices to have in mind:
[Git Style Guide](https://github.com/agis-/git-style-guide)
See our [PR workflow](http://docs.godotengine.org/en/latest/community/contributing/pr_workflow.html)
documentation for tips on using Git, amending commits and rebasing branches.
#### Format your commit logs with readability in mind
The way you format your commit logs is quite important to ensure that the
@ -150,10 +134,6 @@ 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.
You can also help translate [Godot's
documentation](https://hosted.weblate.org/projects/godot-engine/godot-docs/)
on Weblate.
## Communicating with developers
The Godot Engine community has [many communication

File diff suppressed because it is too large Load Diff

530
DONORS.md
View File

@ -13,508 +13,224 @@ generous deed immortalized in the next stable release of Godot Engine.
## Platinum sponsors
Enjin Coin <https://enjincoin.io>
Heroic Labs <https://heroiclabs.com>
Interblock <http://interblockgaming.com>
## Gold sponsors
Gamblify <https://www.gamblify.com>
Image Campus <https://www.imagecampus.edu.ar>
Moonwards <https://www.moonwards.com>
GameDev.TV <https://www.gamedev.tv>
## Mini sponsors
AD Ford
Alan Beauchamp
Anandarup Mallik
Andrew Dunai
Andreas
Brandon Lamb
Christopher Montesano
Christian Uldall Pedersen
Christopher Igoe
Christoph Woinke
Darkhan Baimyrza
Denis Malyavin
Edward Flick
Gamechuck
GameDev.net
GameDev.tv
Grady
E Hewert
Hein-Pieter van Braam
Jacob McKenney
Javary Co.
Jeffery Chiu
Jeppe Zapp
John Benard (Linuxydable)
Justin Arnold
Justo Delgado Baudí
Kyle Szklenski
Leonard Meagher
Mariano Suligoy
Jamal Alyafei
Jay Sistar
Jordan M Lucas
Matthieu Huvé
Maxim Karsten
Mike King
Nathan Warden
Neal Gompa (Conan Kudo)
ScottMakesGames
Pascal Julien
Ruslan Mustakov
Slobodan Milnovic
Stephan Lanfermann
Steve
Tristan Pemble
VilliHaukka
Stoney Meyerhoeffer
Thomas Mathews
## Gold donors
Andrei
3Dexplorer
Alexander Otto
Asdf
cheese65536
Dave
David Gehrig
David Snopek
Ed Morley
Florian Krick
Florian Rämisch
GiulianoB
Jakub Grzesik
K9Kraken
Jake Bo
Manuele Finocchiaro
Officine Pixel S.n.c.
Retro Village
Ronan Zeegers
Sofox
Taylor Ritenour
Rémi Verschelde
Zaven Muradyan
_
Alexander Trey Saunders
Asher Glick
Allen Schade
Andreas Schüle
Austen McRae
Bernhard Werner
beVR
Brian van der Stel
Carlo Cabanilla
Daniel James
David Giardi
Default Name
Florian Breisch
Gamejunkey
Gero
Javier Roman
Jay Horton
Joel Höglund
Jon Woodward
Jose Fernando Alexandre
Karl Werf
Klavdij Voncina
Lex Steers
Luke
Maciej Pendolski
Matthew Hillier
Mored1984
Paul LaMotte
Péter Magyar
Rob Messick
Ryan Badour
Scott Wadden
Sergey
Shawn Yu
The Architect
thechris
Tom Langwaldt
tukon
Unseen Domains
Benjamin Botwin
Bernhard Liebl
Johannes Wuensch
Josep G. Camarasa
Kris Michael
Libre-Dépanne
Ranoller
Svenne Krap
Timothy Hagberg
Alex Khayrullin
Branwyn Tylwyth
Chris Goddard
BanjoNode2D
Brandon
Chris Serino
Christian Padilla
Conrad Curry
Craig Smith
Darrian Little
Ivan Trombley
Jakub Dering
Joan Fons
Joshua Flores
Krzysztof Jankowski
Lord Bloodhound
Nathan Lundquist
Pascal Grüter
Petr Malac
Rami
Reneator
Rob
David Churchill
Dean Harmon
Dexter Miguel
Garrett Dockins
Guilherme Felipe de C. G. da Silva
Harman Bains
Karsten Bock
Laurence Bannister
Robert Willes
Ronnie Ashlock
Robin Arys
ScottMakesGames
Testus Maximus
Thomas Bjarnelöf
Vincent Henderson
Wojciech Chojnacki
Xavier PATRICELLI
Xavier Tan
Zaq Poi
Adam Neumann
Alexander J Maynard
Alexey Dyadchenko
Andreas Funke
André Frélicot
andres eduardo lopez
Andrew Bowen
aoshiwik
Ben Botwin
Carlos de Sousa Marques
Chase Taranto
Chris Petrich
Christian Leth Jeppesen
Christoph Schröder
Amanda Haldy
Andreas Haas
Arnaud Verstuyf
Chris Brown
Chris Wilson
Cody Parker
D
Daniel Eichler
David White
Daniel Eliasinski
Eric Monson
Erik Hatfield
Eugenio Hugo Salgüero Jáñez
Fain
Ezra Theunissen
flesk
gavlig
François Cantin
GGGames.org
Guilherme Felipe de C. G. da Silva
Heath Hayes
Hysteria
Idzard Kwadijk
Jared White
Jeremy Sims
Jerry Ling
Joe Flood
Jose Malheiro
Joshua Lesperance
Juan T Chen
Juan Velandia
Jeppe Zapp
Jeremi Biernacki
joe513
Juraj Móza
Kasper Jeppesen
kinfox
Maarten Elings
Marcelo Dornbusch Lopes
Markus Fehr
Justin Arnold
Justo Delgado Baudí
Leandro Voltolino
Lisandro Lorea
Markus Wiesner
Martin Eigel
Marvin
Matt Eunson
Max Bulai
MuffinManKen
Nick Nikitin
Oliver Dick
Patrick Ting
Paul Hocker
Paul Von Zimmerman
Pablo Cholaky
Paolo Munoz
Patrick Schnorbus
Pete Goodwin
pl
Ranoller
Robert Larnach
Robin Arys
Rocknight Studios
Romildo Franco
Ryan
Samuel Judd
Scott Pilet
spilldata
Stoned Xander
TheLevelOfDetail .
Thomas Krampl
Thomas Kurz
Tobias Bocanegra
Urho
Zie Weaver
Rami
Ryan Estes
Ted
Travis Womack
Trent McPheron
## Silver donors
1D_Inc
Abraham Haskins
Adam
Adam Brunnmeier
Adam Carr
Adam Long
Adam Nakonieczny
Adam N Webber
Adam Smeltzer
Adisibio
Adrian Demetrescu
Agustinus Arya
Aidan O'Flannagain
Aki Mimoto
Albin Jonasson Svärdsby
Alder Stefano
Alessandro Senese
Alexandre
Alex Davies-Moore
Allen Schade
Andreas Evers
Andreas Krampitz
André Simões
Andrés Rodríguez
Álvaro Domínguez López
Andrea Badii
Andrew Thomas
Andrzej Skalski
Angelos Arnaoutis
Anthony Bongiovanni
Anthony Staunton
Anton Kurkin
AP Condomines
Arda Erol
Arseniy M
Arthur S. Muszynski
Atilla Kiran
Aubrey Falconer
Avencherus
B A
Balázs Batári
Bastian Böhm
Benedikt
Ben G
Ben Phelan
Benjamin Beshara
Ben Vercammen
Bernd Jänichen
Black Block
Blair Allen
Bobby CC Wong
Bryanna M
Bryan Stevenson
Carl van der Geest
Carwyn Edwards
Casey M.
Chris Brown
Chris Chapin
Casey Foote
Christian Baune
Christian Chipont
Christian Winter
Christoffer Sundbom
Christopher Schmitt
Clay Heaton
Collin Shooltz
Daniel Johnson
Daniel Kimblad
DanielMaximiano
Daniel Pontillo
Daniel Reed
Daniel Egger
Daniel Kaplan
Daniel Langegger
Daniel Mircea
David Cravens
David May
David Rapisarda
David Woodard
Dominic Cooney
Diego Moreira Guimarães
Dominik Wetzel
Donn Eddy
Donovan Hutcheon
Dragontrapper
Dr Ewan Murray
Duobix
Eduardo Teixeira
Edward Herbert
Egon Elbre
Ellen Marie Dash
Elmeri '- Duy Kevin Nguyen
Emanuel Kotzayan
Ennemoser Ernst
Eric Ellingson
Eric Martini
Eric Williams
Erkki Seppälä
EugeneTel
Evan Rose
Felix Kollmann
Flaredown
Florian Richer
FuDiggity
Fabian Becker
fengjiongmax
Francesco Lisi
Fredy Romero Sam
G3Dev sàrl
Gadzhi Kharkharov
gamedev by Celio
Gary Hulst
George Marques
gmmath
Greg Olson
GREGORY C FEIN
Greg P
Greyson Richey
Geequlim
Gerrit Großkopf
Gilberto K. Otubo
Guldoman
Hal A
HeartBeast
Heribert Hirth
Hiroshi Naruo
Hunter Jones
Hylpher
Iiari
IndustrialRobot
Isaac Morton
Jack Newley
Jaiden Gerig
Jaime Ruiz-Borau Vizárraga
Jako Danar
James A F Manley
Jannik Gröger
Jax
Jed
Jed Rose
Jeff Hungerford
Jeff Nyte
Jennifer Graves
Jeremy Kahn
Jesse Dubay
Joao Senerchia
Joe Alden
Joel Fivat
Joel Setterberg
Johannes Wuensch
Jomei Jackson
Jonas Rudlang
Jonas Yamazaki
Jonathan G
Jonathan Nieto
Jonathon
Jon Bonazza
Jon Sully
Jose Aleman
Jose Andrés Mejias Rojas
Jose C. Rubio
Joseph Catrambone
Juanfran
Josh 'Cheeseness' Bush
Juan Negrier
Judd
JuDelCo
Julian Murgia
JungleRobba
Justin Spedding
Kaiser Bald0
Kamuna
Kauzig
KC Chan
Keedong Park
Keith Bradner
Kevin McPhillips
kickmaniac
Kiyohiro Kawamura (kyorohiro)
Kjetil Haugland
Klagsam
Klassix
KR McGinley
KsyTek Games
Kuan Cheang
kycho
Levi Lindsey
Kevin Boyer
Kevin Kamper Meejach Petersen
Klavdij Voncina
Lars pfeffer
Linus Lind Lundgren
Lionel Gaillard
LunaticInAHat
Lurkars
Macil
Major Haul
Malcolm
Malik Ahmed
Malik Nejer
Marcus Richter
Markus Michael Egger
Martin Candela
Martin Holas
Martin Liška
Matthew Little
Matti Pohjanvirta
Maxime Blade
Maxwell
medecau
Melissa Mears
M H
magodev
Martin Eigel
Martin Novák
Matthew Fitzpatrick
Matthias Hölzl
Maurice Meysel
Max R.R. Collada
memoryruins
mhilbrunner
Michael Dürwald
Michael Gringauz
Michael Haney
Michael Labbe
Mikael Olsson
Mikayla
Mike Birkhead
Mitchell J. Wagner
MoM
Nathan Fish
Natrim
monokrome
Moritz Laass
nee
Neil Blakey-Milner
Nerdforge
Nicholas
Nicholas Bettencourt
Nick Macholl
Niclas Eriksen
Nicolás Montaña
Nicolas SAN AGUSTIN
Nima Farid
Nithin Jino
NZ
Oleg Reva
Olivier
Omar Delarosa
Oscar Norlander
Nik Lee
Niko Leopold
Noi Sek
Oleg Tyshchenko
Pablo Seibelt
Pan Ip
Pat LaBine
Patrick Nafarrete
Paul Gieske
Patric Vormstein
Paul Mason
Paweł Kowal
Penguin
Petrus Prinsloo
Philip Cohoe
Pierre-Igor Berthet
Pitsanu Tongprasin
Point08
Poryg
Rafa Laguna
rainerLinux
Raphael Leroux
Remi Rampin
Rémi Verschelde
Rezgi
Ricardo Alcantara
Richard Diss
Richard Ivánek
Richard Patching
Robert Farr (Larington)
Robert Hernandez
Rodrigo Loli
Pietro Vertechi
Piotr Kaczmarski
Richman Stewart
Rodolfo Baeza
Roger Burgess
Roger Smith
Roland Rząsa
Roman Tinkov
Ronan Jouchet
Ryan Groom
Ryan Hentz
Sam.C
Sam Edson
Samuele Zolfanelli
Sanka.X
Sasori Olkof
Scott D. Yelich
Sebastian Michailidis
sgnsajgon
Shane
Shane Sicienski
Shane Spoor
Simon Ledam
Simon Wenner
SK
smbe19
Sootstone
Svenne Krap
tezuvholovdr
thomas
Thomas Bechtold
Thomas Kelly
tiansheng li
Tim Drumheller
Timothy B. MacDonald
TJRHTK
Tobbun
Tom Fulp
Tom Glenn
Torsten Crass
Travis O'Brien
Trent Skinner
Troy Bonneau
Tryggve Sollid
Turgut Temucin
Tyler Stafos
Stephen Traskal
Theo Cranmore
Thomas Bell
Thomas Herzog & Xananax
Tom Larrow
UltyX
Vaiktorg
Victor
Vigilant Watch
Vincent Cloutier
waka nya
Wayne Haak
werner mendizabal
Wiley Thompson
Will
William Hogben
Wout Standaert
Wyatt Goodin
Yegor
蕭惟允
Yu He
## Bronze donors

View File

@ -1,5 +1,5 @@
Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.
Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)
Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.
Copyright (c) 2014-2018 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

View File

@ -26,7 +26,7 @@ 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.
![Screenshot of a 3D scene in Godot Engine](https://download.tuxfamily.org/godotengine/media/screenshots/editor_3d_fracteed.jpg)
![Screenshot of a 3D scene in Godot Engine](http://download.tuxfamily.org/godotengine/media/screenshots/editor_3d_fracteed.jpg)
### Getting the engine
@ -37,10 +37,10 @@ Official binaries for the Godot editor and the export templates can be found
#### Compiling from source
[See the official docs](https://docs.godotengine.org/en/latest/development/compiling/)
[See the official docs](http://docs.godotengine.org/en/latest/development/compiling/)
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 +49,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](https://docs.godotengine.org).
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](https://docs.godotengine.org/en/latest/classes/)
The [class reference](http://docs.godotengine.org/en/latest/classes/)
is also accessible from within the engine.
The official demos are maintained in their own [GitHub repository](https://github.com/godotengine/godot-demo-projects)

View File

@ -2,15 +2,16 @@
EnsureSConsVersion(0, 98, 1)
# System
import glob
import os
import sys
# Local
import string
import os
import os.path
import glob
import sys
import methods
import gles_builders
from platform_methods import run_in_subprocess
# moved below to compensate with module version string
# methods.update_version()
# scan possible build platforms
@ -22,19 +23,22 @@ active_platforms = []
active_platform_ids = []
platform_exporters = []
platform_apis = []
global_defaults = []
for x in sorted(glob.glob("platform/*")):
for x in glob.glob("platform/*"):
if (not os.path.isdir(x) or not os.path.exists(x + "/detect.py")):
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()):
active_platforms.append(detect.get_name())
active_platform_ids.append(x)
@ -49,23 +53,27 @@ for x in sorted(glob.glob("platform/*")):
module_list = methods.detect_modules()
# print "Detected Platforms: "+str(platform_list)
methods.save_active_platforms(active_platforms, active_platform_ids)
custom_tools = ['default']
platform_arg = ARGUMENTS.get("platform", ARGUMENTS.get("p", False))
if os.name == "nt" and (platform_arg == "android" or ARGUMENTS.get("use_mingw", False)):
custom_tools = ['mingw']
elif platform_arg == 'javascript':
# Use generic POSIX build toolchain for Emscripten.
custom_tools = ['cc', 'c++', 'ar', 'link', 'textfile', 'zip']
if (os.name == "posix"):
pass
elif (os.name == "nt"):
if (os.getenv("VCINSTALLDIR") == None or platform_arg == "android" or platform_arg == "javascript"):
custom_tools = ['mingw']
env_base = Environment(tools=custom_tools)
if 'TERM' in os.environ:
env_base['ENV']['TERM'] = os.environ['TERM']
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 = []
@ -73,7 +81,6 @@ 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 = []
@ -85,14 +92,20 @@ env_base.use_ptrcall = False
env_base.split_drivers = False
env_base.split_modules = False
env_base.module_version_string = ""
env_base.msvc = False
# 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
@ -112,8 +125,6 @@ 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.__class__.disable_warnings = methods.disable_warnings
env_base["x86_libtheora_opt_gcc"] = False
env_base["x86_libtheora_opt_vc"] = False
@ -124,6 +135,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"):
@ -132,57 +144,52 @@ if profile:
opts = Variables(customs, ARGUMENTS)
# Target build options
opts.Add('arch', "Platform-dependent architecture (arm/arm64/x86/x64/mips/...)", '')
opts.Add(EnumVariable('bits', "Target platform bits", 'default', ('default', '32', '64')))
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('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(EnumVariable('optimize', "Optimization type", 'speed', ('speed', 'size')))
opts.Add(BoolVariable('tools', "Build the tools (a.k.a. the Godot editor)", True))
opts.Add(BoolVariable('use_lto', 'Use link-time optimization', False))
opts.Add(BoolVariable('use_precise_math_checks', 'Math checks use very precise epsilon (useful to debug the engine)', False))
opts.Add(BoolVariable('tools', "Build the tools a.k.a. the Godot editor", True))
opts.Add(BoolVariable('use_lto', 'Use linking time optimization', False))
# Components
opts.Add(BoolVariable('deprecated', "Enable deprecated features", True))
opts.Add(BoolVariable('gdscript', "Enable GDScript support", True))
opts.Add(BoolVariable('minizip', "Enable ZIP archive support using minizip", True))
opts.Add(BoolVariable('xaudio2', "Enable the XAudio2 audio driver", False))
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))
# Advanced options
opts.Add(BoolVariable('verbose', "Enable verbose output for the compilation", False))
opts.Add(BoolVariable('progress', "Show a progress indicator during compilation", True))
opts.Add(EnumVariable('warnings', "Set the level of warnings emitted during compilation", 'all', ('extra', 'all', 'moderate', 'no')))
opts.Add(BoolVariable('werror', "Treat compiler warnings as errors. Depends on the level of warnings set with 'warnings'", False))
opts.Add(BoolVariable('dev', "If yes, alias for verbose=yes warnings=all", False))
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('extra_suffix', "Custom extra suffix added to the base filename of all generated binary files", '')
opts.Add(BoolVariable('vsproj', "Generate a Visual Studio solution", False))
opts.Add(EnumVariable('macports_clang', "Build using Clang from MacPorts", 'no', ('no', '5.0', 'devel')))
opts.Add(BoolVariable('disable_3d', "Disable 3D nodes for a smaller executable", False))
opts.Add(BoolVariable('disable_advanced_gui', "Disable advanced GUI nodes and behaviors", False))
opts.Add(BoolVariable('no_editor_splash', "Don't use the custom splash screen for the editor", False))
opts.Add('system_certs_path', "Use this path as SSL certificates default for editor (for package maintainers)", '')
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')))
# Thirdparty libraries
opts.Add(BoolVariable('builtin_bullet', "Use the built-in Bullet library", True))
opts.Add(BoolVariable('builtin_certs', "Bundle default SSL certificates to be used if you don't specify an override in the project settings", True))
opts.Add(BoolVariable('builtin_enet', "Use the built-in ENet library", True))
opts.Add(BoolVariable('builtin_freetype', "Use the built-in FreeType library", True))
opts.Add(BoolVariable('builtin_libogg', "Use the built-in libogg library", True))
opts.Add(BoolVariable('builtin_libpng', "Use the built-in libpng library", True))
opts.Add(BoolVariable('builtin_libtheora', "Use the built-in libtheora library", True))
opts.Add(BoolVariable('builtin_libvorbis', "Use the built-in libvorbis library", True))
opts.Add(BoolVariable('builtin_libvpx', "Use the built-in libvpx library", True))
opts.Add(BoolVariable('builtin_libwebp', "Use the built-in libwebp library", True))
opts.Add(BoolVariable('builtin_libwebsockets', "Use the built-in libwebsockets library", True))
opts.Add(BoolVariable('builtin_mbedtls', "Use the built-in mbedTLS library", True))
opts.Add(BoolVariable('builtin_miniupnpc', "Use the built-in miniupnpc library", True))
opts.Add(BoolVariable('builtin_opus', "Use the built-in Opus library", True))
opts.Add(BoolVariable('builtin_pcre2', "Use the built-in PCRE2 library)", True))
opts.Add(BoolVariable('builtin_recast', "Use the built-in Recast library", True))
opts.Add(BoolVariable('builtin_squish', "Use the built-in squish library", True))
opts.Add(BoolVariable('builtin_xatlas', "Use the built-in xatlas library", True))
opts.Add(BoolVariable('builtin_zlib', "Use the built-in zlib library", True))
opts.Add(BoolVariable('builtin_zstd', "Use the built-in Zstd library", True))
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))
# Compilation environment setup
opts.Add("CXX", "C++ compiler")
@ -193,6 +200,7 @@ opts.Add("CXXFLAGS", "Custom flags for the C++ compiler")
opts.Add("CFLAGS", "Custom flags for the C compiler")
opts.Add("LINKFLAGS", "Custom flags for the linker")
# add platform specific options
for k in platform_opts.keys():
@ -203,7 +211,7 @@ for k in platform_opts.keys():
for x in module_list:
module_enabled = True
tmppath = "./modules/" + x
sys.path.insert(0, tmppath)
sys.path.append(tmppath)
import config
enabled_attr = getattr(config, "is_enabled", None)
if (callable(enabled_attr) and not config.is_enabled()):
@ -217,36 +225,33 @@ Help(opts.GenerateHelpText(env_base)) # generate help
# add default include paths
env_base.Append(CPPPATH=['#editor', '#'])
env_base.Append(CPPPATH=['#core', '#core/math', '#editor', '#drivers', '#'])
# configure ENV for platform
env_base.platform_exporters = platform_exporters
env_base.platform_apis = platform_apis
if (env_base["use_precise_math_checks"]):
env_base.Append(CPPDEFINES=['PRECISE_MATH_CHECKS'])
"""
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(CPPDEFINES=['DEBUG_MEMORY_ALLOC','DISABLE_FORCED_INLINE'])
# The two options below speed up incremental builds, but reduce the certainty that all files
# will properly be rebuilt. As such, we only enable them for debug (dev) builds, not release.
# 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.Append(CPPFLAGS=['-DDEBUG_MEMORY_ALLOC'])
env_base.Append(CPPFLAGS=['-DSCI_NAMESPACE'])
if (env_base['no_editor_splash']):
env_base.Append(CPPDEFINES=['NO_EDITOR_SPLASH'])
env_base.Append(CPPFLAGS=['-DNO_EDITOR_SPLASH'])
if not env_base['deprecated']:
env_base.Append(CPPDEFINES=['DISABLE_DEPRECATED'])
env_base.Append(CPPFLAGS=['-DDISABLE_DEPRECATED'])
env_base.platforms = {}
selected_platform = ""
if env_base['platform'] != "":
@ -255,9 +260,10 @@ elif env_base['p'] != "":
selected_platform = env_base['p']
env_base["platform"] = selected_platform
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)
@ -320,60 +326,44 @@ 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)
# Configure compiler warnings
if env.msvc:
# Truncations, narrowing conversions, signed/unsigned comparisons...
disable_nonessential_warnings = ['/wd4267', '/wd4244', '/wd4305', '/wd4018', '/wd4800']
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'):
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'])
if (env["werror"]):
env.Append(CCFLAGS=['/WX'])
else: # Rest of the world
shadow_local_warning = []
all_plus_warnings = ['-Wwrite-strings']
if methods.using_gcc(env):
version = methods.get_compiler_version(env)
if version != None and version[0] >= '7':
shadow_local_warning = ['-Wshadow-local']
if (env["warnings"] == 'extra'):
# FIXME: enable -Wclobbered once #26351 is fixed
# Note: enable -Wimplicit-fallthrough for Clang (already part of -Wextra for GCC)
# once we switch to C++11 or later (necessary for our FALLTHROUGH macro).
env.Append(CCFLAGS=['-Wall', '-Wextra', '-Wno-unused-parameter'] + all_plus_warnings + shadow_local_warning)
if methods.using_gcc(env):
env['CCFLAGS'] += ['-Wno-clobbered']
elif (env["warnings"] == 'all'):
env.Append(CCFLAGS=['-Wall'] + shadow_local_warning)
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'] + shadow_local_warning)
env.Append(CCFLAGS=['-Wall', '-Wno-unused'])
else: # 'no'
env.Append(CCFLAGS=['-w'])
if (env["werror"]):
env.Append(CCFLAGS=['-Werror'])
else: # always enable those errors
env.Append(CCFLAGS=['-Werror=return-type'])
if (hasattr(detect, 'get_program_suffix')):
suffix = "." + detect.get_program_suffix()
else:
suffix = "." + selected_platform
#env['platform_libsuffix'] = env['LIBSUFFIX']
suffix = "." + selected_platform
if (env["target"] == "release"):
if env["tools"]:
print("Tools can only be built with targets 'debug' and 'release_debug'.")
sys.exit(255)
suffix += ".opt"
env.Append(CPPDEFINES=['NDEBUG'])
env.Append(CCFLAGS=['-DNDEBUG'])
elif (env["target"] == "release_debug"):
if env["tools"]:
@ -392,10 +382,12 @@ if selected_platform in platform_list:
suffix += ".32"
elif (env["bits"] == "64"):
suffix += ".64"
elif (env["bits"] == "fat"):
suffix += ".fat"
suffix += env.extra_suffix
sys.path.remove(tmppath)
sys.path.remove("./platform/" + selected_platform)
sys.modules.pop('detect')
env.module_list = []
@ -405,20 +397,10 @@ if selected_platform in platform_list:
if not env['module_' + x + '_enabled']:
continue
tmppath = "./modules/" + x
sys.path.insert(0, tmppath)
sys.path.append(tmppath)
env.current_module = x
import config
# can_build changed number of arguments between 3.0 (1) and 3.1 (2),
# so try both to preserve compatibility for 3.0 modules
can_build = False
try:
can_build = config.can_build(env, selected_platform)
except TypeError:
print("Warning: module '%s' uses a deprecated `can_build` "
"signature in its config.py file, it should be "
"`can_build(env, platform)`." % x)
can_build = config.can_build(selected_platform)
if (can_build):
if (config.can_build(selected_platform)):
config.configure(env)
env.module_list.append(x)
try:
@ -436,46 +418,35 @@ if selected_platform in platform_list:
env["PROGSUFFIX"] = suffix + env.module_version_string + env["PROGSUFFIX"]
env["OBJSUFFIX"] = suffix + env["OBJSUFFIX"]
# (SH)LIBSUFFIX will be used for our own built libraries
# LIBSUFFIXES contains LIBSUFFIX and SHLIBSUFFIX by default,
# so we need to append the default suffixes to keep the ability
# to link against thirdparty libraries (.a, .so, .lib, etc.).
if os.name == "nt":
# On Windows, only static libraries and import libraries can be
# statically linked - both using .lib extension
env["LIBSUFFIXES"] += [env["LIBSUFFIX"]]
else:
env["LIBSUFFIXES"] += [env["LIBSUFFIX"], env["SHLIBSUFFIX"]]
env["LIBSUFFIX"] = suffix + env["LIBSUFFIX"]
env["SHLIBSUFFIX"] = suffix + env["SHLIBSUFFIX"]
if (env.use_ptrcall):
env.Append(CPPDEFINES=['PTRCALL_ENABLED'])
env.Append(CPPFLAGS=['-DPTRCALL_ENABLED'])
# to test 64 bits compiltion
# env.Append(CPPFLAGS=['-m64'])
if env['tools']:
env.Append(CPPDEFINES=['TOOLS_ENABLED'])
env.Append(CPPFLAGS=['-DTOOLS_ENABLED'])
if env['disable_3d']:
if env['tools']:
print("Build option 'disable_3d=yes' cannot be used with 'tools=yes' (editor), only with 'tools=no' (export template).")
sys.exit(255)
else:
env.Append(CPPDEFINES=['_3D_DISABLED'])
env.Append(CPPFLAGS=['-D_3D_DISABLED'])
if env['gdscript']:
env.Append(CPPDEFINES=['GDSCRIPT_ENABLED'])
env.Append(CPPFLAGS=['-DGDSCRIPT_ENABLED'])
if env['disable_advanced_gui']:
if env['tools']:
print("Build option 'disable_advanced_gui=yes' cannot be used with 'tools=yes' (editor), only with 'tools=no' (export template).")
sys.exit(255)
else:
env.Append(CPPDEFINES=['ADVANCED_GUI_DISABLED'])
env.Append(CPPFLAGS=['-DADVANCED_GUI_DISABLED'])
if env['minizip']:
env.Append(CPPDEFINES=['MINIZIP_ENABLED'])
env.Append(CPPFLAGS=['-DMINIZIP_ENABLED'])
if env['xml']:
env.Append(CPPFLAGS=['-DXML_ENABLED'])
if not env['verbose']:
methods.no_verbose(sys, env)
if (not env["platform"] == "server"): # FIXME: detect GLES3
env.Append(BUILDERS = { 'GLES3_GLSL' : env.Builder(action=run_in_subprocess(gles_builders.build_gles3_headers), suffix='glsl.gen.h', src_suffix='.glsl')})
env.Append(BUILDERS = { 'GLES2_GLSL' : env.Builder(action=run_in_subprocess(gles_builders.build_gles2_headers), suffix='glsl.gen.h', src_suffix='.glsl')})
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:
@ -509,128 +480,141 @@ if selected_platform in platform_list:
if ("check_c_headers" in env):
for header in env["check_c_headers"]:
if (conf.CheckCHeader(header[0])):
env.AppendUnique(CPPDEFINES=[header[1]])
if (env.msvc):
env.Append(CCFLAGS=['/D' + header[1]])
else:
env.Append(CCFLAGS=['-D' + header[1]])
else:
print("No valid target platform selected.")
print("The following platforms were detected:")
print("The following were detected:")
for x in platform_list:
print("\t" + x)
print("\nPlease run SCons again with the argument: platform=<string>")
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
screen = sys.stdout
node_count = 0
node_count_max = 0
node_count_interval = 1
node_pruning = 8 # Number of nodes to process before prunning the cache
if ('env' in locals()):
node_count_fname = str(env.Dir('#')) + '/.scons_node_count'
# Progress reporting is not available in non-TTY environments since it
# messes with the output (for example, when writing to a file)
if sys.stdout.isatty():
show_progress = env['progress']
else:
show_progress = False
import time, math
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')
class cache_progress:
# The default is 1 GB cache and 12 hours half life
def __init__(self, path = None, limit = 1073741824, half_life = 43200):
global node_pruning
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.pruning = node_pruning
self.delete(self.file_list())
def __call__(self, node, *args, **kw):
global node_count, node_count_max, node_count_interval, node_count_fname, node_pruning, 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()
# Prune if the number of nodes processed is 'node_pruning' or bigger
self.pruning -= node_count_interval
if self.pruning <= 0:
self.pruning = node_pruning
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'))
map(os.remove, files)
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 file_list(self):
if self.path is 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 is 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 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 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())
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)
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)
progress_finish_command = Command('progress_finish', [], progress_finish)
AlwaysBuild(progress_finish_command)

View File

@ -16,8 +16,6 @@ if sys.version_info < (3,):
return x
def iteritems(d):
return d.iteritems()
def itervalues(d):
return d.itervalues()
def escape_string(s):
if isinstance(s, unicode):
s = s.encode('ascii')
@ -46,8 +44,6 @@ else:
return codecs.utf_8_decode(x)[0]
def iteritems(d):
return iter(d.items())
def itervalues(d):
return iter(d.values())
def charcode_to_c_escapes(c):
rev_result = []
while c >= 256:

View File

@ -2,13 +2,27 @@
Import('env')
import core_builders
import make_binders
from platform_methods import run_in_subprocess
env.core_sources = []
# Generate global defaults
gd_call = ""
gd_inc = ""
for x in env.global_defaults:
env.core_sources.append("#platform/" + x + "/globals/global_defaults.cpp")
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 += gd_inc
gd_cpp += "void ProjectSettings::register_global_defaults() {\n" + gd_call + "\n}\n"
f = open("global_defaults.gen.cpp", "w")
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"
@ -33,141 +47,64 @@ 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)
# NOTE: It is safe to generate this file here, since this is still executed serially
with open("script_encryption_key.gen.cpp", "w") as f:
f.write("#include \"core/project_settings.h\"\nuint8_t script_encryption_key[32]={" + txt + "};\n")
f = open("script_encryption_key.gen.cpp", "w")
f.write("#include \"project_settings.h\"\nuint8_t script_encryption_key[32]={" + txt + "};\n")
f.close()
# Add required thirdparty code.
env_thirdparty = env.Clone()
env_thirdparty.disable_warnings()
# Misc thirdparty code: header paths are hardcoded, we don't need to append
# 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_misc_dir = "#thirdparty/misc/"
thirdparty_misc_sources = [
# C sources
"base64.c",
"fastlz.c",
"sha256.c",
"smaz.c",
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",
# C++ sources
"aes256.cpp",
"hq2x.cpp",
"md5.cpp",
"pcg.cpp",
"triangulator.cpp",
]
thirdparty_misc_sources = [thirdparty_misc_dir + file for file in thirdparty_misc_sources]
env_thirdparty.add_source_files(env.core_sources, thirdparty_misc_sources)
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
env.add_source_files(env.core_sources, thirdparty_sources)
# Zlib library, can be unbundled
if env['builtin_zlib']:
thirdparty_zlib_dir = "#thirdparty/zlib/"
thirdparty_zlib_sources = [
"adler32.c",
"compress.c",
"crc32.c",
"deflate.c",
"infback.c",
"inffast.c",
"inflate.c",
"inftrees.c",
"trees.c",
"uncompr.c",
"zutil.c",
]
thirdparty_zlib_sources = [thirdparty_zlib_dir + file for file in thirdparty_zlib_sources]
env_thirdparty.Append(CPPPATH=[thirdparty_zlib_dir])
# Needs to be available in main env too
env.Append(CPPPATH=[thirdparty_zlib_dir])
env_thirdparty.add_source_files(env.core_sources, thirdparty_zlib_sources)
# Minizip library, could be unbundled in theory
# 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",
"ioapi.c",
"unzip.c",
"zip.c",
]
thirdparty_minizip_sources = [thirdparty_minizip_dir + file for file in thirdparty_minizip_sources]
env_thirdparty.add_source_files(env.core_sources, thirdparty_minizip_sources)
env.add_source_files(env.core_sources, thirdparty_minizip_sources)
# Zstd library, can be unbundled in theory
# though we currently use some private symbols
# https://github.com/godotengine/godot/issues/17374
if env['builtin_zstd']:
thirdparty_zstd_dir = "#thirdparty/zstd/"
thirdparty_zstd_sources = [
"common/debug.c",
"common/entropy_common.c",
"common/error_private.c",
"common/fse_decompress.c",
"common/pool.c",
"common/threading.c",
"common/xxhash.c",
"common/zstd_common.c",
"compress/fse_compress.c",
"compress/hist.c",
"compress/huf_compress.c",
"compress/zstd_compress.c",
"compress/zstd_double_fast.c",
"compress/zstd_fast.c",
"compress/zstd_lazy.c",
"compress/zstd_ldm.c",
"compress/zstd_opt.c",
"compress/zstdmt_compress.c",
"compress/zstd_compress_literals.c",
"compress/zstd_compress_sequences.c",
"decompress/huf_decompress.c",
"decompress/zstd_ddict.c",
"decompress/zstd_decompress_block.c",
"decompress/zstd_decompress.c",
]
thirdparty_zstd_sources = [thirdparty_zstd_dir + file for file in thirdparty_zstd_sources]
env_thirdparty.Append(CPPPATH=[thirdparty_zstd_dir, thirdparty_zstd_dir + "common"])
env_thirdparty.Append(CCFLAGS="-DZSTD_STATIC_LINKING_ONLY")
env.Append(CPPPATH=thirdparty_zstd_dir)
# Also needed in main env includes will trigger warnings
env.Append(CCFLAGS="-DZSTD_STATIC_LINKING_ONLY")
env_thirdparty.add_source_files(env.core_sources, thirdparty_zstd_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")
# Certificates
env.Depends("#core/io/certs_compressed.gen.h", ["#thirdparty/certs/ca-certificates.crt", env.Value(env['builtin_certs']), env.Value(env['system_certs_path'])])
env.CommandNoCache("#core/io/certs_compressed.gen.h", "#thirdparty/certs/ca-certificates.crt", run_in_subprocess(core_builders.make_certs_header))
# Make binders
env.CommandNoCache(['method_bind.gen.inc', 'method_bind_ext.gen.inc'], 'make_binders.py', run_in_subprocess(make_binders.run))
import make_binders
env.Command(['method_bind.gen.inc', 'method_bind_ext.gen.inc'], 'make_binders.py', make_binders.run)
# Authors
env.Depends('#core/authors.gen.h', "../AUTHORS.md")
env.CommandNoCache('#core/authors.gen.h', "../AUTHORS.md", run_in_subprocess(core_builders.make_authors_header))
# Donors
env.Depends('#core/donors.gen.h', "../DONORS.md")
env.CommandNoCache('#core/donors.gen.h', "../DONORS.md", run_in_subprocess(core_builders.make_donors_header))
# License
env.Depends('#core/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"])
env.CommandNoCache('#core/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"], run_in_subprocess(core_builders.make_license_header))
# Chain load SCsubs
SConscript('os/SCsub')
SConscript('math/SCsub')
SConscript('io/SCsub')
SConscript('bind/SCsub')
SConscript('helper/SCsub')
# Build it all as a library
lib = env.add_library("core", env.core_sources)
env.Prepend(LIBS=[lib])
Export('env')

194
core/allocators.h Normal file
View File

@ -0,0 +1,194 @@
/*************************************************************************/
/* allocators.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 ALLOCATORS_H
#define ALLOCATORS_H
#include "os/memory.h"
template <int PREALLOC_COUNT = 64, int MAX_HANDS = 8>
class BalloonAllocator {
enum {
USED_FLAG = (1 << 30),
USED_MASK = USED_FLAG - 1
};
struct Balloon {
Balloon *next;
Balloon *prev;
uint32_t hand;
};
struct Hand {
int used;
int allocated;
Balloon *first;
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);
unsigned int hand = 0;
while (p_size > (size_t)(1 << hand))
++hand;
Hand &h = hands[hand];
if (h.used == h.allocated) {
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;
} else {
b->prev = NULL;
h.last = b;
h.first = b;
}
}
h.last->next = NULL;
h.allocated += PREALLOC_COUNT;
}
Balloon *pick = h.last;
ERR_FAIL_COND_V((pick->hand & USED_FLAG), NULL);
// remove last
h.last = h.last->prev;
h.last->next = NULL;
pick->next = h.first;
h.first->prev = pick;
pick->prev = NULL;
h.first = pick;
h.used++;
pick->hand |= USED_FLAG;
return (void *)(pick + 1);
}
void free(void *p_ptr) {
Balloon *b = (Balloon *)p_ptr;
b -= 1;
ERR_FAIL_COND(!(b->hand & USED_FLAG));
b->hand = b->hand & USED_MASK; // not used
int hand = b->hand;
Hand &h = hands[hand];
if (b == h.first)
h.first = b->next;
if (b->prev)
b->prev->next = b->next;
if (b->next)
b->next->prev = b->prev;
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
for (int i = 0; i < PREALLOC_COUNT; i++) {
ERR_CONTINUE(h.last->hand & USED_FLAG);
Balloon *new_last = h.last->prev;
if (new_last)
new_last->next = NULL;
memfree(h.last);
h.last = new_last;
}
h.allocated -= PREALLOC_COUNT;
}
}
BalloonAllocator() {
for (int i = 0; i < MAX_HANDS; i++) {
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++) {
while (hands[i].first) {
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;
}
}
~BalloonAllocator() {
clear();
}
};
#endif // ALLOCATORS_H

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -30,13 +30,13 @@
#include "array.h"
#include "core/hashfuncs.h"
#include "core/object.h"
#include "core/variant.h"
#include "core/vector.h"
#include "hashfuncs.h"
#include "object.h"
#include "variant.h"
#include "vector.h"
struct ArrayPrivate {
class ArrayPrivate {
public:
SafeRefCount refcount;
Vector<Variant> array;
};
@ -72,7 +72,7 @@ void Array::_unref() const {
Variant &Array::operator[](int p_idx) {
return _p->array.write[p_idx];
return _p->array[p_idx];
}
const Variant &Array::operator[](int p_idx) const {
@ -211,13 +211,13 @@ const Variant &Array::get(int p_idx) const {
return operator[](p_idx);
}
Array Array::duplicate(bool p_deep) const {
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] = p_deep ? get(i).duplicate(p_deep) : get(i);
new_arr[i] = get(i);
}
return new_arr;
@ -259,27 +259,13 @@ Array &Array::sort_custom(Object *p_obj, const StringName &p_function) {
ERR_FAIL_NULL_V(p_obj, *this);
SortArray<Variant, _ArrayVariantSortCustom, true> avs;
SortArray<Variant, _ArrayVariantSortCustom> avs;
avs.compare.obj = p_obj;
avs.compare.func = p_function;
avs.sort(_p->array.ptrw(), _p->array.size());
return *this;
}
void Array::shuffle() {
const int n = _p->array.size();
if (n < 2)
return;
Variant *data = _p->array.ptrw();
for (int i = n - 1; i >= 1; i--) {
const int j = Math::rand() % (i + 1);
const Variant tmp = data[j];
data[j] = data[i];
data[i] = tmp;
}
}
template <typename Less>
_FORCE_INLINE_ int bisect(const Vector<Variant> &p_array, const Variant &p_value, bool p_before, const Less &p_less) {
@ -355,58 +341,11 @@ Variant Array::pop_front() {
return Variant();
}
Variant Array::min() const {
Variant minval;
for (int i = 0; i < size(); i++) {
if (i == 0) {
minval = get(i);
} else {
bool valid;
Variant ret;
Variant test = get(i);
Variant::evaluate(Variant::OP_LESS, test, minval, ret, valid);
if (!valid) {
return Variant(); //not a valid comparison
}
if (bool(ret)) {
//is less
minval = test;
}
}
}
return minval;
}
Variant Array::max() const {
Variant maxval;
for (int i = 0; i < size(); i++) {
if (i == 0) {
maxval = get(i);
} else {
bool valid;
Variant ret;
Variant test = get(i);
Variant::evaluate(Variant::OP_GREATER, test, maxval, ret, valid);
if (!valid) {
return Variant(); //not a valid comparison
}
if (bool(ret)) {
//is less
maxval = test;
}
}
}
return maxval;
}
Array::Array(const Array &p_from) {
_p = NULL;
_ref(p_from);
}
Array::Array() {
_p = memnew(ArrayPrivate);

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,8 +31,7 @@
#ifndef ARRAY_H
#define ARRAY_H
#include "core/typedefs.h"
#include "typedefs.h"
class Variant;
class ArrayPrivate;
class Object;
@ -72,7 +71,6 @@ public:
Array &sort();
Array &sort_custom(Object *p_obj, const StringName &p_function);
void shuffle();
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();
@ -89,10 +87,7 @@ public:
Variant pop_back();
Variant pop_front();
Array duplicate(bool p_deep = false) const;
Variant min() const;
Variant max() const;
Array duplicate() const;
Array(const Array &p_from);
Array();

View File

@ -3,3 +3,5 @@
Import('env')
env.add_source_files(env.core_sources, "*.cpp")
Export('env')

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -30,14 +30,14 @@
#include "core_bind.h"
#include "core/io/file_access_compressed.h"
#include "core/io/file_access_encrypted.h"
#include "core/io/json.h"
#include "core/io/marshalls.h"
#include "core/math/geometry.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/project_settings.h"
#include "geometry.h"
#include "io/file_access_compressed.h"
#include "io/file_access_encrypted.h"
#include "io/json.h"
#include "io/marshalls.h"
#include "os/keyboard.h"
#include "os/os.h"
#include "thirdparty/misc/base64.h"
@ -112,35 +112,20 @@ PoolStringArray _ResourceLoader::get_dependencies(const String &p_path) {
return ret;
};
#ifndef DISABLE_DEPRECATED
bool _ResourceLoader::has(const String &p_path) {
WARN_PRINTS("ResourceLoader.has() is deprecated, please replace it with the equivalent has_cached() or the new exists().");
return has_cached(p_path);
}
#endif // DISABLE_DEPRECATED
bool _ResourceLoader::has_cached(const String &p_path) {
String local_path = ProjectSettings::get_singleton()->localize_path(p_path);
return ResourceCache::has(local_path);
}
bool _ResourceLoader::exists(const String &p_path, const String &p_type_hint) {
return ResourceLoader::exists(p_path, p_type_hint);
}
};
void _ResourceLoader::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_interactive", "path", "type_hint"), &_ResourceLoader::load_interactive, DEFVAL(""));
ClassDB::bind_method(D_METHOD("load", "path", "type_hint", "no_cache"), &_ResourceLoader::load, DEFVAL(""), DEFVAL(false));
ClassDB::bind_method(D_METHOD("load", "path", "type_hint", "p_no_cache"), &_ResourceLoader::load, DEFVAL(""), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_recognized_extensions_for_type", "type"), &_ResourceLoader::get_recognized_extensions_for_type);
ClassDB::bind_method(D_METHOD("set_abort_on_missing_resources", "abort"), &_ResourceLoader::set_abort_on_missing_resources);
ClassDB::bind_method(D_METHOD("get_dependencies", "path"), &_ResourceLoader::get_dependencies);
ClassDB::bind_method(D_METHOD("has_cached", "path"), &_ResourceLoader::has_cached);
ClassDB::bind_method(D_METHOD("exists", "path", "type_hint"), &_ResourceLoader::exists, DEFVAL(""));
#ifndef DISABLE_DEPRECATED
ClassDB::bind_method(D_METHOD("has", "path"), &_ResourceLoader::has);
#endif // DISABLE_DEPRECATED
}
_ResourceLoader::_ResourceLoader() {
@ -180,7 +165,6 @@ void _ResourceSaver::_bind_methods() {
BIND_ENUM_CONSTANT(FLAG_OMIT_EDITOR_PROPERTIES);
BIND_ENUM_CONSTANT(FLAG_SAVE_BIG_ENDIAN);
BIND_ENUM_CONSTANT(FLAG_COMPRESS);
BIND_ENUM_CONSTANT(FLAG_REPLACE_SUBRESOURCE_PATHS);
}
_ResourceSaver::_ResourceSaver() {
@ -221,38 +205,6 @@ String _OS::get_clipboard() const {
return OS::get_singleton()->get_clipboard();
}
int _OS::get_video_driver_count() const {
return OS::get_singleton()->get_video_driver_count();
}
String _OS::get_video_driver_name(VideoDriver p_driver) const {
return OS::get_singleton()->get_video_driver_name((int)p_driver);
}
_OS::VideoDriver _OS::get_current_video_driver() const {
return (VideoDriver)OS::get_singleton()->get_current_video_driver();
}
int _OS::get_audio_driver_count() const {
return OS::get_singleton()->get_audio_driver_count();
}
String _OS::get_audio_driver_name(int p_driver) const {
return OS::get_singleton()->get_audio_driver_name(p_driver);
}
PoolStringArray _OS::get_connected_midi_inputs() {
return OS::get_singleton()->get_connected_midi_inputs();
}
void _OS::open_midi_inputs() {
return OS::get_singleton()->open_midi_inputs();
}
void _OS::close_midi_inputs() {
return OS::get_singleton()->close_midi_inputs();
}
void _OS::set_video_mode(const Size2 &p_size, bool p_fullscreen, bool p_resizeable, int p_screen) {
OS::VideoMode vm;
@ -320,10 +272,6 @@ void _OS::set_window_size(const Size2 &p_size) {
OS::get_singleton()->set_window_size(p_size);
}
Rect2 _OS::get_window_safe_area() const {
return OS::get_singleton()->get_window_safe_area();
}
void _OS::set_window_fullscreen(bool p_enabled) {
OS::get_singleton()->set_window_fullscreen(p_enabled);
}
@ -356,46 +304,17 @@ bool _OS::is_window_maximized() const {
return OS::get_singleton()->is_window_maximized();
}
void _OS::set_window_always_on_top(bool p_enabled) {
OS::get_singleton()->set_window_always_on_top(p_enabled);
}
bool _OS::is_window_always_on_top() const {
return OS::get_singleton()->is_window_always_on_top();
}
void _OS::set_borderless_window(bool p_borderless) {
OS::get_singleton()->set_borderless_window(p_borderless);
}
bool _OS::get_window_per_pixel_transparency_enabled() const {
return OS::get_singleton()->get_window_per_pixel_transparency_enabled();
}
void _OS::set_window_per_pixel_transparency_enabled(bool p_enabled) {
OS::get_singleton()->set_window_per_pixel_transparency_enabled(p_enabled);
}
bool _OS::get_borderless_window() const {
return OS::get_singleton()->get_borderless_window();
}
void _OS::set_ime_active(const bool p_active) {
OS::get_singleton()->set_ime_active(p_active);
}
void _OS::set_ime_position(const Point2 &p_pos) {
OS::get_singleton()->set_ime_position(p_pos);
}
Point2 _OS::get_ime_selection() const {
return OS::get_singleton()->get_ime_selection();
}
String _OS::get_ime_text() const {
return OS::get_singleton()->get_ime_text();
return OS::get_singleton()->set_ime_position(p_pos);
}
void _OS::set_use_file_access_save_and_swap(bool p_enable) {
@ -444,7 +363,7 @@ Error _OS::shell_open(String p_uri) {
int _OS::execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, Array p_output) {
OS::ProcessID pid = -2;
OS::ProcessID pid;
List<String> args;
for (int i = 0; i < p_arguments.size(); i++)
args.push_back(p_arguments[i]);
@ -457,7 +376,6 @@ int _OS::execute(const String &p_path, const Vector<String> &p_arguments, bool p
else
return pid;
}
Error _OS::kill(int p_pid) {
return OS::get_singleton()->kill(p_pid);
@ -596,17 +514,17 @@ struct Time {
};
*/
uint64_t _OS::get_static_memory_usage() const {
int _OS::get_static_memory_usage() const {
return OS::get_singleton()->get_static_memory_usage();
}
uint64_t _OS::get_static_memory_peak_usage() const {
int _OS::get_static_memory_peak_usage() const {
return OS::get_singleton()->get_static_memory_peak_usage();
}
uint64_t _OS::get_dynamic_memory_usage() const {
int _OS::get_dynamic_memory_usage() const {
return OS::get_singleton()->get_dynamic_memory_usage();
}
@ -679,7 +597,7 @@ Dictionary _OS::get_time(bool utc) const {
*
* @return epoch calculated
*/
int64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const {
uint64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const {
// Bunch of conversion constants
static const unsigned int SECONDS_PER_MINUTE = 60;
@ -693,8 +611,8 @@ int64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const {
unsigned int second = ((datetime.has(SECOND_KEY)) ? static_cast<unsigned int>(datetime[SECOND_KEY]) : 0);
unsigned int minute = ((datetime.has(MINUTE_KEY)) ? static_cast<unsigned int>(datetime[MINUTE_KEY]) : 0);
unsigned int hour = ((datetime.has(HOUR_KEY)) ? static_cast<unsigned int>(datetime[HOUR_KEY]) : 0);
unsigned int day = ((datetime.has(DAY_KEY)) ? static_cast<unsigned int>(datetime[DAY_KEY]) : 1);
unsigned int month = ((datetime.has(MONTH_KEY)) ? static_cast<unsigned int>(datetime[MONTH_KEY]) : 1);
unsigned int day = ((datetime.has(DAY_KEY)) ? static_cast<unsigned int>(datetime[DAY_KEY]) : 0);
unsigned int month = ((datetime.has(MONTH_KEY)) ? static_cast<unsigned int>(datetime[MONTH_KEY]) - 1 : 0);
unsigned int year = ((datetime.has(YEAR_KEY)) ? static_cast<unsigned int>(datetime[YEAR_KEY]) : 0);
/// How many days come before each month (0-12)
@ -714,28 +632,23 @@ int64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const {
ERR_EXPLAIN("Invalid hour value of: " + itos(hour));
ERR_FAIL_COND_V(hour > 23, 0);
ERR_EXPLAIN("Invalid month value of: " + itos(month));
ERR_FAIL_COND_V(month > 12 || month == 0, 0);
ERR_EXPLAIN("Invalid month value of: " + itos(month + 1));
ERR_FAIL_COND_V(month + 1 > 12, 0);
// Do this check after month is tested as valid
ERR_EXPLAIN("Invalid day value of: " + itos(day) + " which is larger than " + itos(MONTH_DAYS_TABLE[LEAPYEAR(year)][month - 1]) + " or 0");
ERR_FAIL_COND_V(day > MONTH_DAYS_TABLE[LEAPYEAR(year)][month - 1] || day == 0, 0);
ERR_EXPLAIN("Invalid day value of: " + itos(day) + " which is larger than " + itos(MONTH_DAYS_TABLE[LEAPYEAR(year)][month]));
ERR_FAIL_COND_V(day > MONTH_DAYS_TABLE[LEAPYEAR(year)][month], 0);
// Calculate all the seconds from months past in this year
uint64_t SECONDS_FROM_MONTHS_PAST_THIS_YEAR = DAYS_PAST_THIS_YEAR_TABLE[LEAPYEAR(year)][month - 1] * SECONDS_PER_DAY;
uint64_t SECONDS_FROM_MONTHS_PAST_THIS_YEAR = DAYS_PAST_THIS_YEAR_TABLE[LEAPYEAR(year)][month] * SECONDS_PER_DAY;
int64_t SECONDS_FROM_YEARS_PAST = 0;
if (year >= EPOCH_YR) {
for (unsigned int iyear = EPOCH_YR; iyear < year; iyear++) {
SECONDS_FROM_YEARS_PAST += YEARSIZE(iyear) * SECONDS_PER_DAY;
}
} else {
for (unsigned int iyear = EPOCH_YR - 1; iyear >= year; iyear--) {
SECONDS_FROM_YEARS_PAST -= YEARSIZE(iyear) * SECONDS_PER_DAY;
}
uint64_t SECONDS_FROM_YEARS_PAST = 0;
for (unsigned int iyear = EPOCH_YR; iyear < year; iyear++) {
SECONDS_FROM_YEARS_PAST += YEARSIZE(iyear) * SECONDS_PER_DAY;
}
int64_t epoch =
uint64_t epoch =
second +
minute * SECONDS_PER_MINUTE +
hour * SECONDS_PER_HOUR +
@ -758,41 +671,39 @@ int64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const {
*
* @return dictionary of date and time values
*/
Dictionary _OS::get_datetime_from_unix_time(int64_t unix_time_val) const {
Dictionary _OS::get_datetime_from_unix_time(uint64_t unix_time_val) const {
// Just fail if unix time is negative (when interpreted as an int).
// This means the user passed in a negative value by accident
ERR_EXPLAIN("unix_time_val was really huge!" + itos(unix_time_val) + " You probably passed in a negative value!");
ERR_FAIL_COND_V((int64_t)unix_time_val < 0, Dictionary());
OS::Date date;
OS::Time time;
long dayclock, dayno;
unsigned long dayclock, dayno;
int year = EPOCH_YR;
if (unix_time_val >= 0) {
dayno = unix_time_val / SECS_DAY;
dayclock = unix_time_val % SECS_DAY;
/* day 0 was a thursday */
date.weekday = static_cast<OS::Weekday>((dayno + 4) % 7);
while (dayno >= YEARSIZE(year)) {
dayno -= YEARSIZE(year);
year++;
}
} else {
dayno = (unix_time_val - SECS_DAY + 1) / SECS_DAY;
dayclock = unix_time_val - dayno * SECS_DAY;
date.weekday = static_cast<OS::Weekday>((dayno - 3) % 7 + 7);
do {
year--;
dayno += YEARSIZE(year);
} while (dayno < 0);
}
dayclock = (unsigned long)unix_time_val % SECS_DAY;
dayno = (unsigned long)unix_time_val / SECS_DAY;
time.sec = dayclock % 60;
time.min = (dayclock % 3600) / 60;
time.hour = dayclock / 3600;
/* day 0 was a thursday */
date.weekday = static_cast<OS::Weekday>((dayno + 4) % 7);
while (dayno >= YEARSIZE(year)) {
dayno -= YEARSIZE(year);
year++;
}
date.year = year;
size_t imonth = 0;
while ((unsigned long)dayno >= MONTH_DAYS_TABLE[LEAPYEAR(year)][imonth]) {
while (dayno >= MONTH_DAYS_TABLE[LEAPYEAR(year)][imonth]) {
dayno -= MONTH_DAYS_TABLE[LEAPYEAR(year)][imonth];
imonth++;
}
@ -831,10 +742,6 @@ uint64_t _OS::get_system_time_secs() const {
return OS::get_singleton()->get_system_time_secs();
}
uint64_t _OS::get_system_time_msecs() const {
return OS::get_singleton()->get_system_time_msecs();
}
void _OS::delay_usec(uint32_t p_usec) const {
OS::get_singleton()->delay_usec(p_usec);
@ -850,11 +757,6 @@ uint32_t _OS::get_ticks_msec() const {
return OS::get_singleton()->get_ticks_msec();
}
uint64_t _OS::get_ticks_usec() const {
return OS::get_singleton()->get_ticks_usec();
}
uint32_t _OS::get_splash_tick_msec() const {
return OS::get_singleton()->get_splash_tick_msec();
@ -1036,11 +938,6 @@ void _OS::center_window() {
OS::get_singleton()->center_window();
}
void _OS::move_window_to_foreground() {
OS::get_singleton()->move_window_to_foreground();
}
bool _OS::is_debug_build() const {
#ifdef DEBUG_ENABLED
@ -1093,11 +990,6 @@ void _OS::alert(const String &p_alert, const String &p_title) {
OS::get_singleton()->alert(p_alert, p_title);
}
bool _OS::request_permission(const String &p_name) {
return OS::get_singleton()->request_permission(p_name);
}
_OS *_OS::singleton = NULL;
void _OS::_bind_methods() {
@ -1115,16 +1007,6 @@ void _OS::_bind_methods() {
//ClassDB::bind_method(D_METHOD("is_video_mode_resizable","screen"),&_OS::is_video_mode_resizable,DEFVAL(0));
//ClassDB::bind_method(D_METHOD("get_fullscreen_mode_list","screen"),&_OS::get_fullscreen_mode_list,DEFVAL(0));
ClassDB::bind_method(D_METHOD("get_video_driver_count"), &_OS::get_video_driver_count);
ClassDB::bind_method(D_METHOD("get_video_driver_name", "driver"), &_OS::get_video_driver_name);
ClassDB::bind_method(D_METHOD("get_current_video_driver"), &_OS::get_current_video_driver);
ClassDB::bind_method(D_METHOD("get_audio_driver_count"), &_OS::get_audio_driver_count);
ClassDB::bind_method(D_METHOD("get_audio_driver_name", "driver"), &_OS::get_audio_driver_name);
ClassDB::bind_method(D_METHOD("get_connected_midi_inputs"), &_OS::get_connected_midi_inputs);
ClassDB::bind_method(D_METHOD("open_midi_inputs"), &_OS::open_midi_inputs);
ClassDB::bind_method(D_METHOD("close_midi_inputs"), &_OS::close_midi_inputs);
ClassDB::bind_method(D_METHOD("get_screen_count"), &_OS::get_screen_count);
ClassDB::bind_method(D_METHOD("get_current_screen"), &_OS::get_current_screen);
ClassDB::bind_method(D_METHOD("set_current_screen", "screen"), &_OS::set_current_screen);
@ -1135,7 +1017,6 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_window_position", "position"), &_OS::set_window_position);
ClassDB::bind_method(D_METHOD("get_window_size"), &_OS::get_window_size);
ClassDB::bind_method(D_METHOD("set_window_size", "size"), &_OS::set_window_size);
ClassDB::bind_method(D_METHOD("get_window_safe_area"), &_OS::get_window_safe_area);
ClassDB::bind_method(D_METHOD("set_window_fullscreen", "enabled"), &_OS::set_window_fullscreen);
ClassDB::bind_method(D_METHOD("is_window_fullscreen"), &_OS::is_window_fullscreen);
ClassDB::bind_method(D_METHOD("set_window_resizable", "enabled"), &_OS::set_window_resizable);
@ -1144,23 +1025,14 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_window_minimized"), &_OS::is_window_minimized);
ClassDB::bind_method(D_METHOD("set_window_maximized", "enabled"), &_OS::set_window_maximized);
ClassDB::bind_method(D_METHOD("is_window_maximized"), &_OS::is_window_maximized);
ClassDB::bind_method(D_METHOD("set_window_always_on_top", "enabled"), &_OS::set_window_always_on_top);
ClassDB::bind_method(D_METHOD("is_window_always_on_top"), &_OS::is_window_always_on_top);
ClassDB::bind_method(D_METHOD("request_attention"), &_OS::request_attention);
ClassDB::bind_method(D_METHOD("get_real_window_size"), &_OS::get_real_window_size);
ClassDB::bind_method(D_METHOD("center_window"), &_OS::center_window);
ClassDB::bind_method(D_METHOD("move_window_to_foreground"), &_OS::move_window_to_foreground);
ClassDB::bind_method(D_METHOD("set_borderless_window", "borderless"), &_OS::set_borderless_window);
ClassDB::bind_method(D_METHOD("get_borderless_window"), &_OS::get_borderless_window);
ClassDB::bind_method(D_METHOD("get_window_per_pixel_transparency_enabled"), &_OS::get_window_per_pixel_transparency_enabled);
ClassDB::bind_method(D_METHOD("set_window_per_pixel_transparency_enabled", "enabled"), &_OS::set_window_per_pixel_transparency_enabled);
ClassDB::bind_method(D_METHOD("set_ime_active", "active"), &_OS::set_ime_active);
ClassDB::bind_method(D_METHOD("set_ime_position", "position"), &_OS::set_ime_position);
ClassDB::bind_method(D_METHOD("get_ime_selection"), &_OS::get_ime_selection);
ClassDB::bind_method(D_METHOD("get_ime_text"), &_OS::get_ime_text);
ClassDB::bind_method(D_METHOD("set_screen_orientation", "orientation"), &_OS::set_screen_orientation);
ClassDB::bind_method(D_METHOD("get_screen_orientation"), &_OS::get_screen_orientation);
@ -1197,7 +1069,6 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_datetime_from_unix_time", "unix_time_val"), &_OS::get_datetime_from_unix_time);
ClassDB::bind_method(D_METHOD("get_unix_time_from_datetime", "datetime"), &_OS::get_unix_time_from_datetime);
ClassDB::bind_method(D_METHOD("get_system_time_secs"), &_OS::get_system_time_secs);
ClassDB::bind_method(D_METHOD("get_system_time_msecs"), &_OS::get_system_time_msecs);
ClassDB::bind_method(D_METHOD("set_icon", "icon"), &_OS::set_icon);
@ -1207,7 +1078,6 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("delay_usec", "usec"), &_OS::delay_usec);
ClassDB::bind_method(D_METHOD("delay_msec", "msec"), &_OS::delay_msec);
ClassDB::bind_method(D_METHOD("get_ticks_msec"), &_OS::get_ticks_msec);
ClassDB::bind_method(D_METHOD("get_ticks_usec"), &_OS::get_ticks_usec);
ClassDB::bind_method(D_METHOD("get_splash_tick_msec"), &_OS::get_splash_tick_msec);
ClassDB::bind_method(D_METHOD("get_locale"), &_OS::get_locale);
ClassDB::bind_method(D_METHOD("get_latin_keyboard_variant"), &_OS::get_latin_keyboard_variant);
@ -1270,8 +1140,6 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_power_seconds_left"), &_OS::get_power_seconds_left);
ClassDB::bind_method(D_METHOD("get_power_percent_left"), &_OS::get_power_percent_left);
ClassDB::bind_method(D_METHOD("request_permission", "name"), &_OS::request_permission);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "clipboard"), "set_clipboard", "get_clipboard");
ADD_PROPERTY(PropertyInfo(Variant::INT, "current_screen"), "set_current_screen", "get_current_screen");
ADD_PROPERTY(PropertyInfo(Variant::INT, "exit_code"), "set_exit_code", "get_exit_code");
@ -1281,7 +1149,6 @@ void _OS::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_orientation", PROPERTY_HINT_ENUM, "Landscape,Portrait,Reverse Landscape,Reverse Portrait,Sensor Landscape,Sensor Portrait,Sensor"), "set_screen_orientation", "get_screen_orientation");
ADD_GROUP("Window", "window_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_borderless"), "set_borderless_window", "get_borderless_window");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_per_pixel_transparency_enabled"), "set_window_per_pixel_transparency_enabled", "get_window_per_pixel_transparency_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_fullscreen"), "set_window_fullscreen", "is_window_fullscreen");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_maximized"), "set_window_maximized", "is_window_maximized");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_minimized"), "set_window_minimized", "is_window_minimized");
@ -1289,9 +1156,6 @@ void _OS::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "window_position"), "set_window_position", "get_window_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "window_size"), "set_window_size", "get_window_size");
BIND_ENUM_CONSTANT(VIDEO_DRIVER_GLES2);
BIND_ENUM_CONSTANT(VIDEO_DRIVER_GLES3);
BIND_ENUM_CONSTANT(DAY_SUNDAY);
BIND_ENUM_CONSTANT(DAY_MONDAY);
BIND_ENUM_CONSTANT(DAY_TUESDAY);
@ -1381,16 +1245,6 @@ Variant _Geometry::segment_intersects_segment_2d(const Vector2 &p_from_a, const
};
};
Variant _Geometry::line_intersects_line_2d(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b) {
Vector2 result;
if (Geometry::line_intersects_line_2d(p_from_a, p_dir_a, p_from_b, p_dir_b, result)) {
return result;
} else {
return Variant();
}
}
PoolVector<Vector2> _Geometry::get_closest_points_between_segments_2d(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2) {
Vector2 r1, r2;
@ -1546,7 +1400,6 @@ void _Geometry::_bind_methods() {
ClassDB::bind_method(D_METHOD("build_capsule_planes", "radius", "height", "sides", "lats", "axis"), &_Geometry::build_capsule_planes, DEFVAL(Vector3::AXIS_Z));
ClassDB::bind_method(D_METHOD("segment_intersects_circle", "segment_from", "segment_to", "circle_position", "circle_radius"), &_Geometry::segment_intersects_circle);
ClassDB::bind_method(D_METHOD("segment_intersects_segment_2d", "from_a", "to_a", "from_b", "to_b"), &_Geometry::segment_intersects_segment_2d);
ClassDB::bind_method(D_METHOD("line_intersects_line_2d", "from_a", "dir_a", "from_b", "dir_b"), &_Geometry::line_intersects_line_2d);
ClassDB::bind_method(D_METHOD("get_closest_points_between_segments_2d", "p1", "q1", "p2", "q2"), &_Geometry::get_closest_points_between_segments_2d);
ClassDB::bind_method(D_METHOD("get_closest_points_between_segments", "p1", "p2", "q1", "q2"), &_Geometry::get_closest_points_between_segments);
@ -1651,17 +1504,6 @@ bool _File::is_open() const {
return f != NULL;
}
String _File::get_path() const {
ERR_FAIL_COND_V(!f, "");
return f->get_path();
}
String _File::get_path_absolute() const {
ERR_FAIL_COND_V(!f, "");
return f->get_path_absolute();
}
void _File::seek(int64_t p_position) {
@ -1786,9 +1628,9 @@ String _File::get_line() const {
return f->get_line();
}
Vector<String> _File::get_csv_line(const String &p_delim) const {
Vector<String> _File::get_csv_line(String delim) const {
ERR_FAIL_COND_V(!f, Vector<String>());
return f->get_csv_line(p_delim);
return f->get_csv_line(delim);
}
/**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
@ -1885,11 +1727,6 @@ void _File::store_line(const String &p_string) {
f->store_line(p_string);
}
void _File::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
ERR_FAIL_COND(!f);
f->store_csv_line(p_values, p_delim);
}
void _File::store_buffer(const PoolVector<uint8_t> &p_buffer) {
ERR_FAIL_COND(!f);
@ -1908,18 +1745,18 @@ bool _File::file_exists(const String &p_name) const {
return FileAccess::exists(p_name);
}
void _File::store_var(const Variant &p_var, bool p_full_objects) {
void _File::store_var(const Variant &p_var) {
ERR_FAIL_COND(!f);
int len;
Error err = encode_variant(p_var, NULL, len, p_full_objects);
Error err = encode_variant(p_var, NULL, len);
ERR_FAIL_COND(err != OK);
PoolVector<uint8_t> buff;
buff.resize(len);
PoolVector<uint8_t>::Write w = buff.write();
err = encode_variant(p_var, &w[0], len, p_full_objects);
err = encode_variant(p_var, &w[0], len);
ERR_FAIL_COND(err != OK);
w = PoolVector<uint8_t>::Write();
@ -1927,7 +1764,7 @@ void _File::store_var(const Variant &p_var, bool p_full_objects) {
store_buffer(buff);
}
Variant _File::get_var(bool p_allow_objects) const {
Variant _File::get_var() const {
ERR_FAIL_COND_V(!f, Variant());
uint32_t len = get_32();
@ -1937,7 +1774,7 @@ Variant _File::get_var(bool p_allow_objects) const {
PoolVector<uint8_t>::Read r = buff.read();
Variant v;
Error err = decode_variant(v, &r[0], len, NULL, p_allow_objects);
Error err = decode_variant(v, &r[0], len);
ERR_FAIL_COND_V(err != OK, Variant());
return v;
@ -1956,8 +1793,6 @@ void _File::_bind_methods() {
ClassDB::bind_method(D_METHOD("open", "path", "flags"), &_File::open);
ClassDB::bind_method(D_METHOD("close"), &_File::close);
ClassDB::bind_method(D_METHOD("get_path"), &_File::get_path);
ClassDB::bind_method(D_METHOD("get_path_absolute"), &_File::get_path_absolute);
ClassDB::bind_method(D_METHOD("is_open"), &_File::is_open);
ClassDB::bind_method(D_METHOD("seek", "position"), &_File::seek);
ClassDB::bind_method(D_METHOD("seek_end", "position"), &_File::seek_end, DEFVAL(0));
@ -1973,14 +1808,14 @@ void _File::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_real"), &_File::get_real);
ClassDB::bind_method(D_METHOD("get_buffer", "len"), &_File::get_buffer);
ClassDB::bind_method(D_METHOD("get_line"), &_File::get_line);
ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &_File::get_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("get_as_text"), &_File::get_as_text);
ClassDB::bind_method(D_METHOD("get_md5", "path"), &_File::get_md5);
ClassDB::bind_method(D_METHOD("get_sha256", "path"), &_File::get_sha256);
ClassDB::bind_method(D_METHOD("get_endian_swap"), &_File::get_endian_swap);
ClassDB::bind_method(D_METHOD("set_endian_swap", "enable"), &_File::set_endian_swap);
ClassDB::bind_method(D_METHOD("get_error"), &_File::get_error);
ClassDB::bind_method(D_METHOD("get_var", "allow_objects"), &_File::get_var, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_var"), &_File::get_var);
ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &_File::get_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("store_8", "value"), &_File::store_8);
ClassDB::bind_method(D_METHOD("store_16", "value"), &_File::store_16);
@ -1991,9 +1826,8 @@ void _File::_bind_methods() {
ClassDB::bind_method(D_METHOD("store_real", "value"), &_File::store_real);
ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), &_File::store_buffer);
ClassDB::bind_method(D_METHOD("store_line", "line"), &_File::store_line);
ClassDB::bind_method(D_METHOD("store_csv_line", "values", "delim"), &_File::store_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("store_string", "string"), &_File::store_string);
ClassDB::bind_method(D_METHOD("store_var", "value", "full_objects"), &_File::store_var, DEFVAL(false));
ClassDB::bind_method(D_METHOD("store_var", "value"), &_File::store_var);
ClassDB::bind_method(D_METHOD("store_pascal_string", "string"), &_File::store_pascal_string);
ClassDB::bind_method(D_METHOD("get_pascal_string"), &_File::get_pascal_string);
@ -2223,17 +2057,17 @@ _Marshalls *_Marshalls::get_singleton() {
return singleton;
}
String _Marshalls::variant_to_base64(const Variant &p_var, bool p_full_objects) {
String _Marshalls::variant_to_base64(const Variant &p_var) {
int len;
Error err = encode_variant(p_var, NULL, len, p_full_objects);
Error err = encode_variant(p_var, NULL, len);
ERR_FAIL_COND_V(err != OK, "");
PoolVector<uint8_t> buff;
buff.resize(len);
PoolVector<uint8_t>::Write w = buff.write();
err = encode_variant(p_var, &w[0], len, p_full_objects);
err = encode_variant(p_var, &w[0], len);
ERR_FAIL_COND_V(err != OK, "");
int b64len = len / 3 * 4 + 4 + 1;
@ -2249,7 +2083,7 @@ String _Marshalls::variant_to_base64(const Variant &p_var, bool p_full_objects)
return ret;
};
Variant _Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects) {
Variant _Marshalls::base64_to_variant(const String &p_str) {
int strlen = p_str.length();
CharString cstr = p_str.ascii();
@ -2261,7 +2095,7 @@ Variant _Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects)
int len = base64_decode((char *)(&w[0]), (char *)cstr.get_data(), strlen);
Variant v;
Error err = decode_variant(v, &w[0], len, NULL, p_allow_objects);
Error err = decode_variant(v, &w[0], len);
ERR_FAIL_COND_V(err != OK, Variant());
return v;
@ -2340,8 +2174,8 @@ String _Marshalls::base64_to_utf8(const String &p_str) {
void _Marshalls::_bind_methods() {
ClassDB::bind_method(D_METHOD("variant_to_base64", "variant", "full_objects"), &_Marshalls::variant_to_base64, DEFVAL(false));
ClassDB::bind_method(D_METHOD("base64_to_variant", "base64_str", "allow_objects"), &_Marshalls::base64_to_variant, DEFVAL(false));
ClassDB::bind_method(D_METHOD("variant_to_base64", "variant"), &_Marshalls::variant_to_base64);
ClassDB::bind_method(D_METHOD("base64_to_variant", "base64_str"), &_Marshalls::base64_to_variant);
ClassDB::bind_method(D_METHOD("raw_to_base64", "array"), &_Marshalls::raw_to_base64);
ClassDB::bind_method(D_METHOD("base64_to_raw", "base64_str"), &_Marshalls::base64_to_raw);
@ -2439,7 +2273,7 @@ void _Thread::_start_func(void *ud) {
} break;
case Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: {
reason = "Too Few Arguments";
reason = "Too Many Arguments";
} break;
case Variant::CallError::CALL_ERROR_INVALID_METHOD: {
@ -2530,9 +2364,9 @@ _Thread::_Thread() {
_Thread::~_Thread() {
if (active) {
ERR_EXPLAIN("Reference to a Thread object object was lost while the thread is still running...");
ERR_EXPLAIN("Reference to a Thread object object was lost while the thread is still running..");
}
ERR_FAIL_COND(active);
ERR_FAIL_COND(active == true);
}
/////////////////////////////////////
@ -2758,14 +2592,6 @@ int _Engine::get_iterations_per_second() const {
return Engine::get_singleton()->get_iterations_per_second();
}
void _Engine::set_physics_jitter_fix(float p_threshold) {
Engine::get_singleton()->set_physics_jitter_fix(p_threshold);
}
float _Engine::get_physics_jitter_fix() const {
return Engine::get_singleton()->get_physics_jitter_fix();
}
void _Engine::set_target_fps(int p_fps) {
Engine::get_singleton()->set_target_fps(p_fps);
}
@ -2804,26 +2630,6 @@ Dictionary _Engine::get_version_info() const {
return Engine::get_singleton()->get_version_info();
}
Dictionary _Engine::get_author_info() const {
return Engine::get_singleton()->get_author_info();
}
Array _Engine::get_copyright_info() const {
return Engine::get_singleton()->get_copyright_info();
}
Dictionary _Engine::get_donor_info() const {
return Engine::get_singleton()->get_donor_info();
}
Dictionary _Engine::get_license_info() const {
return Engine::get_singleton()->get_license_info();
}
String _Engine::get_license_text() const {
return Engine::get_singleton()->get_license_text();
}
bool _Engine::is_in_physics_frame() const {
return Engine::get_singleton()->is_in_physics_frame();
}
@ -2852,8 +2658,6 @@ void _Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_iterations_per_second", "iterations_per_second"), &_Engine::set_iterations_per_second);
ClassDB::bind_method(D_METHOD("get_iterations_per_second"), &_Engine::get_iterations_per_second);
ClassDB::bind_method(D_METHOD("set_physics_jitter_fix", "physics_jitter_fix"), &_Engine::set_physics_jitter_fix);
ClassDB::bind_method(D_METHOD("get_physics_jitter_fix"), &_Engine::get_physics_jitter_fix);
ClassDB::bind_method(D_METHOD("set_target_fps", "target_fps"), &_Engine::set_target_fps);
ClassDB::bind_method(D_METHOD("get_target_fps"), &_Engine::get_target_fps);
@ -2866,11 +2670,6 @@ void _Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_main_loop"), &_Engine::get_main_loop);
ClassDB::bind_method(D_METHOD("get_version_info"), &_Engine::get_version_info);
ClassDB::bind_method(D_METHOD("get_author_info"), &_Engine::get_author_info);
ClassDB::bind_method(D_METHOD("get_copyright_info"), &_Engine::get_copyright_info);
ClassDB::bind_method(D_METHOD("get_donor_info"), &_Engine::get_donor_info);
ClassDB::bind_method(D_METHOD("get_license_info"), &_Engine::get_license_info);
ClassDB::bind_method(D_METHOD("get_license_text"), &_Engine::get_license_text);
ClassDB::bind_method(D_METHOD("is_in_physics_frame"), &_Engine::is_in_physics_frame);
@ -2884,7 +2683,6 @@ void _Engine::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "iterations_per_second"), "set_iterations_per_second", "get_iterations_per_second");
ADD_PROPERTY(PropertyInfo(Variant::INT, "target_fps"), "set_target_fps", "get_target_fps");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "time_scale"), "set_time_scale", "get_time_scale");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "physics_jitter_fix"), "set_physics_jitter_fix", "get_physics_jitter_fix");
}
_Engine *_Engine::singleton = NULL;
@ -2904,10 +2702,10 @@ void JSONParseResult::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_error_line", "error_line"), &JSONParseResult::set_error_line);
ClassDB::bind_method(D_METHOD("set_result", "result"), &JSONParseResult::set_result);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "error", PROPERTY_HINT_NONE, "Error", PROPERTY_USAGE_CLASS_IS_ENUM), "set_error", "get_error");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "error_string"), "set_error_string", "get_error_string");
ADD_PROPERTY(PropertyInfo(Variant::INT, "error_line"), "set_error_line", "get_error_line");
ADD_PROPERTY(PropertyInfo(Variant::NIL, "result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_result", "get_result");
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "error", PROPERTY_HINT_NONE, "Error", PROPERTY_USAGE_CLASS_IS_ENUM), "set_error", "get_error");
ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "error_string"), "set_error_string", "get_error_string");
ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "error_line"), "set_error_line", "get_error_line");
ADD_PROPERTYNZ(PropertyInfo(Variant::NIL, "result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_result", "get_result");
}
void JSONParseResult::set_error(Error p_error) {

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,15 +31,15 @@
#ifndef CORE_BIND_H
#define CORE_BIND_H
#include "core/image.h"
#include "core/io/compression.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/os/dir_access.h"
#include "core/os/file_access.h"
#include "core/os/os.h"
#include "core/os/semaphore.h"
#include "core/os/thread.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/thread.h"
class _ResourceLoader : public Object {
GDCLASS(_ResourceLoader, Object);
@ -55,11 +55,7 @@ public:
PoolVector<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);
#ifndef DISABLE_DEPRECATED
bool has(const String &p_path);
#endif // DISABLE_DEPRECATED
bool has_cached(const String &p_path);
bool exists(const String &p_path, const String &p_type_hint = "");
_ResourceLoader();
};
@ -80,7 +76,6 @@ public:
FLAG_OMIT_EDITOR_PROPERTIES = 8,
FLAG_SAVE_BIG_ENDIAN = 16,
FLAG_COMPRESS = 32,
FLAG_REPLACE_SUBRESOURCE_PATHS = 64,
};
static _ResourceSaver *get_singleton() { return singleton; }
@ -103,11 +98,6 @@ protected:
static _OS *singleton;
public:
enum VideoDriver {
VIDEO_DRIVER_GLES3,
VIDEO_DRIVER_GLES2,
};
enum PowerState {
POWERSTATE_UNKNOWN, /**< cannot determine power status */
POWERSTATE_ON_BATTERY, /**< Not plugged in, running on the battery */
@ -156,17 +146,6 @@ public:
bool is_video_mode_resizable(int p_screen = 0) const;
Array get_fullscreen_mode_list(int p_screen = 0) const;
virtual int get_video_driver_count() const;
virtual String get_video_driver_name(VideoDriver p_driver) const;
virtual VideoDriver get_current_video_driver() const;
virtual int get_audio_driver_count() const;
virtual String get_audio_driver_name(int p_driver) const;
virtual PoolStringArray get_connected_midi_inputs();
virtual void open_midi_inputs();
virtual void close_midi_inputs();
virtual int get_screen_count() const;
virtual int get_current_screen() const;
virtual void set_current_screen(int p_screen);
@ -177,7 +156,6 @@ public:
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_fullscreen(bool p_enabled);
virtual bool is_window_fullscreen() const;
@ -187,22 +165,13 @@ 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 move_window_to_foreground();
virtual void set_borderless_window(bool p_borderless);
virtual bool get_borderless_window() const;
virtual bool get_window_per_pixel_transparency_enabled() const;
virtual void set_window_per_pixel_transparency_enabled(bool p_enabled);
virtual void set_ime_active(const bool p_active);
virtual void set_ime_position(const Point2 &p_pos);
virtual Point2 get_ime_selection() const;
virtual String get_ime_text() const;
Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track);
bool native_video_is_playing();
@ -282,21 +251,19 @@ public:
Dictionary get_date(bool utc) const;
Dictionary get_time(bool utc) const;
Dictionary get_datetime(bool utc) const;
Dictionary get_datetime_from_unix_time(int64_t unix_time_val) const;
int64_t get_unix_time_from_datetime(Dictionary datetime) const;
Dictionary get_datetime_from_unix_time(uint64_t unix_time_val) const;
uint64_t get_unix_time_from_datetime(Dictionary datetime) const;
Dictionary get_time_zone_info() const;
uint64_t get_unix_time() const;
uint64_t get_system_time_secs() const;
uint64_t get_system_time_msecs() const;
uint64_t get_static_memory_usage() const;
uint64_t get_static_memory_peak_usage() const;
uint64_t get_dynamic_memory_usage() const;
int get_static_memory_usage() const;
int get_static_memory_peak_usage() const;
int get_dynamic_memory_usage() const;
void delay_usec(uint32_t p_usec) const;
void delay_msec(uint32_t p_msec) const;
uint32_t get_ticks_msec() const;
uint64_t get_ticks_usec() const;
uint32_t get_splash_tick_msec() const;
bool can_use_threads() const;
@ -356,14 +323,11 @@ public:
bool has_feature(const String &p_feature) const;
bool request_permission(const String &p_name);
static _OS *get_singleton() { return singleton; }
_OS();
};
VARIANT_ENUM_CAST(_OS::VideoDriver);
VARIANT_ENUM_CAST(_OS::PowerState);
VARIANT_ENUM_CAST(_OS::Weekday);
VARIANT_ENUM_CAST(_OS::Month);
@ -385,7 +349,6 @@ public:
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);
Variant line_intersects_line_2d(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_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);
@ -444,9 +407,6 @@ public:
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
@ -463,11 +423,10 @@ public:
double get_double() const;
real_t get_real() const;
Variant get_var(bool p_allow_objects = false) const;
Variant get_var() const;
PoolVector<uint8_t> get_buffer(int p_length) const; ///< get an array of bytes
String get_line() const;
Vector<String> get_csv_line(const String &p_delim = ",") const;
String get_as_text() const;
String get_md5(const String &p_path) const;
String get_sha256(const String &p_path) const;
@ -493,14 +452,15 @@ public:
void store_string(const String &p_string);
void store_line(const String &p_string);
void store_csv_line(const Vector<String> &p_values, const String &p_delim = ",");
virtual void store_pascal_string(const String &p_string);
virtual String get_pascal_string();
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, bool p_full_objects = false);
void store_var(const Variant &p_var);
bool file_exists(const String &p_name) const; ///< return true if a file exists
@ -569,8 +529,8 @@ protected:
public:
static _Marshalls *get_singleton();
String variant_to_base64(const Variant &p_var, bool p_full_objects = false);
Variant base64_to_variant(const String &p_str, bool p_allow_objects = false);
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);
@ -697,9 +657,6 @@ public:
void set_iterations_per_second(int p_ips);
int get_iterations_per_second() const;
void set_physics_jitter_fix(float p_threshold);
float get_physics_jitter_fix() const;
void set_target_fps(int p_fps);
int get_target_fps() const;
@ -713,11 +670,6 @@ public:
MainLoop *get_main_loop() const;
Dictionary get_version_info() const;
Dictionary get_author_info() const;
Array get_copyright_info() const;
Dictionary get_donor_info() const;
Dictionary get_license_info() const;
String get_license_text() const;
bool is_in_physics_frame() const;

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -30,13 +30,21 @@
#include "class_db.h"
#include "core/engine.h"
#include "core/os/mutex.h"
#include "core/version.h"
#include "os/mutex.h"
#include "version.h"
#ifdef NO_THREADS
#define OBJTYPE_RLOCK
#define OBJTYPE_WLOCK
#else
#define OBJTYPE_RLOCK RWLockRead _rw_lockr_(lock);
#define OBJTYPE_WLOCK RWLockWrite _rw_lockw_(lock);
#endif
#ifdef DEBUG_METHODS_ENABLED
MethodDefinition D_METHOD(const char *p_name) {
@ -59,8 +67,8 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
MethodDefinition md;
md.name = StaticCString::create(p_name);
md.args.resize(2);
md.args.write[0] = StaticCString::create(p_arg1);
md.args.write[1] = StaticCString::create(p_arg2);
md.args[0] = StaticCString::create(p_arg1);
md.args[1] = StaticCString::create(p_arg2);
return md;
}
@ -69,9 +77,9 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
MethodDefinition md;
md.name = StaticCString::create(p_name);
md.args.resize(3);
md.args.write[0] = StaticCString::create(p_arg1);
md.args.write[1] = StaticCString::create(p_arg2);
md.args.write[2] = StaticCString::create(p_arg3);
md.args[0] = StaticCString::create(p_arg1);
md.args[1] = StaticCString::create(p_arg2);
md.args[2] = StaticCString::create(p_arg3);
return md;
}
@ -80,10 +88,10 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
MethodDefinition md;
md.name = StaticCString::create(p_name);
md.args.resize(4);
md.args.write[0] = StaticCString::create(p_arg1);
md.args.write[1] = StaticCString::create(p_arg2);
md.args.write[2] = StaticCString::create(p_arg3);
md.args.write[3] = StaticCString::create(p_arg4);
md.args[0] = StaticCString::create(p_arg1);
md.args[1] = StaticCString::create(p_arg2);
md.args[2] = StaticCString::create(p_arg3);
md.args[3] = StaticCString::create(p_arg4);
return md;
}
@ -92,11 +100,11 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
MethodDefinition md;
md.name = StaticCString::create(p_name);
md.args.resize(5);
md.args.write[0] = StaticCString::create(p_arg1);
md.args.write[1] = StaticCString::create(p_arg2);
md.args.write[2] = StaticCString::create(p_arg3);
md.args.write[3] = StaticCString::create(p_arg4);
md.args.write[4] = StaticCString::create(p_arg5);
md.args[0] = StaticCString::create(p_arg1);
md.args[1] = StaticCString::create(p_arg2);
md.args[2] = StaticCString::create(p_arg3);
md.args[3] = StaticCString::create(p_arg4);
md.args[4] = StaticCString::create(p_arg5);
return md;
}
@ -105,12 +113,12 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
MethodDefinition md;
md.name = StaticCString::create(p_name);
md.args.resize(6);
md.args.write[0] = StaticCString::create(p_arg1);
md.args.write[1] = StaticCString::create(p_arg2);
md.args.write[2] = StaticCString::create(p_arg3);
md.args.write[3] = StaticCString::create(p_arg4);
md.args.write[4] = StaticCString::create(p_arg5);
md.args.write[5] = StaticCString::create(p_arg6);
md.args[0] = StaticCString::create(p_arg1);
md.args[1] = StaticCString::create(p_arg2);
md.args[2] = StaticCString::create(p_arg3);
md.args[3] = StaticCString::create(p_arg4);
md.args[4] = StaticCString::create(p_arg5);
md.args[5] = StaticCString::create(p_arg6);
return md;
}
@ -119,13 +127,13 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
MethodDefinition md;
md.name = StaticCString::create(p_name);
md.args.resize(7);
md.args.write[0] = StaticCString::create(p_arg1);
md.args.write[1] = StaticCString::create(p_arg2);
md.args.write[2] = StaticCString::create(p_arg3);
md.args.write[3] = StaticCString::create(p_arg4);
md.args.write[4] = StaticCString::create(p_arg5);
md.args.write[5] = StaticCString::create(p_arg6);
md.args.write[6] = StaticCString::create(p_arg7);
md.args[0] = StaticCString::create(p_arg1);
md.args[1] = StaticCString::create(p_arg2);
md.args[2] = StaticCString::create(p_arg3);
md.args[3] = StaticCString::create(p_arg4);
md.args[4] = StaticCString::create(p_arg5);
md.args[5] = StaticCString::create(p_arg6);
md.args[6] = StaticCString::create(p_arg7);
return md;
}
@ -134,14 +142,14 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
MethodDefinition md;
md.name = StaticCString::create(p_name);
md.args.resize(8);
md.args.write[0] = StaticCString::create(p_arg1);
md.args.write[1] = StaticCString::create(p_arg2);
md.args.write[2] = StaticCString::create(p_arg3);
md.args.write[3] = StaticCString::create(p_arg4);
md.args.write[4] = StaticCString::create(p_arg5);
md.args.write[5] = StaticCString::create(p_arg6);
md.args.write[6] = StaticCString::create(p_arg7);
md.args.write[7] = StaticCString::create(p_arg8);
md.args[0] = StaticCString::create(p_arg1);
md.args[1] = StaticCString::create(p_arg2);
md.args[2] = StaticCString::create(p_arg3);
md.args[3] = StaticCString::create(p_arg4);
md.args[4] = StaticCString::create(p_arg5);
md.args[5] = StaticCString::create(p_arg6);
md.args[6] = StaticCString::create(p_arg7);
md.args[7] = StaticCString::create(p_arg8);
return md;
}
@ -150,15 +158,15 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
MethodDefinition md;
md.name = StaticCString::create(p_name);
md.args.resize(9);
md.args.write[0] = StaticCString::create(p_arg1);
md.args.write[1] = StaticCString::create(p_arg2);
md.args.write[2] = StaticCString::create(p_arg3);
md.args.write[3] = StaticCString::create(p_arg4);
md.args.write[4] = StaticCString::create(p_arg5);
md.args.write[5] = StaticCString::create(p_arg6);
md.args.write[6] = StaticCString::create(p_arg7);
md.args.write[7] = StaticCString::create(p_arg8);
md.args.write[8] = StaticCString::create(p_arg9);
md.args[0] = StaticCString::create(p_arg1);
md.args[1] = StaticCString::create(p_arg2);
md.args[2] = StaticCString::create(p_arg3);
md.args[3] = StaticCString::create(p_arg4);
md.args[4] = StaticCString::create(p_arg5);
md.args[5] = StaticCString::create(p_arg6);
md.args[6] = StaticCString::create(p_arg7);
md.args[7] = StaticCString::create(p_arg8);
md.args[8] = StaticCString::create(p_arg9);
return md;
}
@ -167,16 +175,16 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
MethodDefinition md;
md.name = StaticCString::create(p_name);
md.args.resize(10);
md.args.write[0] = StaticCString::create(p_arg1);
md.args.write[1] = StaticCString::create(p_arg2);
md.args.write[2] = StaticCString::create(p_arg3);
md.args.write[3] = StaticCString::create(p_arg4);
md.args.write[4] = StaticCString::create(p_arg5);
md.args.write[5] = StaticCString::create(p_arg6);
md.args.write[6] = StaticCString::create(p_arg7);
md.args.write[7] = StaticCString::create(p_arg8);
md.args.write[8] = StaticCString::create(p_arg9);
md.args.write[9] = StaticCString::create(p_arg10);
md.args[0] = StaticCString::create(p_arg1);
md.args[1] = StaticCString::create(p_arg2);
md.args[2] = StaticCString::create(p_arg3);
md.args[3] = StaticCString::create(p_arg4);
md.args[4] = StaticCString::create(p_arg5);
md.args[5] = StaticCString::create(p_arg6);
md.args[6] = StaticCString::create(p_arg7);
md.args[7] = StaticCString::create(p_arg8);
md.args[8] = StaticCString::create(p_arg9);
md.args[9] = StaticCString::create(p_arg10);
return md;
}
@ -185,17 +193,17 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
MethodDefinition md;
md.name = StaticCString::create(p_name);
md.args.resize(11);
md.args.write[0] = StaticCString::create(p_arg1);
md.args.write[1] = StaticCString::create(p_arg2);
md.args.write[2] = StaticCString::create(p_arg3);
md.args.write[3] = StaticCString::create(p_arg4);
md.args.write[4] = StaticCString::create(p_arg5);
md.args.write[5] = StaticCString::create(p_arg6);
md.args.write[6] = StaticCString::create(p_arg7);
md.args.write[7] = StaticCString::create(p_arg8);
md.args.write[8] = StaticCString::create(p_arg9);
md.args.write[9] = StaticCString::create(p_arg10);
md.args.write[10] = StaticCString::create(p_arg11);
md.args[0] = StaticCString::create(p_arg1);
md.args[1] = StaticCString::create(p_arg2);
md.args[2] = StaticCString::create(p_arg3);
md.args[3] = StaticCString::create(p_arg4);
md.args[4] = StaticCString::create(p_arg5);
md.args[5] = StaticCString::create(p_arg6);
md.args[6] = StaticCString::create(p_arg7);
md.args[7] = StaticCString::create(p_arg8);
md.args[8] = StaticCString::create(p_arg9);
md.args[9] = StaticCString::create(p_arg10);
md.args[10] = StaticCString::create(p_arg11);
return md;
}
@ -204,18 +212,18 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
MethodDefinition md;
md.name = StaticCString::create(p_name);
md.args.resize(12);
md.args.write[0] = StaticCString::create(p_arg1);
md.args.write[1] = StaticCString::create(p_arg2);
md.args.write[2] = StaticCString::create(p_arg3);
md.args.write[3] = StaticCString::create(p_arg4);
md.args.write[4] = StaticCString::create(p_arg5);
md.args.write[5] = StaticCString::create(p_arg6);
md.args.write[6] = StaticCString::create(p_arg7);
md.args.write[7] = StaticCString::create(p_arg8);
md.args.write[8] = StaticCString::create(p_arg9);
md.args.write[9] = StaticCString::create(p_arg10);
md.args.write[10] = StaticCString::create(p_arg11);
md.args.write[11] = StaticCString::create(p_arg12);
md.args[0] = StaticCString::create(p_arg1);
md.args[1] = StaticCString::create(p_arg2);
md.args[2] = StaticCString::create(p_arg3);
md.args[3] = StaticCString::create(p_arg4);
md.args[4] = StaticCString::create(p_arg5);
md.args[5] = StaticCString::create(p_arg6);
md.args[6] = StaticCString::create(p_arg7);
md.args[7] = StaticCString::create(p_arg8);
md.args[8] = StaticCString::create(p_arg9);
md.args[9] = StaticCString::create(p_arg10);
md.args[10] = StaticCString::create(p_arg11);
md.args[11] = StaticCString::create(p_arg12);
return md;
}
@ -224,19 +232,19 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
MethodDefinition md;
md.name = StaticCString::create(p_name);
md.args.resize(13);
md.args.write[0] = StaticCString::create(p_arg1);
md.args.write[1] = StaticCString::create(p_arg2);
md.args.write[2] = StaticCString::create(p_arg3);
md.args.write[3] = StaticCString::create(p_arg4);
md.args.write[4] = StaticCString::create(p_arg5);
md.args.write[5] = StaticCString::create(p_arg6);
md.args.write[6] = StaticCString::create(p_arg7);
md.args.write[7] = StaticCString::create(p_arg8);
md.args.write[8] = StaticCString::create(p_arg9);
md.args.write[9] = StaticCString::create(p_arg10);
md.args.write[10] = StaticCString::create(p_arg11);
md.args.write[11] = StaticCString::create(p_arg12);
md.args.write[12] = StaticCString::create(p_arg13);
md.args[0] = StaticCString::create(p_arg1);
md.args[1] = StaticCString::create(p_arg2);
md.args[2] = StaticCString::create(p_arg3);
md.args[3] = StaticCString::create(p_arg4);
md.args[4] = StaticCString::create(p_arg5);
md.args[5] = StaticCString::create(p_arg6);
md.args[6] = StaticCString::create(p_arg7);
md.args[7] = StaticCString::create(p_arg8);
md.args[8] = StaticCString::create(p_arg9);
md.args[9] = StaticCString::create(p_arg10);
md.args[10] = StaticCString::create(p_arg11);
md.args[11] = StaticCString::create(p_arg12);
md.args[12] = StaticCString::create(p_arg13);
return md;
}
@ -249,24 +257,17 @@ void ClassDB::set_current_api(APIType p_api) {
current_api = p_api;
}
ClassDB::APIType ClassDB::get_current_api() {
return current_api;
}
HashMap<StringName, ClassDB::ClassInfo> ClassDB::classes;
HashMap<StringName, StringName> ClassDB::resource_base_extensions;
HashMap<StringName, StringName> ClassDB::compat_classes;
HashMap<StringName, ClassDB::ClassInfo, StringNameHasher> ClassDB::classes;
HashMap<StringName, StringName, StringNameHasher> ClassDB::resource_base_extensions;
HashMap<StringName, StringName, StringNameHasher> ClassDB::compat_classes;
ClassDB::ClassInfo::ClassInfo() {
api = API_NONE;
creation_func = NULL;
inherits_ptr = NULL;
disabled = false;
exposed = false;
}
ClassDB::ClassInfo::~ClassInfo() {
}
@ -363,7 +364,7 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
ClassInfo *t = classes.getptr(E->get());
ERR_FAIL_COND_V(!t, 0);
if (t->api != p_api || !t->exposed)
if (t->api != p_api)
continue;
hash = hash_djb2_one_64(t->name.hash(), hash);
hash = hash_djb2_one_64(t->inherits.hash(), hash);
@ -518,12 +519,7 @@ Object *ClassDB::instance(const StringName &p_class) {
ERR_FAIL_COND_V(ti->disabled, NULL);
ERR_FAIL_COND_V(!ti->creation_func, NULL);
}
#ifdef TOOLS_ENABLED
if (ti->api == API_EDITOR && !Engine::get_singleton()->is_editor_hint()) {
ERR_PRINTS("Class '" + String(p_class) + "' can only be instantiated by editor.");
return NULL;
}
#endif
return ti->creation_func();
}
bool ClassDB::can_instance(const StringName &p_class) {
@ -664,6 +660,7 @@ void ClassDB::bind_integer_constant(const StringName &p_class, const StringName
}
type->constant_map[p_name] = p_constant;
#ifdef DEBUG_METHODS_ENABLED
String enum_name = p_enum;
if (enum_name != String()) {
@ -682,7 +679,6 @@ void ClassDB::bind_integer_constant(const StringName &p_class, const StringName
}
}
#ifdef DEBUG_METHODS_ENABLED
type->constant_order.push_back(p_name);
#endif
}
@ -738,6 +734,7 @@ int ClassDB::get_integer_constant(const StringName &p_class, const StringName &p
return 0;
}
#ifdef DEBUG_METHODS_ENABLED
StringName ClassDB::get_integer_constant_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) {
OBJTYPE_RLOCK;
@ -806,6 +803,7 @@ void ClassDB::get_enum_constants(const StringName &p_class, const StringName &p_
type = type->inherits_ptr;
}
}
#endif
void ClassDB::add_signal(StringName p_class, const MethodInfo &p_signal) {
@ -814,10 +812,10 @@ void ClassDB::add_signal(StringName p_class, const MethodInfo &p_signal) {
ClassInfo *type = classes.getptr(p_class);
ERR_FAIL_COND(!type);
StringName sname = p_signal.name;
#ifdef DEBUG_METHODS_ENABLED
ClassInfo *check = type;
StringName sname = p_signal.name;
#ifdef DEBUG_METHODS_ENABLED
while (check) {
if (check->signal_map.has(sname)) {
ERR_EXPLAIN("Type " + String(p_class) + " already has signal: " + String(sname));
@ -897,9 +895,15 @@ void ClassDB::add_property_group(StringName p_class, const String &p_name, const
void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index) {
#ifndef NO_THREADS
lock->read_lock();
#endif
ClassInfo *type = classes.getptr(p_class);
#ifndef NO_THREADS
lock->read_unlock();
#endif
ERR_FAIL_COND(!type);
@ -941,8 +945,9 @@ void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, cons
}
#ifdef DEBUG_METHODS_ENABLED
if (type->property_setget.has(p_pinfo.name)) {
ERR_EXPLAIN("Object " + p_class + " already has property: " + p_pinfo.name);
ERR_EXPLAIN("Object already has property: " + p_class);
ERR_FAIL();
}
#endif
@ -1256,7 +1261,7 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const c
defvals.resize(p_defcount);
for (int i = 0; i < p_defcount; i++) {
defvals.write[i] = *p_defs[p_defcount - i - 1];
defvals[i] = *p_defs[p_defcount - i - 1];
}
p_bind->set_default_arguments(defvals);
@ -1371,46 +1376,14 @@ void ClassDB::get_extensions_for_type(const StringName &p_class, List<String> *p
}
}
HashMap<StringName, HashMap<StringName, Variant> > ClassDB::default_values;
Variant ClassDB::class_get_default_property_value(const StringName &p_class, const StringName &p_property) {
if (!default_values.has(p_class)) {
default_values[p_class] = HashMap<StringName, Variant>();
if (ClassDB::can_instance(p_class)) {
Object *c = ClassDB::instance(p_class);
List<PropertyInfo> plist;
c->get_property_list(&plist);
for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
if (E->get().usage & (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR)) {
Variant v = c->get(E->get().name);
default_values[p_class][E->get().name] = v;
}
}
memdelete(c);
}
}
if (!default_values.has(p_class)) {
return Variant();
}
if (!default_values[p_class].has(p_property)) {
return Variant();
}
return default_values[p_class][p_property];
}
RWLock *ClassDB::lock = NULL;
void ClassDB::init() {
#ifndef NO_THREADS
lock = RWLock::create();
#endif
}
void ClassDB::cleanup() {
@ -1432,9 +1405,11 @@ void ClassDB::cleanup() {
classes.clear();
resource_base_extensions.clear();
compat_classes.clear();
default_values.clear();
#ifndef NO_THREADS
memdelete(lock);
#endif
}
//

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,18 +31,14 @@
#ifndef CLASS_DB_H
#define CLASS_DB_H
#include "core/method_bind.h"
#include "core/object.h"
#include "core/print_string.h"
#include "method_bind.h"
#include "object.h"
#include "print_string.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
/** To bind more then 6 parameters include this:
* #include "core/method_bind_ext.gen.inc"
*/
#define DEFVAL(m_defval) (m_defval)
//#define SIMPLE_METHODDEF
@ -118,19 +114,19 @@ public:
APIType api;
ClassInfo *inherits_ptr;
HashMap<StringName, MethodBind *> method_map;
HashMap<StringName, int> constant_map;
HashMap<StringName, List<StringName> > enum_map;
HashMap<StringName, MethodInfo> signal_map;
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> property_setget;
HashMap<StringName, PropertySetGet, StringNameHasher> property_setget;
StringName inherits;
StringName name;
@ -147,9 +143,9 @@ public:
}
static RWLock *lock;
static HashMap<StringName, ClassInfo> classes;
static HashMap<StringName, StringName> resource_base_extensions;
static HashMap<StringName, StringName> compat_classes;
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);
@ -161,8 +157,6 @@ public:
static void _add_class2(const StringName &p_class, const StringName &p_inherits);
static HashMap<StringName, HashMap<StringName, Variant> > default_values;
public:
// DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!!
template <class T>
@ -350,11 +344,11 @@ public:
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);
static Variant class_get_default_property_value(const StringName &p_class, const StringName &p_property);
#endif
static StringName get_category(const StringName &p_node);
@ -371,7 +365,6 @@ public:
static void init();
static void set_current_api(APIType p_api);
static APIType get_current_api();
static void cleanup();
};

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -30,85 +30,45 @@
#include "color.h"
#include "core/color_names.inc"
#include "core/map.h"
#include "core/math/math_funcs.h"
#include "core/print_string.h"
#include "color_names.inc"
#include "map.h"
#include "math_funcs.h"
#include "print_string.h"
uint32_t Color::to_argb32() const {
uint32_t c = (uint8_t)Math::round(a * 255);
uint32_t c = (uint8_t)(a * 255);
c <<= 8;
c |= (uint8_t)Math::round(r * 255);
c |= (uint8_t)(r * 255);
c <<= 8;
c |= (uint8_t)Math::round(g * 255);
c |= (uint8_t)(g * 255);
c <<= 8;
c |= (uint8_t)Math::round(b * 255);
c |= (uint8_t)(b * 255);
return c;
}
uint32_t Color::to_abgr32() const {
uint32_t c = (uint8_t)Math::round(a * 255);
uint32_t c = (uint8_t)(a * 255);
c <<= 8;
c |= (uint8_t)Math::round(b * 255);
c |= (uint8_t)(b * 255);
c <<= 8;
c |= (uint8_t)Math::round(g * 255);
c |= (uint8_t)(g * 255);
c <<= 8;
c |= (uint8_t)Math::round(r * 255);
c |= (uint8_t)(r * 255);
return c;
}
uint32_t Color::to_rgba32() const {
uint32_t c = (uint8_t)Math::round(r * 255);
uint32_t c = (uint8_t)(r * 255);
c <<= 8;
c |= (uint8_t)Math::round(g * 255);
c |= (uint8_t)(g * 255);
c <<= 8;
c |= (uint8_t)Math::round(b * 255);
c |= (uint8_t)(b * 255);
c <<= 8;
c |= (uint8_t)Math::round(a * 255);
return c;
}
uint64_t Color::to_abgr64() const {
uint64_t c = (uint16_t)Math::round(a * 65535);
c <<= 16;
c |= (uint16_t)Math::round(b * 65535);
c <<= 16;
c |= (uint16_t)Math::round(g * 65535);
c <<= 16;
c |= (uint16_t)Math::round(r * 65535);
return c;
}
uint64_t Color::to_argb64() const {
uint64_t c = (uint16_t)Math::round(a * 65535);
c <<= 16;
c |= (uint16_t)Math::round(r * 65535);
c <<= 16;
c |= (uint16_t)Math::round(g * 65535);
c <<= 16;
c |= (uint16_t)Math::round(b * 65535);
return c;
}
uint64_t Color::to_rgba64() const {
uint64_t c = (uint16_t)Math::round(r * 65535);
c <<= 16;
c |= (uint16_t)Math::round(g * 65535);
c <<= 16;
c |= (uint16_t)Math::round(b * 65535);
c <<= 16;
c |= (uint16_t)Math::round(a * 65535);
c |= (uint8_t)(a * 255);
return c;
}
@ -240,34 +200,6 @@ Color Color::hex(uint32_t p_hex) {
return Color(r, g, b, a);
}
Color Color::hex64(uint64_t p_hex) {
float a = (p_hex & 0xFFFF) / 65535.0;
p_hex >>= 16;
float b = (p_hex & 0xFFFF) / 65535.0;
p_hex >>= 16;
float g = (p_hex & 0xFFFF) / 65535.0;
p_hex >>= 16;
float r = (p_hex & 0xFFFF) / 65535.0;
return Color(r, g, b, a);
}
Color Color::from_rgbe9995(uint32_t p_rgbe) {
float r = p_rgbe & 0x1ff;
float g = (p_rgbe >> 9) & 0x1ff;
float b = (p_rgbe >> 18) & 0x1ff;
float e = (p_rgbe >> 27);
float m = Math::pow(2, e - 15.0 - 9.0);
float rd = r * m;
float gd = g * m;
float bd = b * m;
return Color(rd, gd, bd, 1.0f);
}
static float _parse_col(const String &p_str, int p_ofs) {
int ig = 0;
@ -436,7 +368,7 @@ Color Color::named(const String &p_name) {
String _to_hex(float p_val) {
int v = Math::round(p_val * 255);
int v = p_val * 255;
v = CLAMP(v, 0, 255);
String ret;
@ -468,64 +400,8 @@ String Color::to_html(bool p_alpha) const {
return txt;
}
Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const {
p_h = Math::fmod(p_h * 360.0f, 360.0f);
if (p_h < 0.0)
p_h += 360.0f;
const float h_ = p_h / 60.0f;
const float c = p_v * p_s;
const float x = c * (1.0f - Math::abs(Math::fmod(h_, 2.0f) - 1.0f));
float r, g, b;
switch ((int)h_) {
case 0: {
r = c;
g = x;
b = 0;
} break;
case 1: {
r = x;
g = c;
b = 0;
} break;
case 2: {
r = 0;
g = c;
b = x;
} break;
case 3: {
r = 0;
g = x;
b = c;
} break;
case 4: {
r = x;
g = 0;
b = c;
} break;
case 5: {
r = c;
g = 0;
b = x;
} break;
default: {
r = 0;
g = 0;
b = 0;
} break;
}
const float m = p_v - c;
return Color(m + r, m + g, m + b, p_a);
}
// FIXME: Remove once Godot 3.1 has been released
float Color::gray() const {
ERR_EXPLAIN("Color.gray() is deprecated and will be removed in a future version. Use Color.get_v() for a better grayscale approximation.");
WARN_DEPRECATED
return (r + g + b) / 3.0;
}

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,8 +31,8 @@
#ifndef COLOR_H
#define COLOR_H
#include "core/math/math_funcs.h"
#include "core/ustring.h"
#include "math_funcs.h"
#include "ustring.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@ -55,9 +55,6 @@ struct Color {
uint32_t to_rgba32() const;
uint32_t to_argb32() const;
uint32_t to_abgr32() const;
uint64_t to_rgba64() const;
uint64_t to_argb64() const;
uint64_t to_abgr64() const;
float gray() const;
float get_h() const;
float get_s() const;
@ -189,13 +186,10 @@ struct Color {
}
static Color hex(uint32_t p_hex);
static Color hex64(uint64_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;
Color from_hsv(float p_h, float p_s, float p_v, float p_a) const;
static Color from_rgbe9995(uint32_t p_color);
_FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys
operator String() const;

View File

@ -1,9 +1,9 @@
// 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 "core/map.h"
#include "map.h"
static Map<String, Color> _named_colors;
static void _populate_named_colors() {
if (!_named_colors.empty()) return;
if(!_named_colors.empty()) return;
_named_colors.insert("aliceblue", Color(0.94, 0.97, 1.00));
_named_colors.insert("antiquewhite", Color(0.98, 0.92, 0.84));
_named_colors.insert("aqua", Color(0.00, 1.00, 1.00));

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -30,7 +30,7 @@
#include "command_queue_mt.h"
#include "core/os/os.h"
#include "os/os.h"
void CommandQueueMT::lock() {
@ -97,7 +97,7 @@ tryagain:
return false;
}
dealloc_ptr += (size >> 1) + 8;
dealloc_ptr += (size >> 1) + sizeof(uint32_t);
return true;
}
@ -105,9 +105,7 @@ CommandQueueMT::CommandQueueMT(bool p_sync) {
read_ptr = 0;
write_ptr = 0;
dealloc_ptr = 0;
mutex = Mutex::create();
command_mem = (uint8_t *)memalloc(COMMAND_MEM_SIZE);
for (int i = 0; i < SYNC_SEMAPHORES; i++) {
@ -129,5 +127,4 @@ CommandQueueMT::~CommandQueueMT() {
memdelete(sync_sems[i].sem);
}
memfree(command_mem);
}

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,12 +31,11 @@
#ifndef COMMAND_QUEUE_MT_H
#define COMMAND_QUEUE_MT_H
#include "core/os/memory.h"
#include "core/os/mutex.h"
#include "core/os/semaphore.h"
#include "core/simple_type.h"
#include "core/typedefs.h"
#include "os/memory.h"
#include "os/mutex.h"
#include "os/semaphore.h"
#include "simple_type.h"
#include "typedefs.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@ -55,13 +54,9 @@
#define _COMMA_10 ,
#define _COMMA_11 ,
#define _COMMA_12 ,
#define _COMMA_13 ,
// 1-based comma separated list of ITEMs
#define COMMA_SEP_LIST(ITEM, LENGTH) _COMMA_SEP_LIST_##LENGTH(ITEM)
#define _COMMA_SEP_LIST_13(ITEM) \
_COMMA_SEP_LIST_12(ITEM) \
, ITEM(13)
#define _COMMA_SEP_LIST_12(ITEM) \
_COMMA_SEP_LIST_11(ITEM) \
, ITEM(12)
@ -102,9 +97,6 @@
// 1-based semicolon separated list of ITEMs
#define SEMIC_SEP_LIST(ITEM, LENGTH) _SEMIC_SEP_LIST_##LENGTH(ITEM)
#define _SEMIC_SEP_LIST_13(ITEM) \
_SEMIC_SEP_LIST_12(ITEM); \
ITEM(13)
#define _SEMIC_SEP_LIST_12(ITEM) \
_SEMIC_SEP_LIST_11(ITEM); \
ITEM(12)
@ -145,9 +137,6 @@
// 1-based space separated list of ITEMs
#define SPACE_SEP_LIST(ITEM, LENGTH) _SPACE_SEP_LIST_##LENGTH(ITEM)
#define _SPACE_SEP_LIST_13(ITEM) \
_SPACE_SEP_LIST_12(ITEM) \
ITEM(13)
#define _SPACE_SEP_LIST_12(ITEM) \
_SPACE_SEP_LIST_11(ITEM) \
ITEM(12)
@ -255,7 +244,6 @@
unlock(); \
if (sync) sync->post(); \
ss->sem->wait(); \
ss->in_use = false; \
}
#define CMD_SYNC_TYPE(N) CommandSync##N<T, M COMMA(N) COMMA_SEP_LIST(TYPE_ARG, N)>
@ -272,10 +260,9 @@
unlock(); \
if (sync) sync->post(); \
ss->sem->wait(); \
ss->in_use = false; \
}
#define MAX_CMD_PARAMS 13
#define MAX_CMD_PARAMS 12
class CommandQueueMT {
@ -298,19 +285,20 @@ class CommandQueueMT {
virtual void post() {
sync_sem->sem->post();
sync_sem->in_use = false;
}
};
DECL_CMD(0)
SPACE_SEP_LIST(DECL_CMD, 13)
SPACE_SEP_LIST(DECL_CMD, 12)
/* comands that return */
DECL_CMD_RET(0)
SPACE_SEP_LIST(DECL_CMD_RET, 13)
SPACE_SEP_LIST(DECL_CMD_RET, 12)
/* commands that don't return but sync */
DECL_CMD_SYNC(0)
SPACE_SEP_LIST(DECL_CMD_SYNC, 13)
SPACE_SEP_LIST(DECL_CMD_SYNC, 12)
/***** BASE *******/
@ -320,7 +308,7 @@ class CommandQueueMT {
SYNC_SEMAPHORES = 8
};
uint8_t *command_mem;
uint8_t command_mem[COMMAND_MEM_SIZE];
uint32_t read_ptr;
uint32_t write_ptr;
uint32_t dealloc_ptr;
@ -332,7 +320,7 @@ class CommandQueueMT {
T *allocate() {
// alloc size is size+T+safeguard
uint32_t alloc_size = ((sizeof(T) + 8 - 1) & ~(8 - 1)) + 8;
uint32_t alloc_size = sizeof(T) + sizeof(uint32_t);
tryagain:
@ -362,7 +350,7 @@ class CommandQueueMT {
}
// if this happens, it's a bug
ERR_FAIL_COND_V((COMMAND_MEM_SIZE - write_ptr) < 8, NULL);
ERR_FAIL_COND_V((COMMAND_MEM_SIZE - write_ptr) < sizeof(uint32_t), NULL);
// zero means, wrap to beginning
uint32_t *p = (uint32_t *)&command_mem[write_ptr];
@ -374,13 +362,12 @@ class CommandQueueMT {
// Allocate the size and the 'in use' bit.
// First bit used to mark if command is still in use (1)
// or if it has been destroyed and can be deallocated (0).
uint32_t size = (sizeof(T) + 8 - 1) & ~(8 - 1);
uint32_t *p = (uint32_t *)&command_mem[write_ptr];
*p = (size << 1) | 1;
write_ptr += 8;
*p = (sizeof(T) << 1) | 1;
write_ptr += sizeof(uint32_t);
// allocate the command
T *cmd = memnew_placement(&command_mem[write_ptr], T);
write_ptr += size;
write_ptr += sizeof(T);
return cmd;
}
@ -418,7 +405,7 @@ class CommandQueueMT {
goto tryagain;
}
read_ptr += 8;
read_ptr += sizeof(uint32_t);
CommandBase *cmd = reinterpret_cast<CommandBase *>(&command_mem[read_ptr]);
@ -445,15 +432,15 @@ class CommandQueueMT {
public:
/* NORMAL PUSH COMMANDS */
DECL_PUSH(0)
SPACE_SEP_LIST(DECL_PUSH, 13)
SPACE_SEP_LIST(DECL_PUSH, 12)
/* PUSH AND RET COMMANDS */
DECL_PUSH_AND_RET(0)
SPACE_SEP_LIST(DECL_PUSH_AND_RET, 13)
SPACE_SEP_LIST(DECL_PUSH_AND_RET, 12)
/* PUSH AND RET SYNC COMMANDS*/
DECL_PUSH_AND_SYNC(0)
SPACE_SEP_LIST(DECL_PUSH_AND_SYNC, 13)
SPACE_SEP_LIST(DECL_PUSH_AND_SYNC, 12)
void wait_and_flush_one() {
ERR_FAIL_COND(!sync);

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -30,7 +30,7 @@
#include "compressed_translation.h"
#include "core/pair.h"
#include "pair.h"
extern "C" {
#include "thirdparty/misc/smaz.h"
@ -50,6 +50,7 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) {
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;
@ -72,7 +73,7 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) {
Pair<int, CharString> p;
p.first = idx;
p.second = cs;
buckets.write[h % size].push_back(p);
buckets[h % size].push_back(p);
//compress string
CharString src_s = p_from->get_message(E->get()).operator String().utf8();
@ -83,7 +84,7 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) {
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.ptrw(), 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();
@ -99,22 +100,25 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) {
ps.compressed[0] = 0;
}
compressed.write[idx] = ps;
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).");
for (int i = 0; i < size; i++) {
const Vector<Pair<int, CharString> > &b = buckets[i];
Map<uint32_t, int> &t = table.write[i];
Vector<Pair<int, CharString> > &b = buckets[i];
Map<uint32_t, int> &t = table[i];
if (b.size() == 0)
continue;
//print_line("bucket: "+itos(i)+" - elements: "+itos(b.size()));
int d = 1;
int item = 0;
@ -132,10 +136,13 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) {
}
}
hfunc_table.write[i] = d;
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));
hash_table.resize(size);
bucket_table.resize(bucket_table_size);
@ -150,7 +157,7 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) {
for (int i = 0; i < size; i++) {
const Map<uint32_t, int> &t = table[i];
Map<uint32_t, int> &t = table[i];
if (t.size() == 0) {
htw[i] = 0xFFFFFFFF; //nothing
continue;
@ -171,6 +178,8 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) {
}
}
print_line("total collisions: " + itos(collisions));
strings.resize(total_compression_size);
PoolVector<uint8_t>::Write cw = strings.write();
@ -189,11 +198,15 @@ 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;
//print_line("translation: loaded hash table of size: "+itos(hash_table.size()));
} 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;
//print_line("translation: loaded string table of size: "+itos(strings.size()));
} else if (name == "load_from") {
//print_line("generating");
generate(p_value);
} else
return false;
@ -235,7 +248,11 @@ StringName PHashTranslation::get_message(const StringName &p_src_text) const {
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!");
return StringName(); //nothing
}
@ -254,7 +271,9 @@ StringName PHashTranslation::get_message(const StringName &p_src_text) const {
}
}
//print_line("bucket pos: "+itos(idx));
if (idx == -1) {
//print_line("GETMSG: Not in Bucket!");
return StringName();
}
@ -262,6 +281,8 @@ StringName PHashTranslation::get_message(const StringName &p_src_text) const {
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);
return rstr;
} else {
@ -271,6 +292,8 @@ StringName PHashTranslation::get_message(const StringName &p_src_text) const {
smaz_decompress(&sptr[bucket.elem[idx].str_offset], bucket.elem[idx].comp_size, uncomp.ptrw(), 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);
return rstr;
}
}

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,7 +31,7 @@
#ifndef COMPRESSED_TRANSLATION_H
#define COMPRESSED_TRANSLATION_H
#include "core/translation.h"
#include "translation.h"
class PHashTranslation : public Translation {

View File

@ -1,269 +0,0 @@
"""Functions used to generate source files during build time
All such functions are invoked in a subprocess on Windows to prevent build flakiness.
"""
from platform_methods import subprocess_main
from compat import iteritems, itervalues, open_utf8, escape_string, byte_to_str
def make_certs_header(target, source, env):
src = source[0]
dst = target[0]
f = open(src, "rb")
g = open_utf8(dst, "w")
buf = f.read()
decomp_size = len(buf)
import zlib
buf = zlib.compress(buf)
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
g.write("#ifndef _CERTS_RAW_H\n")
g.write("#define _CERTS_RAW_H\n")
# System certs path. Editor will use them if defined. (for package maintainers)
path = env['system_certs_path']
g.write("#define _SYSTEM_CERTS_PATH \"%s\"\n" % str(path))
if env['builtin_certs']:
# Defined here and not in env so changing it does not trigger a full rebuild.
g.write("#define BUILTIN_CERTS_ENABLED\n")
g.write("static const int _certs_compressed_size = " + str(len(buf)) + ";\n")
g.write("static const int _certs_uncompressed_size = " + str(decomp_size) + ";\n")
g.write("static const unsigned char _certs_compressed[] = {\n")
for i in range(len(buf)):
g.write("\t" + byte_to_str(buf[i]) + ",\n")
g.write("};\n")
g.write("#endif")
g.close()
f.close()
def make_authors_header(target, source, env):
sections = ["Project Founders", "Lead Developer", "Project Manager", "Developers"]
sections_id = ["AUTHORS_FOUNDERS", "AUTHORS_LEAD_DEVELOPERS", "AUTHORS_PROJECT_MANAGERS", "AUTHORS_DEVELOPERS"]
src = source[0]
dst = target[0]
f = open_utf8(src, "r")
g = open_utf8(dst, "w")
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
g.write("#ifndef _EDITOR_AUTHORS_H\n")
g.write("#define _EDITOR_AUTHORS_H\n")
reading = False
def close_section():
g.write("\t0\n")
g.write("};\n")
for line in f:
if reading:
if line.startswith(" "):
g.write("\t\"" + escape_string(line.strip()) + "\",\n")
continue
if line.startswith("## "):
if reading:
close_section()
reading = False
for section, section_id in zip(sections, sections_id):
if line.strip().endswith(section):
current_section = escape_string(section_id)
reading = True
g.write("const char *const " + current_section + "[] = {\n")
break
if reading:
close_section()
g.write("#endif\n")
g.close()
f.close()
def make_donors_header(target, source, env):
sections = ["Platinum sponsors", "Gold sponsors", "Mini sponsors",
"Gold donors", "Silver donors", "Bronze donors"]
sections_id = ["DONORS_SPONSOR_PLAT", "DONORS_SPONSOR_GOLD", "DONORS_SPONSOR_MINI",
"DONORS_GOLD", "DONORS_SILVER", "DONORS_BRONZE"]
src = source[0]
dst = target[0]
f = open_utf8(src, "r")
g = open_utf8(dst, "w")
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
g.write("#ifndef _EDITOR_DONORS_H\n")
g.write("#define _EDITOR_DONORS_H\n")
reading = False
def close_section():
g.write("\t0\n")
g.write("};\n")
for line in f:
if reading >= 0:
if line.startswith(" "):
g.write("\t\"" + escape_string(line.strip()) + "\",\n")
continue
if line.startswith("## "):
if reading:
close_section()
reading = False
for section, section_id in zip(sections, sections_id):
if line.strip().endswith(section):
current_section = escape_string(section_id)
reading = True
g.write("const char *const " + current_section + "[] = {\n")
break
if reading:
close_section()
g.write("#endif\n")
g.close()
f.close()
def make_license_header(target, source, env):
src_copyright = source[0]
src_license = source[1]
dst = target[0]
class LicenseReader:
def __init__(self, license_file):
self._license_file = license_file
self.line_num = 0
self.current = self.next_line()
def next_line(self):
line = self._license_file.readline()
self.line_num += 1
while line.startswith("#"):
line = self._license_file.readline()
self.line_num += 1
self.current = line
return line
def next_tag(self):
if not ':' in self.current:
return ('', [])
tag, line = self.current.split(":", 1)
lines = [line.strip()]
while self.next_line() and self.current.startswith(" "):
lines.append(self.current.strip())
return (tag, lines)
from collections import OrderedDict
projects = OrderedDict()
license_list = []
with open_utf8(src_copyright, "r") as copyright_file:
reader = LicenseReader(copyright_file)
part = {}
while reader.current:
tag, content = reader.next_tag()
if tag in ("Files", "Copyright", "License"):
part[tag] = content[:]
elif tag == "Comment":
# attach part to named project
projects[content[0]] = projects.get(content[0], []) + [part]
if not tag or not reader.current:
# end of a paragraph start a new part
if "License" in part and not "Files" in part:
# no Files tag in this one, so assume standalone license
license_list.append(part["License"])
part = {}
reader.next_line()
data_list = []
for project in itervalues(projects):
for part in project:
part["file_index"] = len(data_list)
data_list += part["Files"]
part["copyright_index"] = len(data_list)
data_list += part["Copyright"]
with open_utf8(dst, "w") as f:
f.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
f.write("#ifndef _EDITOR_LICENSE_H\n")
f.write("#define _EDITOR_LICENSE_H\n")
f.write("const char *const GODOT_LICENSE_TEXT =")
with open_utf8(src_license, "r") as license_file:
for line in license_file:
escaped_string = escape_string(line.strip())
f.write("\n\t\t\"" + escaped_string + "\\n\"")
f.write(";\n\n")
f.write("struct ComponentCopyrightPart {\n"
"\tconst char *license;\n"
"\tconst char *const *files;\n"
"\tconst char *const *copyright_statements;\n"
"\tint file_count;\n"
"\tint copyright_count;\n"
"};\n\n")
f.write("struct ComponentCopyright {\n"
"\tconst char *name;\n"
"\tconst ComponentCopyrightPart *parts;\n"
"\tint part_count;\n"
"};\n\n")
f.write("const char *const COPYRIGHT_INFO_DATA[] = {\n")
for line in data_list:
f.write("\t\"" + escape_string(line) + "\",\n")
f.write("};\n\n")
f.write("const ComponentCopyrightPart COPYRIGHT_PROJECT_PARTS[] = {\n")
part_index = 0
part_indexes = {}
for project_name, project in iteritems(projects):
part_indexes[project_name] = part_index
for part in project:
f.write("\t{ \"" + escape_string(part["License"][0]) + "\", "
+ "&COPYRIGHT_INFO_DATA[" + str(part["file_index"]) + "], "
+ "&COPYRIGHT_INFO_DATA[" + str(part["copyright_index"]) + "], "
+ str(len(part["Files"])) + ", "
+ str(len(part["Copyright"])) + " },\n")
part_index += 1
f.write("};\n\n")
f.write("const int COPYRIGHT_INFO_COUNT = " + str(len(projects)) + ";\n")
f.write("const ComponentCopyright COPYRIGHT_INFO[] = {\n")
for project_name, project in iteritems(projects):
f.write("\t{ \"" + escape_string(project_name) + "\", "
+ "&COPYRIGHT_PROJECT_PARTS[" + str(part_indexes[project_name]) + "], "
+ str(len(project)) + " },\n")
f.write("};\n\n")
f.write("const int LICENSE_COUNT = " + str(len(license_list)) + ";\n")
f.write("const char *const LICENSE_NAMES[] = {\n")
for l in license_list:
f.write("\t\"" + escape_string(l[0]) + "\",\n")
f.write("};\n\n")
f.write("const char *const LICENSE_BODIES[] = {\n\n")
for l in license_list:
for line in l[1:]:
if line == ".":
f.write("\t\"\\n\"\n")
else:
f.write("\t\"" + escape_string(line) + "\\n\"\n")
f.write("\t\"\",\n\n")
f.write("};\n\n")
f.write("#endif\n")
if __name__ == '__main__':
subprocess_main(globals())

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -47,27 +47,28 @@ CoreStringNames::CoreStringNames() :
#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")) {
_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");
}

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,7 +31,7 @@
#ifndef CORE_STRING_NAMES_H
#define CORE_STRING_NAMES_H
#include "core/string_name.h"
#include "string_db.h"
class CoreStringNames {

View File

@ -1,372 +0,0 @@
/*************************************************************************/
/* cowdata.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 COWDATA_H_
#define COWDATA_H_
#include <string.h>
#include "core/os/memory.h"
#include "core/safe_refcount.h"
template <class T>
class Vector;
class String;
class CharString;
template <class T, class V>
class VMap;
template <class T>
class CowData {
template <class TV>
friend class Vector;
friend class String;
friend class CharString;
template <class TV, class VV>
friend class VMap;
private:
mutable T *_ptr;
// internal helpers
_FORCE_INLINE_ uint32_t *_get_refcount() const {
if (!_ptr)
return NULL;
return reinterpret_cast<uint32_t *>(_ptr) - 2;
}
_FORCE_INLINE_ uint32_t *_get_size() const {
if (!_ptr)
return NULL;
return reinterpret_cast<uint32_t *>(_ptr) - 1;
}
_FORCE_INLINE_ T *_get_data() const {
if (!_ptr)
return NULL;
return reinterpret_cast<T *>(_ptr);
}
_FORCE_INLINE_ size_t _get_alloc_size(size_t p_elements) const {
//return nearest_power_of_2_templated(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int));
return next_power_of_2(p_elements * sizeof(T));
}
_FORCE_INLINE_ bool _get_alloc_size_checked(size_t p_elements, size_t *out) const {
#if defined(_add_overflow) && defined(_mul_overflow)
size_t o;
size_t p;
if (_mul_overflow(p_elements, sizeof(T), &o)) {
*out = 0;
return false;
}
*out = next_power_of_2(o);
if (_add_overflow(o, static_cast<size_t>(32), &p)) return false; //no longer allocated here
return true;
#else
// Speed is more important than correctness here, do the operations unchecked
// and hope the best
*out = _get_alloc_size(p_elements);
return true;
#endif
}
void _unref(void *p_data);
void _ref(const CowData *p_from);
void _ref(const CowData &p_from);
void _copy_on_write();
public:
void operator=(const CowData<T> &p_from) { _ref(p_from); }
_FORCE_INLINE_ T *ptrw() {
_copy_on_write();
return (T *)_get_data();
}
_FORCE_INLINE_ const T *ptr() const {
return _get_data();
}
_FORCE_INLINE_ int size() const {
uint32_t *size = (uint32_t *)_get_size();
if (size)
return *size;
else
return 0;
}
_FORCE_INLINE_ void clear() { resize(0); }
_FORCE_INLINE_ bool empty() const { return _ptr == 0; }
_FORCE_INLINE_ void set(int p_index, const T &p_elem) {
CRASH_BAD_INDEX(p_index, size());
_copy_on_write();
_get_data()[p_index] = p_elem;
}
_FORCE_INLINE_ T &get_m(int p_index) {
CRASH_BAD_INDEX(p_index, size());
_copy_on_write();
return _get_data()[p_index];
}
_FORCE_INLINE_ const T &get(int p_index) const {
CRASH_BAD_INDEX(p_index, size());
return _get_data()[p_index];
}
Error resize(int p_size);
_FORCE_INLINE_ void remove(int p_index) {
ERR_FAIL_INDEX(p_index, size());
T *p = ptrw();
int len = size();
for (int i = p_index; i < len - 1; i++) {
p[i] = p[i + 1];
};
resize(len - 1);
};
Error insert(int p_pos, const T &p_val) {
ERR_FAIL_INDEX_V(p_pos, size() + 1, ERR_INVALID_PARAMETER);
resize(size() + 1);
for (int i = (size() - 1); i > p_pos; i--)
set(i, get(i - 1));
set(p_pos, p_val);
return OK;
};
int find(const T &p_val, int p_from = 0) const;
_FORCE_INLINE_ CowData();
_FORCE_INLINE_ ~CowData();
_FORCE_INLINE_ CowData(CowData<T> &p_from) { _ref(p_from); };
};
template <class T>
void CowData<T>::_unref(void *p_data) {
if (!p_data)
return;
uint32_t *refc = _get_refcount();
if (atomic_decrement(refc) > 0)
return; // still in use
// clean up
if (!__has_trivial_destructor(T)) {
uint32_t *count = _get_size();
T *data = (T *)(count + 1);
for (uint32_t i = 0; i < *count; ++i) {
// call destructors
data[i].~T();
}
}
// free mem
Memory::free_static((uint8_t *)p_data, true);
}
template <class T>
void CowData<T>::_copy_on_write() {
if (!_ptr)
return;
uint32_t *refc = _get_refcount();
if (unlikely(*refc > 1)) {
/* in use by more than me */
uint32_t current_size = *_get_size();
uint32_t *mem_new = (uint32_t *)Memory::alloc_static(_get_alloc_size(current_size), true);
*(mem_new - 2) = 1; //refcount
*(mem_new - 1) = current_size; //size
T *_data = (T *)(mem_new);
// initialize new elements
if (__has_trivial_copy(T)) {
memcpy(mem_new, _ptr, current_size * sizeof(T));
} else {
for (uint32_t i = 0; i < current_size; i++) {
memnew_placement(&_data[i], T(_get_data()[i]));
}
}
_unref(_ptr);
_ptr = _data;
}
}
template <class T>
Error CowData<T>::resize(int p_size) {
ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER);
if (p_size == size())
return OK;
if (p_size == 0) {
// wants to clean up
_unref(_ptr);
_ptr = NULL;
return OK;
}
// possibly changing size, copy on write
_copy_on_write();
size_t alloc_size;
ERR_FAIL_COND_V(!_get_alloc_size_checked(p_size, &alloc_size), ERR_OUT_OF_MEMORY);
if (p_size > size()) {
if (size() == 0) {
// alloc from scratch
uint32_t *ptr = (uint32_t *)Memory::alloc_static(alloc_size, true);
ERR_FAIL_COND_V(!ptr, ERR_OUT_OF_MEMORY);
*(ptr - 1) = 0; //size, currently none
*(ptr - 2) = 1; //refcount
_ptr = (T *)ptr;
} else {
void *_ptrnew = (T *)Memory::realloc_static(_ptr, alloc_size, true);
ERR_FAIL_COND_V(!_ptrnew, ERR_OUT_OF_MEMORY);
_ptr = (T *)(_ptrnew);
}
// construct the newly created elements
if (!__has_trivial_constructor(T)) {
T *elems = _get_data();
for (int i = *_get_size(); i < p_size; i++) {
memnew_placement(&elems[i], T);
}
}
*_get_size() = p_size;
} else if (p_size < size()) {
if (!__has_trivial_destructor(T)) {
// deinitialize no longer needed elements
for (uint32_t i = p_size; i < *_get_size(); i++) {
T *t = &_get_data()[i];
t->~T();
}
}
void *_ptrnew = (T *)Memory::realloc_static(_ptr, alloc_size, true);
ERR_FAIL_COND_V(!_ptrnew, ERR_OUT_OF_MEMORY);
_ptr = (T *)(_ptrnew);
*_get_size() = p_size;
}
return OK;
}
template <class T>
int CowData<T>::find(const T &p_val, int p_from) const {
int ret = -1;
if (p_from < 0 || size() == 0) {
return ret;
}
for (int i = p_from; i < size(); i++) {
if (get(i) == p_val) {
ret = i;
break;
}
}
return ret;
}
template <class T>
void CowData<T>::_ref(const CowData *p_from) {
_ref(*p_from);
}
template <class T>
void CowData<T>::_ref(const CowData &p_from) {
if (_ptr == p_from._ptr)
return; // self assign, do nothing.
_unref(_ptr);
_ptr = NULL;
if (!p_from._ptr)
return; //nothing to do
if (atomic_conditional_increment(p_from._get_refcount()) > 0) { // could reference
_ptr = p_from._ptr;
}
}
template <class T>
CowData<T>::CowData() {
_ptr = NULL;
}
template <class T>
CowData<T>::~CowData() {
_unref(_ptr);
}
#endif /* COW_H_ */

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -30,9 +30,9 @@
#include "dictionary.h"
#include "core/ordered_hash_map.h"
#include "core/safe_refcount.h"
#include "core/variant.h"
#include "ordered_hash_map.h"
#include "safe_refcount.h"
#include "variant.h"
struct DictionaryPrivate {
@ -50,32 +50,6 @@ void Dictionary::get_key_list(List<Variant> *p_keys) const {
}
}
Variant Dictionary::get_key_at_index(int p_index) const {
int index = 0;
for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
if (index == p_index) {
return E.key();
}
index++;
}
return Variant();
}
Variant Dictionary::get_value_at_index(int p_index) const {
int index = 0;
for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
if (index == p_index) {
return E.value();
}
index++;
}
return Variant();
}
Variant &Dictionary::operator[](const Variant &p_key) {
return _p->variant_map[p_key];
@ -112,15 +86,6 @@ Variant Dictionary::get_valid(const Variant &p_key) const {
return E.get();
}
Variant Dictionary::get(const Variant &p_key, const Variant &p_default) const {
const Variant *result = getptr(p_key);
if (!result) {
return p_default;
}
return *result;
}
int Dictionary::size() const {
return _p->variant_map.size();
@ -144,9 +109,9 @@ bool Dictionary::has_all(const Array &p_keys) const {
return true;
}
bool Dictionary::erase(const Variant &p_key) {
void Dictionary::erase(const Variant &p_key) {
return _p->variant_map.erase(p_key);
_p->variant_map.erase(p_key);
}
bool Dictionary::operator==(const Dictionary &p_dictionary) const {
@ -154,11 +119,6 @@ bool Dictionary::operator==(const Dictionary &p_dictionary) const {
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 {
//make a copy first (thread safe)
@ -251,7 +211,7 @@ const Variant *Dictionary::next(const Variant *p_key) const {
return NULL;
}
Dictionary Dictionary::duplicate(bool p_deep) const {
Dictionary Dictionary::duplicate() const {
Dictionary n;
@ -259,7 +219,7 @@ Dictionary Dictionary::duplicate(bool p_deep) const {
get_key_list(&keys);
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
n[E->get()] = p_deep ? operator[](E->get()).duplicate(p_deep) : operator[](E->get());
n[E->get()] = operator[](E->get());
}
return n;

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,10 +31,9 @@
#ifndef DICTIONARY_H
#define DICTIONARY_H
#include "core/array.h"
#include "core/list.h"
#include "core/ustring.h"
#include "array.h"
#include "list.h"
#include "ustring.h"
class Variant;
struct DictionaryPrivate;
@ -48,8 +47,6 @@ class Dictionary {
public:
void get_key_list(List<Variant> *p_keys) const;
Variant get_key_at_index(int p_index) const;
Variant get_value_at_index(int p_index) const;
Variant &operator[](const Variant &p_key);
const Variant &operator[](const Variant &p_key) const;
@ -58,7 +55,6 @@ public:
Variant *getptr(const Variant &p_key);
Variant get_valid(const Variant &p_key) const;
Variant get(const Variant &p_key, const Variant &p_default) const;
int size() const;
bool empty() const;
@ -67,10 +63,9 @@ public:
bool has(const Variant &p_key) const;
bool has_all(const Array &p_keys) const;
bool erase(const Variant &p_key);
void erase(const Variant &p_key);
bool operator==(const Dictionary &p_dictionary) const;
bool operator!=(const Dictionary &p_dictionary) const;
uint32_t hash() const;
void operator=(const Dictionary &p_dictionary);
@ -80,7 +75,7 @@ public:
Array keys() const;
Array values() const;
Dictionary duplicate(bool p_deep = false) const;
Dictionary duplicate() const;
Dictionary(const Dictionary &p_from);
Dictionary();

71
core/dvector.cpp Normal file
View File

@ -0,0 +1,71 @@
/*************************************************************************/
/* dvector.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 "dvector.h"
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 Normal file
View File

@ -0,0 +1,643 @@
/*************************************************************************/
/* dvector.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 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;
void _copy_on_write() {
if (!alloc)
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
// Refcount should not be zero, otherwise it's a misuse of COW
if (alloc->refcount.get() == 1)
return; //nothing to do
//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();
}
MemoryPool::Alloc *old_alloc = alloc;
//take one from the free list
alloc = MemoryPool::free_list;
MemoryPool::free_list = alloc->free_list;
//increment the used counter
MemoryPool::allocs_used++;
//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);
}
{
Write w;
w._ref(alloc);
Read r;
r._ref(old_alloc);
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]));
}
}
if (old_alloc->refcount.unref() == true) {
//this should never happen but..
#ifdef DEBUG_ENABLED
MemoryPool::alloc_mutex->lock();
MemoryPool::total_memory -= old_alloc->size;
MemoryPool::alloc_mutex->unlock();
#endif
{
Write w;
w._ref(old_alloc);
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 (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) {
if (alloc == p_dvector.alloc)
return;
_unreference();
if (!p_dvector.alloc) {
return;
}
if (p_dvector.alloc->refcount.ref()) {
alloc = p_dvector.alloc;
}
}
void _unreference() {
if (!alloc)
return;
if (alloc->refcount.unref() == false) {
alloc = NULL;
return;
}
//must be disposed!
{
int cur_elements = alloc->size / sizeof(T);
// 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);
for (int i = 0; i < cur_elements; i++) {
w[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 {
memfree(alloc->mem);
alloc->mem = NULL;
alloc->size = 0;
MemoryPool::alloc_mutex->lock();
alloc->free_list = MemoryPool::free_list;
MemoryPool::free_list = alloc;
MemoryPool::allocs_used--;
MemoryPool::alloc_mutex->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;
}
public:
virtual ~Access() {
_unref();
}
};
class Read : public Access {
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);
}
Read(const Read &p_read) {
this->_ref(p_read.alloc);
}
Read() {}
};
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);
}
return r;
}
Write write() {
Write w;
if (alloc) {
_copy_on_write(); //make sure there is only one being acessed
w._ref(alloc);
}
return w;
}
template <class MC>
void fill_with(const MC &p_mc) {
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()) {
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++) {
w[i] = w[i + 1];
};
w = Write();
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) {
int ds = p_arr.size();
if (ds == 0)
return;
int bs = size();
resize(bs + ds);
Write w = write();
Read r = p_arr.read();
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;
}
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);
{
Write w = write();
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; }
inline const T operator[](int p_index) const;
Error resize(int p_size);
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(); }
};
template <class T>
int PoolVector<T>::size() const {
return alloc ? alloc->size / sizeof(T) : 0;
}
template <class T>
T PoolVector<T>::get(int p_index) const {
return operator[](p_index);
}
template <class T>
void PoolVector<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());
}
Write w = write();
w[p_index] = p_val;
}
template <class T>
void PoolVector<T>::push_back(const T &p_val) {
resize(size() + 1);
set(size() - 1, p_val);
}
template <class T>
const T PoolVector<T>::operator[](int p_index) const {
CRASH_BAD_INDEX(p_index, size());
Read r = read();
return r[p_index];
}
template <class T>
Error PoolVector<T>::resize(int p_size) {
if (alloc == NULL) {
if (p_size == 0)
return OK; //nothing to do here
//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);
}
//take one from the free list
alloc = MemoryPool::free_list;
MemoryPool::free_list = alloc->free_list;
//increment the used counter
MemoryPool::allocs_used++;
//cleanup the alloc
alloc->size = 0;
alloc->refcount.init();
alloc->pool_id = POOL_ALLOCATOR_INVALID_ID;
MemoryPool::alloc_mutex->unlock();
} else {
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();
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
int cur_elements = alloc->size / sizeof(T);
if (p_size > cur_elements) {
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);
}
}
alloc->size = new_size;
Write w = write();
for (int i = cur_elements; i < p_size; i++) {
memnew_placement(&w[i], T);
}
} else {
{
Write w = write();
for (int i = p_size; i < cur_elements; i++) {
w[i].~T();
}
}
if (MemoryPool::memory_pool) {
//resize memory pool
//if none, create
//if some resize
} else {
if (new_size == 0) {
memfree(alloc->mem);
alloc->mem = NULL;
alloc->size = 0;
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;
}
}
}
return OK;
}
template <class T>
void PoolVector<T>::invert() {
T temp;
Write w = write();
int s = size();
int half_s = s / 2;
for (int i = 0; i < half_s; i++) {
temp = w[i];
w[i] = w[s - i - 1];
w[s - i - 1] = temp;
}
}
#endif

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -30,11 +30,8 @@
#include "engine.h"
#include "core/authors.gen.h"
#include "core/donors.gen.h"
#include "core/license.gen.h"
#include "core/version.h"
#include "core/version_hash.gen.h"
#include "version.h"
#include "version_hash.gen.h"
void Engine::set_iterations_per_second(int p_ips) {
@ -45,16 +42,6 @@ int Engine::get_iterations_per_second() const {
return ips;
}
void Engine::set_physics_jitter_fix(float p_threshold) {
if (p_threshold < 0)
p_threshold = 0;
physics_jitter_fix = p_threshold;
}
float Engine::get_physics_jitter_fix() const {
return physics_jitter_fix;
}
void Engine::set_target_fps(int p_fps) {
_target_fps = p_fps > 0 ? p_fps : 0;
}
@ -98,7 +85,6 @@ Dictionary Engine::get_version_info() const {
#else
dict["patch"] = 0;
#endif
dict["hex"] = VERSION_HEX;
dict["status"] = VERSION_STATUS;
dict["build"] = VERSION_BUILD;
dict["year"] = VERSION_YEAR;
@ -115,78 +101,6 @@ Dictionary Engine::get_version_info() const {
return dict;
}
static Array array_from_info(const char *const *info_list) {
Array arr;
for (int i = 0; info_list[i] != NULL; i++) {
arr.push_back(info_list[i]);
}
return arr;
}
static Array array_from_info_count(const char *const *info_list, int info_count) {
Array arr;
for (int i = 0; i < info_count; i++) {
arr.push_back(info_list[i]);
}
return arr;
}
Dictionary Engine::get_author_info() const {
Dictionary dict;
dict["lead_developers"] = array_from_info(AUTHORS_LEAD_DEVELOPERS);
dict["project_managers"] = array_from_info(AUTHORS_PROJECT_MANAGERS);
dict["founders"] = array_from_info(AUTHORS_FOUNDERS);
dict["developers"] = array_from_info(AUTHORS_DEVELOPERS);
return dict;
}
Array Engine::get_copyright_info() const {
Array components;
for (int component_index = 0; component_index < COPYRIGHT_INFO_COUNT; component_index++) {
const ComponentCopyright &cp_info = COPYRIGHT_INFO[component_index];
Dictionary component_dict;
component_dict["name"] = cp_info.name;
Array parts;
for (int i = 0; i < cp_info.part_count; i++) {
const ComponentCopyrightPart &cp_part = cp_info.parts[i];
Dictionary part_dict;
part_dict["files"] = array_from_info_count(cp_part.files, cp_part.file_count);
part_dict["copyright"] = array_from_info_count(cp_part.copyright_statements, cp_part.copyright_count);
part_dict["license"] = cp_part.license;
parts.push_back(part_dict);
}
component_dict["parts"] = parts;
components.push_back(component_dict);
}
return components;
}
Dictionary Engine::get_donor_info() const {
Dictionary donors;
donors["platinum_sponsors"] = array_from_info(DONORS_SPONSOR_PLAT);
donors["gold_sponsors"] = array_from_info(DONORS_SPONSOR_GOLD);
donors["mini_sponsors"] = array_from_info(DONORS_SPONSOR_MINI);
donors["gold_donors"] = array_from_info(DONORS_GOLD);
donors["silver_donors"] = array_from_info(DONORS_SILVER);
donors["bronze_donors"] = array_from_info(DONORS_BRONZE);
return donors;
}
Dictionary Engine::get_license_info() const {
Dictionary licenses;
for (int i = 0; i < LICENSE_COUNT; i++) {
licenses[LICENSE_NAMES[i]] = LICENSE_BODIES[i];
}
return licenses;
}
String Engine::get_license_text() const {
return String(GODOT_LICENSE_TEXT);
}
void Engine::add_singleton(const Singleton &p_singleton) {
singletons.push_back(p_singleton);
@ -223,7 +137,6 @@ Engine::Engine() {
singleton = this;
frames_drawn = 0;
ips = 60;
physics_jitter_fix = 0.5;
_frame_delay = 0;
_fps = 1;
_target_fps = 0;

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,10 +31,10 @@
#ifndef ENGINE_H
#define ENGINE_H
#include "core/list.h"
#include "core/os/main_loop.h"
#include "core/ustring.h"
#include "core/vector.h"
#include "list.h"
#include "os/main_loop.h"
#include "ustring.h"
#include "vector.h"
class Engine {
@ -57,7 +57,6 @@ private:
float _frame_step;
int ips;
float physics_jitter_fix;
float _fps;
int _target_fps;
float _time_scale;
@ -80,9 +79,6 @@ public:
virtual void set_iterations_per_second(int p_ips);
virtual int get_iterations_per_second() const;
void set_physics_jitter_fix(float p_threshold);
float get_physics_jitter_fix() const;
virtual void set_target_fps(int p_fps);
virtual float get_target_fps() const;
@ -118,14 +114,8 @@ public:
#endif
Dictionary get_version_info() const;
Dictionary get_author_info() const;
Array get_copyright_info() const;
Dictionary get_donor_info() const;
Dictionary get_license_info() const;
String get_license_text() const;
Engine();
virtual ~Engine() {}
};
#endif // ENGINE_H

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -39,7 +39,7 @@
*/
enum Error {
OK, // (0)
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
@ -69,12 +69,12 @@ enum Error {
ERR_CONNECTION_ERROR,
ERR_CANT_ACQUIRE_RESOURCE,
ERR_CANT_FORK,
ERR_INVALID_DATA, ///< Data passed is invalid (30)
ERR_INVALID_DATA, ///< Data passed is invalid (30)
ERR_INVALID_PARAMETER, ///< Parameter passed is invalid
ERR_ALREADY_EXISTS, ///< When adding, item already exists
ERR_DOES_NOT_EXIST, ///< When retrieving/erasing, if item does not exist
ERR_DOES_NOT_EXIST, ///< When retrieving/erasing, it item does not exist
ERR_DATABASE_CANT_READ, ///< database is full
ERR_DATABASE_CANT_WRITE, ///< database is full (35)
ERR_DATABASE_CANT_WRITE, ///< database is full (35)
ERR_COMPILATION_FAILED,
ERR_METHOD_NOT_FOUND,
ERR_LINK_FAILED,

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -30,7 +30,7 @@
#include "error_macros.h"
#include "core/io/logger.h"
#include "io/logger.h"
#include "os/os.h"
bool _err_error_exists = false;

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,7 +31,7 @@
#ifndef ERROR_MACROS_H
#define ERROR_MACROS_H
#include "core/typedefs.h"
#include "typedefs.h"
/**
* Error macros. Unlike exceptions and asserts, these macros try to maintain consistency and stability
* inside the code. It is recommended to always return processable data, so in case of an error, the
@ -154,20 +154,6 @@ extern bool _err_error_exists;
_err_error_exists = false; \
} while (0); // (*)
/** An index has failed if 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
*/
#define ERR_FAIL_UNSIGNED_INDEX_V(m_index, m_size, m_retval) \
do { \
if (unlikely((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); // (*)
/** 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.
*/
@ -310,16 +296,6 @@ extern bool _err_error_exists;
_err_error_exists = false; \
}
#define ERR_PRINT_ONCE(m_string) \
{ \
static bool first_print = true; \
if (first_print) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string); \
_err_error_exists = false; \
first_print = false; \
} \
}
/** Print a warning string.
*/
@ -335,24 +311,4 @@ extern bool _err_error_exists;
_err_error_exists = false; \
}
#define WARN_PRINT_ONCE(m_string) \
{ \
static bool first_print = true; \
if (first_print) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string, ERR_HANDLER_WARNING); \
_err_error_exists = false; \
first_print = false; \
} \
}
#define WARN_DEPRECATED \
{ \
static volatile bool warning_shown = false; \
if (!warning_shown) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future", ERR_HANDLER_WARNING); \
_err_error_exists = false; \
warning_shown = true; \
} \
}
#endif

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -69,6 +69,7 @@ void FuncRef::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_function", "name"), &FuncRef::set_function);
}
FuncRef::FuncRef() :
id(0) {
FuncRef::FuncRef() {
id = 0;
}

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,7 +31,7 @@
#ifndef FUNC_REF_H
#define FUNC_REF_H
#include "core/reference.h"
#include "reference.h"
class FuncRef : public Reference {

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -30,10 +30,10 @@
#include "global_constants.h"
#include "core/object.h"
#include "core/os/input_event.h"
#include "core/os/keyboard.h"
#include "core/variant.h"
#include "object.h"
#include "os/input_event.h"
#include "os/keyboard.h"
#include "variant.h"
struct _GlobalConstant {
@ -89,7 +89,6 @@ VARIANT_ENUM_CAST(KeyList);
VARIANT_ENUM_CAST(KeyModifierMask);
VARIANT_ENUM_CAST(ButtonList);
VARIANT_ENUM_CAST(JoystickList);
VARIANT_ENUM_CAST(MidiMessageList);
void register_global_constants() {
@ -379,8 +378,6 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT(BUTTON_LEFT);
BIND_GLOBAL_ENUM_CONSTANT(BUTTON_RIGHT);
BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MIDDLE);
BIND_GLOBAL_ENUM_CONSTANT(BUTTON_XBUTTON1);
BIND_GLOBAL_ENUM_CONSTANT(BUTTON_XBUTTON2);
BIND_GLOBAL_ENUM_CONSTANT(BUTTON_WHEEL_UP);
BIND_GLOBAL_ENUM_CONSTANT(BUTTON_WHEEL_DOWN);
BIND_GLOBAL_ENUM_CONSTANT(BUTTON_WHEEL_LEFT);
@ -388,8 +385,6 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_LEFT);
BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_RIGHT);
BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_MIDDLE);
BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_XBUTTON1);
BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_XBUTTON2);
//joypads
BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_0);
@ -459,66 +454,49 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_L2);
BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_R2);
// midi
BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_OFF);
BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_ON);
BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_AFTERTOUCH);
BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_CONTROL_CHANGE);
BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_PROGRAM_CHANGE);
BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_CHANNEL_PRESSURE);
BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_PITCH_BEND);
// error list
BIND_GLOBAL_ENUM_CONSTANT(OK); // (0)
BIND_GLOBAL_ENUM_CONSTANT(FAILED);
BIND_GLOBAL_ENUM_CONSTANT(ERR_UNAVAILABLE);
BIND_GLOBAL_ENUM_CONSTANT(ERR_UNCONFIGURED);
BIND_GLOBAL_ENUM_CONSTANT(ERR_UNAUTHORIZED);
BIND_GLOBAL_ENUM_CONSTANT(ERR_PARAMETER_RANGE_ERROR); // (5)
BIND_GLOBAL_ENUM_CONSTANT(ERR_OUT_OF_MEMORY);
BIND_GLOBAL_ENUM_CONSTANT(OK);
BIND_GLOBAL_ENUM_CONSTANT(FAILED); ///< Generic fail error
BIND_GLOBAL_ENUM_CONSTANT(ERR_UNAVAILABLE); ///< What is requested is unsupported/unavailable
BIND_GLOBAL_ENUM_CONSTANT(ERR_UNCONFIGURED); ///< The object being used hasn't been properly set up yet
BIND_GLOBAL_ENUM_CONSTANT(ERR_UNAUTHORIZED); ///< Missing credentials for requested resource
BIND_GLOBAL_ENUM_CONSTANT(ERR_PARAMETER_RANGE_ERROR); ///< Parameter given out of range
BIND_GLOBAL_ENUM_CONSTANT(ERR_OUT_OF_MEMORY); ///< Out of memory
BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_NOT_FOUND);
BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_BAD_DRIVE);
BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_BAD_PATH);
BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_NO_PERMISSION); // (10)
BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_NO_PERMISSION);
BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_ALREADY_IN_USE);
BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_CANT_OPEN);
BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_CANT_WRITE);
BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_CANT_READ);
BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_UNRECOGNIZED); // (15)
BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_UNRECOGNIZED);
BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_CORRUPT);
BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_MISSING_DEPENDENCIES);
BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_EOF);
BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_OPEN);
BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_CREATE); // (20)
BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_OPEN); ///< Can't open a resource/socket/file
BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_CREATE);
BIND_GLOBAL_ENUM_CONSTANT(ERR_PARSE_ERROR);
BIND_GLOBAL_ENUM_CONSTANT(ERR_QUERY_FAILED);
BIND_GLOBAL_ENUM_CONSTANT(ERR_ALREADY_IN_USE);
BIND_GLOBAL_ENUM_CONSTANT(ERR_LOCKED);
BIND_GLOBAL_ENUM_CONSTANT(ERR_LOCKED); ///< resource is locked
BIND_GLOBAL_ENUM_CONSTANT(ERR_TIMEOUT);
BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_CONNECT); // (25)
BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_RESOLVE);
BIND_GLOBAL_ENUM_CONSTANT(ERR_CONNECTION_ERROR);
BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_ACQUIRE_RESOURCE);
BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_FORK);
BIND_GLOBAL_ENUM_CONSTANT(ERR_INVALID_DATA); // (30)
BIND_GLOBAL_ENUM_CONSTANT(ERR_INVALID_PARAMETER);
BIND_GLOBAL_ENUM_CONSTANT(ERR_ALREADY_EXISTS);
BIND_GLOBAL_ENUM_CONSTANT(ERR_DOES_NOT_EXIST);
BIND_GLOBAL_ENUM_CONSTANT(ERR_DATABASE_CANT_READ);
BIND_GLOBAL_ENUM_CONSTANT(ERR_DATABASE_CANT_WRITE); // (35)
BIND_GLOBAL_ENUM_CONSTANT(ERR_INVALID_DATA); ///< Data passed is invalid
BIND_GLOBAL_ENUM_CONSTANT(ERR_INVALID_PARAMETER); ///< Parameter passed is invalid
BIND_GLOBAL_ENUM_CONSTANT(ERR_ALREADY_EXISTS); ///< When adding ), item already exists
BIND_GLOBAL_ENUM_CONSTANT(ERR_DOES_NOT_EXIST); ///< When retrieving/erasing ), it item does not exist
BIND_GLOBAL_ENUM_CONSTANT(ERR_DATABASE_CANT_READ); ///< database is full
BIND_GLOBAL_ENUM_CONSTANT(ERR_DATABASE_CANT_WRITE); ///< database is full
BIND_GLOBAL_ENUM_CONSTANT(ERR_COMPILATION_FAILED);
BIND_GLOBAL_ENUM_CONSTANT(ERR_METHOD_NOT_FOUND);
BIND_GLOBAL_ENUM_CONSTANT(ERR_LINK_FAILED);
BIND_GLOBAL_ENUM_CONSTANT(ERR_SCRIPT_FAILED);
BIND_GLOBAL_ENUM_CONSTANT(ERR_CYCLIC_LINK); // (40)
BIND_GLOBAL_ENUM_CONSTANT(ERR_INVALID_DECLARATION);
BIND_GLOBAL_ENUM_CONSTANT(ERR_DUPLICATE_SYMBOL);
BIND_GLOBAL_ENUM_CONSTANT(ERR_PARSE_ERROR);
BIND_GLOBAL_ENUM_CONSTANT(ERR_CYCLIC_LINK);
BIND_GLOBAL_ENUM_CONSTANT(ERR_BUSY);
BIND_GLOBAL_ENUM_CONSTANT(ERR_SKIP); // (45)
BIND_GLOBAL_ENUM_CONSTANT(ERR_HELP);
BIND_GLOBAL_ENUM_CONSTANT(ERR_BUG);
BIND_GLOBAL_ENUM_CONSTANT(ERR_PRINTER_ON_FIRE);
BIND_GLOBAL_ENUM_CONSTANT(ERR_HELP); ///< user requested help!!
BIND_GLOBAL_ENUM_CONSTANT(ERR_BUG); ///< a bug in the software certainly happened ), due to a double check failing or unexpected behavior.
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_NONE);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_RANGE);
@ -540,7 +518,6 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_GLOBAL_DIR);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_RESOURCE_TYPE);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_MULTILINE_TEXT);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_PLACEHOLDER_TEXT);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_COLOR_NO_ALPHA);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_IMAGE_COMPRESS_LOSSY);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS);
@ -555,9 +532,8 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_INTERNATIONALIZED);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_GROUP);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_CATEGORY);
//deprecated, replaced by ClassDB function to check default value
//BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_STORE_IF_NONZERO);
//BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_STORE_IF_NONONE);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_STORE_IF_NONZERO);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_STORE_IF_NONONE);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_NO_INSTANCE_STATE);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_RESTART_IF_CHANGED);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_SCRIPT_VARIABLE);

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,7 +31,7 @@
#ifndef GLOBAL_CONSTANTS_H
#define GLOBAL_CONSTANTS_H
#include "core/string_name.h"
#include "string_db.h"
class GlobalConstants {
public:

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,12 +31,12 @@
#ifndef HASH_MAP_H
#define HASH_MAP_H
#include "core/error_macros.h"
#include "core/hashfuncs.h"
#include "core/list.h"
#include "core/math/math_funcs.h"
#include "core/os/memory.h"
#include "core/ustring.h"
#include "error_macros.h"
#include "hashfuncs.h"
#include "list.h"
#include "math_funcs.h"
#include "os/memory.h"
#include "ustring.h"
/**
* @class HashMap
@ -150,7 +150,7 @@ private:
if (new_hash_table_power == -1)
return;
Element **new_hash_table = memnew_arr(Element *, ((uint64_t)1 << new_hash_table_power));
Element **new_hash_table = memnew_arr(Element *, (1 << new_hash_table_power));
if (!new_hash_table) {
ERR_PRINT("Out of Memory");
@ -230,7 +230,7 @@ private:
if (!p_t.hash_table || p_t.hash_table_power == 0)
return; /* not copying from empty table */
hash_table = memnew_arr(Element *, (uint64_t)1 << p_t.hash_table_power);
hash_table = memnew_arr(Element *, 1 << p_t.hash_table_power);
hash_table_power = p_t.hash_table_power;
elements = p_t.elements;

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,12 +31,10 @@
#ifndef HASHFUNCS_H
#define HASHFUNCS_H
#include "core/math/math_defs.h"
#include "core/math/math_funcs.h"
#include "core/node_path.h"
#include "core/string_name.h"
#include "core/typedefs.h"
#include "core/ustring.h"
#include "math_defs.h"
#include "math_funcs.h"
#include "typedefs.h"
#include "ustring.h"
/**
* Hashing functions
@ -133,7 +131,6 @@ static inline uint64_t make_uint64_t(T p_in) {
}
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); }
@ -148,10 +145,6 @@ struct HashMapHasherDefault {
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 StringName &p_string_name) { return p_string_name.hash(); }
static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); }
//static _FORCE_INLINE_ uint32_t hash(const void* p_ptr) { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); }
};

7
core/helper/SCsub Normal file
View File

@ -0,0 +1,7 @@
#!/usr/bin/env python
Import('env')
env.add_source_files(env.core_sources, "*.cpp")
Export('env')

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -30,7 +30,7 @@
#ifdef TOOLS_ENABLED
#include "math_fieldwise.h"
#include "core/helper/math_fieldwise.h"
#define SETUP_TYPE(m_type) \
m_type source = p_source; \

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */

View File

@ -0,0 +1,46 @@
/*************************************************************************/
/* value_evaluator.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 VALUE_EVALUATOR_H
#define VALUE_EVALUATOR_H
#include "core/object.h"
class ValueEvaluator : public Object {
GDCLASS(ValueEvaluator, Object);
public:
virtual double eval(const String &p_text) {
return p_text.to_double();
}
};
#endif // VALUE_EVALUATOR_H

File diff suppressed because it is too large Load Diff

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,10 +31,10 @@
#ifndef IMAGE_H
#define IMAGE_H
#include "core/color.h"
#include "core/math/rect2.h"
#include "core/pool_vector.h"
#include "core/resource.h"
#include "color.h"
#include "dvector.h"
#include "math_2d.h"
#include "resource.h"
/**
* @author Juan Linietsky <reduzio@gmail.com>
@ -47,19 +47,18 @@
class Image;
typedef Error (*SavePNGFunc)(const String &p_path, const Ref<Image> &p_img);
typedef Ref<Image> (*ImageMemLoadFunc)(const uint8_t *p_png, int p_size);
class Image : public Resource {
GDCLASS(Image, Resource);
public:
static SavePNGFunc save_png_func;
enum {
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
@ -108,26 +107,21 @@ public:
INTERPOLATE_NEAREST,
INTERPOLATE_BILINEAR,
INTERPOLATE_CUBIC,
INTERPOLATE_TRILINEAR,
/* INTERPOLATE_TRICUBIC, */
/* INTERPOLATE GAUSS */
};
enum CompressSource {
COMPRESS_SOURCE_GENERIC,
COMPRESS_SOURCE_SRGB,
COMPRESS_SOURCE_NORMAL,
COMPRESS_SOURCE_LAYERED,
COMPRESS_SOURCE_NORMAL
};
//some functions provided by something else
static ImageMemLoadFunc _png_mem_loader_func;
static ImageMemLoadFunc _jpg_mem_loader_func;
static ImageMemLoadFunc _webp_mem_loader_func;
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 *, float, CompressSource p_source);
static void (*_image_compress_bptc_func)(Image *, float p_lossy_quality, CompressSource p_source);
static void (*_image_compress_bc_func)(Image *, CompressSource p_source);
static void (*_image_compress_pvrtc2_func)(Image *);
static void (*_image_compress_pvrtc4_func)(Image *);
static void (*_image_compress_etc1_func)(Image *, float);
@ -135,7 +129,6 @@ public:
static void (*_image_decompress_pvrtc)(Image *);
static void (*_image_decompress_bc)(Image *);
static void (*_image_decompress_bptc)(Image *);
static void (*_image_decompress_etc1)(Image *);
static void (*_image_decompress_etc2)(Image *);
@ -182,17 +175,6 @@ private:
void _set_data(const Dictionary &p_data);
Dictionary _get_data() const;
Error _load_from_buffer(const PoolVector<uint8_t> &p_array, ImageMemLoadFunc p_loader);
static void average_4_uint8(uint8_t &p_out, const uint8_t &p_a, const uint8_t &p_b, const uint8_t &p_c, const uint8_t &p_d);
static void average_4_float(float &p_out, const float &p_a, const float &p_b, const float &p_c, const float &p_d);
static void average_4_half(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
static void average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint32_t &p_b, const uint32_t &p_c, const uint32_t &p_d);
static void renormalize_uint8(uint8_t *p_rgb);
static void renormalize_float(float *p_rgb);
static void renormalize_half(uint16_t *p_rgb);
static void renormalize_rgbe9995(uint32_t *p_rgb);
public:
int get_width() const; ///< Get image width
int get_height() const; ///< Get image height
@ -223,7 +205,6 @@ public:
void resize(int p_width, int p_height, Interpolation p_interpolation = INTERPOLATE_BILINEAR);
void shrink_x2();
void expand_x2_hq2x();
bool is_size_po2() const;
/**
* Crop the image to a specific size, if larger, then the image is filled by black
*/
@ -236,10 +217,9 @@ public:
/**
* Generate a mipmap to an image (creates an image 1/4 the size, with averaging of 4->1)
*/
Error generate_mipmaps(bool p_renormalize = false);
Error generate_mipmaps();
void clear_mipmaps();
void normalize(); //for normal maps
/**
* Create a new image of a given size and format. Current image will be lost
@ -285,9 +265,8 @@ public:
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, bool p_mipmaps = false);
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);
static int get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap);
enum CompressMode {
COMPRESS_S3TC,
@ -295,7 +274,6 @@ public:
COMPRESS_PVRTC4,
COMPRESS_ETC,
COMPRESS_ETC2,
COMPRESS_BPTC
};
Error compress(CompressMode p_mode = COMPRESS_S3TC, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7);
@ -306,8 +284,6 @@ public:
void premultiply_alpha();
void srgb_to_linear();
void normalmap_to_xy();
Ref<Image> rgbe_to_srgb();
void bumpmap_to_normalmap(float bump_scale = 1.0);
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);
@ -318,13 +294,11 @@ public:
Rect2 get_used_rect() const;
Ref<Image> get_rect(const Rect2 &p_area) const;
static void set_compress_bc_func(void (*p_compress_func)(Image *, float, CompressSource));
static void set_compress_bptc_func(void (*p_compress_func)(Image *, float, CompressSource));
static void set_compress_bc_func(void (*p_compress_func)(Image *, CompressSource));
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);
Error load_webp_from_buffer(const PoolVector<uint8_t> &p_array);
Image(const uint8_t *p_mem_png_jpg, int p_len = -1);
Image(const char **p_xpm);
@ -345,11 +319,8 @@ public:
};
DetectChannels get_detected_channels();
void optimize_channels();
Color get_pixelv(const Point2 &p_src) const;
Color get_pixel(int p_x, int p_y) const;
void set_pixelv(const Point2 &p_dest, const Color &p_color);
void set_pixel(int p_x, int p_y, const Color &p_color);
void copy_internals_from(const Ref<Image> &p_image) {

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -30,37 +30,32 @@
#include "input_map.h"
#include "core/os/keyboard.h"
#include "core/project_settings.h"
#include "os/keyboard.h"
#include "project_settings.h"
InputMap *InputMap::singleton = NULL;
int InputMap::ALL_DEVICES = -1;
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", "deadzone"), &InputMap::add_action, DEFVAL(0.5f));
ClassDB::bind_method(D_METHOD("add_action", "action"), &InputMap::add_action);
ClassDB::bind_method(D_METHOD("erase_action", "action"), &InputMap::erase_action);
ClassDB::bind_method(D_METHOD("action_set_deadzone", "action", "deadzone"), &InputMap::action_set_deadzone);
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("action_erase_events", "action"), &InputMap::action_erase_events);
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, float p_deadzone) {
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_map[p_action].deadzone = p_deadzone;
last_id++;
}
@ -99,21 +94,19 @@ List<StringName> InputMap::get_actions() const {
return actions;
}
List<Ref<InputEvent> >::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength) const {
List<Ref<InputEvent> >::Element *InputMap::_find_event(List<Ref<InputEvent> > &p_list, const Ref<InputEvent> &p_event, bool p_action_test) const {
for (List<Ref<InputEvent> >::Element *E = p_action.inputs.front(); E; E = E->next()) {
for (List<Ref<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;
int device = e->get_device();
if (device == ALL_DEVICES || device == p_event->get_device()) {
if (e->action_match(p_event, p_pressed, p_strength, p_action.deadzone)) {
return E;
}
}
if (e->get_device() != p_event->get_device())
continue;
if (e->action_match(p_event))
return E;
}
return NULL;
@ -124,18 +117,11 @@ bool InputMap::has_action(const StringName &p_action) const {
return input_map.has(p_action);
}
void InputMap::action_set_deadzone(const StringName &p_action, float p_deadzone) {
ERR_FAIL_COND(!input_map.has(p_action));
input_map[p_action].deadzone = p_deadzone;
}
void InputMap::action_add_event(const StringName &p_action, const Ref<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], p_event))
if (_find_event(input_map[p_action].inputs, p_event))
return; //already gots
input_map[p_action].inputs.push_back(p_event);
@ -144,25 +130,18 @@ void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent
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], p_event) != NULL);
return (_find_event(input_map[p_action].inputs, p_event) != NULL);
}
void InputMap::action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(!input_map.has(p_action));
List<Ref<InputEvent> >::Element *E = _find_event(input_map[p_action], p_event);
List<Ref<InputEvent> >::Element *E = _find_event(input_map[p_action].inputs, p_event);
if (E)
input_map[p_action].inputs.erase(E);
}
void InputMap::action_erase_events(const StringName &p_action) {
ERR_FAIL_COND(!input_map.has(p_action));
input_map[p_action].inputs.clear();
}
Array InputMap::_get_action_list(const StringName &p_action) {
Array ret;
@ -187,37 +166,19 @@ const List<Ref<InputEvent> > *InputMap::get_action_list(const StringName &p_acti
}
bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action) const {
return event_get_action_status(p_event, p_action);
}
bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed, float *p_strength) 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);
}
Ref<InputEventAction> input_event_action = p_event;
if (input_event_action.is_valid()) {
if (p_pressed != NULL)
*p_pressed = input_event_action->is_pressed();
if (p_strength != NULL)
*p_strength = (*p_pressed) ? 1.0f : 0.0f;
return input_event_action->get_action() == p_action;
Ref<InputEventAction> iea = p_event;
if (iea.is_valid()) {
return iea->get_action() == p_action;
}
bool pressed;
float strength;
List<Ref<InputEvent> >::Element *event = _find_event(E->get(), p_event, &pressed, &strength);
if (event != NULL) {
if (p_pressed != NULL)
*p_pressed = pressed;
if (p_strength != NULL)
*p_strength = strength;
return true;
} else {
return false;
}
return _find_event(E->get().inputs, p_event, true) != NULL;
}
const Map<StringName, InputMap::Action> &InputMap::get_action_map() const {
@ -239,16 +200,16 @@ void InputMap::load_from_globals() {
String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length());
Dictionary action = ProjectSettings::get_singleton()->get(pi.name);
float deadzone = action.has("deadzone") ? (float)action["deadzone"] : 0.5f;
Array events = action["events"];
add_action(name);
add_action(name, deadzone);
for (int i = 0; i < events.size(); i++) {
Ref<InputEvent> event = events[i];
if (event.is_null())
Array va = ProjectSettings::get_singleton()->get(pi.name);
for (int i = 0; i < va.size(); i++) {
Ref<InputEvent> ie = va[i];
if (ie.is_null())
continue;
action_add_event(name, event);
action_add_event(name, ie);
}
}
}
@ -321,16 +282,6 @@ void InputMap::load_default() {
key->set_scancode(KEY_PAGEDOWN);
action_add_event("ui_page_down", key);
add_action("ui_home");
key.instance();
key->set_scancode(KEY_HOME);
action_add_event("ui_home", key);
add_action("ui_end");
key.instance();
key->set_scancode(KEY_END);
action_add_event("ui_end", key);
//set("display/window/handheld/orientation", "landscape");
}

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,22 +31,16 @@
#ifndef INPUT_MAP_H
#define INPUT_MAP_H
#include "core/object.h"
#include "core/os/input_event.h"
#include "object.h"
#include "os/input_event.h"
class InputMap : public Object {
GDCLASS(InputMap, Object);
public:
/**
* A special value used to signify that a given Action can be triggered by any device
*/
static int ALL_DEVICES;
struct Action {
int id;
float deadzone;
List<Ref<InputEvent> > inputs;
};
@ -55,7 +49,7 @@ private:
mutable Map<StringName, Action> input_map;
List<Ref<InputEvent> >::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed = NULL, float *p_strength = NULL) const;
List<Ref<InputEvent> >::Element *_find_event(List<Ref<InputEvent> > &p_list, const Ref<InputEvent> &p_event, bool p_action_test = false) const;
Array _get_action_list(const StringName &p_action);
Array _get_actions();
@ -68,18 +62,15 @@ public:
bool has_action(const StringName &p_action) const;
List<StringName> get_actions() const;
void add_action(const StringName &p_action, float p_deadzone = 0.5);
void add_action(const StringName &p_action);
void erase_action(const StringName &p_action);
void action_set_deadzone(const StringName &p_action, float p_deadzone);
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_erase_events(const StringName &p_action);
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;
bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed = NULL, float *p_strength = NULL) const;
const Map<StringName, Action> &get_action_map() const;
void load_from_globals();

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */

View File

@ -3,3 +3,6 @@
Import('env')
env.add_source_files(env.core_sources, "*.cpp")
Export('env')

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -29,10 +29,9 @@
/*************************************************************************/
#include "compression.h"
#include "core/io/zip_io.h"
#include "core/os/copymem.h"
#include "core/project_settings.h"
#include "os/copymem.h"
#include "project_settings.h"
#include "zip_io.h"
#include "thirdparty/misc/fastlz.h"
@ -81,10 +80,10 @@ int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,
} break;
case MODE_ZSTD: {
ZSTD_CCtx *cctx = ZSTD_createCCtx();
ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, zstd_level);
ZSTD_CCtx_setParameter(cctx, ZSTD_p_compressionLevel, zstd_level);
if (zstd_long_distance_matching) {
ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, 1);
ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, zstd_window_log_size);
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);
@ -175,9 +174,7 @@ int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p
} break;
case MODE_ZSTD: {
ZSTD_DCtx *dctx = ZSTD_createDCtx();
if (zstd_long_distance_matching) {
ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, zstd_window_log_size);
}
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;
@ -191,4 +188,4 @@ 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; // ZSTD_WINDOWLOG_LIMIT_DEFAULT
int Compression::zstd_window_log_size = 27;

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,7 +31,7 @@
#ifndef COMPRESSION_H
#define COMPRESSION_H
#include "core/typedefs.h"
#include "typedefs.h"
class Compression {

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -29,10 +29,9 @@
/*************************************************************************/
#include "config_file.h"
#include "core/os/file_access.h"
#include "core/os/keyboard.h"
#include "core/variant_parser.h"
#include "os/file_access.h"
#include "os/keyboard.h"
#include "variant_parser.h"
PoolStringArray ConfigFile::_get_sections() const {

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -32,7 +32,7 @@
#define CONFIG_FILE_H
#include "core/ordered_hash_map.h"
#include "core/reference.h"
#include "reference.h"
class ConfigFile : public Reference {

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -30,7 +30,9 @@
#include "file_access_buffered.h"
#include "core/error_macros.h"
#include <string.h>
#include "error_macros.h"
Error FileAccessBuffered::set_error(Error p_error) const {

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,9 +31,10 @@
#ifndef FILE_ACCESS_BUFFERED_H
#define FILE_ACCESS_BUFFERED_H
#include "core/os/file_access.h"
#include "core/pool_vector.h"
#include "core/ustring.h"
#include "os/file_access.h"
#include "dvector.h"
#include "ustring.h"
class FileAccessBuffered : public FileAccess {

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -54,7 +54,7 @@ class FileAccessBufferedFA : public FileAccessBuffered {
cache.offset = p_offset;
cache.buffer.resize(p_size);
// on PoolVector
// on dvector
//PoolVector<uint8_t>::Write write = cache.buffer.write();
//f.get_buffer(write.ptrw(), p_size);

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -29,9 +29,7 @@
/*************************************************************************/
#include "file_access_compressed.h"
#include "core/print_string.h"
#include "print_string.h"
void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_mode, int p_block_size) {
magic = p_magic.ascii().get_data();
@ -208,8 +206,7 @@ void FileAccessCompressed::seek(size_t p_position) {
if (p_position == read_total) {
at_end = true;
} else {
at_end = false;
read_eof = false;
int block_idx = p_position / block_size;
if (block_idx != read_block) {
@ -294,6 +291,7 @@ uint8_t FileAccessCompressed::get_8() const {
} else {
read_block--;
at_end = true;
ret = 0;
}
}
@ -374,23 +372,24 @@ uint64_t FileAccessCompressed::_get_modified_time(const String &p_file) {
return 0;
}
FileAccessCompressed::FileAccessCompressed() :
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_ptr(NULL),
read_block(0),
read_block_count(0),
read_block_size(0),
read_pos(0),
read_total(0),
magic("GCMP"),
f(NULL) {
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;
}
FileAccessCompressed::~FileAccessCompressed() {

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,8 +31,8 @@
#ifndef FILE_ACCESS_COMPRESSED_H
#define FILE_ACCESS_COMPRESSED_H
#include "core/io/compression.h"
#include "core/os/file_access.h"
#include "io/compression.h"
#include "os/file_access.h"
class FileAccessCompressed : public FileAccess {

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -30,9 +30,9 @@
#include "file_access_encrypted.h"
#include "core/os/copymem.h"
#include "core/print_string.h"
#include "core/variant.h"
#include "os/copymem.h"
#include "print_string.h"
#include "thirdparty/misc/aes256.h"
#include "thirdparty/misc/md5.h"
@ -43,6 +43,7 @@
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);
@ -88,7 +89,7 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8
for (size_t i = 0; i < ds; i += 16) {
aes256_decrypt_ecb(&ctx, &data.write[i]);
aes256_decrypt_ecb(&ctx, &data[i]);
}
aes256_done(&ctx);
@ -116,7 +117,7 @@ Error FileAccessEncrypted::open_and_parse_password(FileAccess *p_base, const Str
key.resize(32);
for (int i = 0; i < 32; i++) {
key.write[i] = cs[i];
key[i] = cs[i];
}
return open_and_parse(p_base, key, p_mode);
@ -147,7 +148,7 @@ void FileAccessEncrypted::close() {
compressed.resize(len);
zeromem(compressed.ptrw(), len);
for (int i = 0; i < data.size(); i++) {
compressed.write[i] = data[i];
compressed[i] = data[i];
}
aes256_context ctx;
@ -155,7 +156,7 @@ void FileAccessEncrypted::close() {
for (size_t i = 0; i < len; i += 16) {
aes256_encrypt_ecb(&ctx, &compressed.write[i]);
aes256_encrypt_ecb(&ctx, &compressed[i]);
}
aes256_done(&ctx);
@ -262,7 +263,7 @@ void FileAccessEncrypted::store_buffer(const uint8_t *p_src, int p_length) {
data.resize(pos + p_length);
for (int i = 0; i < p_length; i++) {
data.write[pos + i] = p_src[i];
data[pos + i] = p_src[i];
}
pos += p_length;
}
@ -279,7 +280,7 @@ void FileAccessEncrypted::store_8(uint8_t p_dest) {
ERR_FAIL_COND(!writing);
if (pos < data.size()) {
data.write[pos] = p_dest;
data[pos] = p_dest;
pos++;
} else if (pos == data.size()) {
data.push_back(p_dest);

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,7 +31,7 @@
#ifndef FILE_ACCESS_ENCRYPTED_H
#define FILE_ACCESS_ENCRYPTED_H
#include "core/os/file_access.h"
#include "os/file_access.h"
class FileAccessEncrypted : public FileAccess {
public:

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -30,10 +30,10 @@
#include "file_access_memory.h"
#include "core/map.h"
#include "core/os/copymem.h"
#include "core/os/dir_access.h"
#include "core/project_settings.h"
#include "map.h"
#include "os/copymem.h"
#include "os/dir_access.h"
#include "project_settings.h"
static Map<String, Vector<uint8_t> > *files = NULL;
@ -92,7 +92,7 @@ Error FileAccessMemory::_open(const String &p_path, int p_mode_flags) {
Map<String, Vector<uint8_t> >::Element *E = files->find(name);
ERR_FAIL_COND_V(!E, ERR_FILE_NOT_FOUND);
data = E->get().ptrw();
data = &(E->get()[0]);
length = E->get().size();
pos = 0;

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,7 +31,7 @@
#ifndef FILE_ACCESS_MEMORY_H
#define FILE_ACCESS_MEMORY_H
#include "core/os/file_access.h"
#include "os/file_access.h"
class FileAccessMemory : public FileAccess {

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -29,11 +29,10 @@
/*************************************************************************/
#include "file_access_network.h"
#include "core/io/ip.h"
#include "core/io/marshalls.h"
#include "core/os/os.h"
#include "core/project_settings.h"
#include "io/ip.h"
#include "marshalls.h"
#include "os/os.h"
#include "project_settings.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());
@ -94,6 +93,8 @@ void FileAccessNetworkClient::_thread_func() {
DEBUG_TIME("sem_unlock");
//DEBUG_PRINT("semwait returned "+itos(werr));
DEBUG_PRINT("MUTEX LOCK " + itos(lockcount));
DEBUG_PRINT("POPO");
DEBUG_PRINT("PEPE");
lock_mutex();
DEBUG_PRINT("MUTEX PASS");
@ -227,7 +228,7 @@ FileAccessNetworkClient::FileAccessNetworkClient() {
quit = false;
singleton = this;
last_id = 0;
client.instance();
client = Ref<StreamPeerTCP>(StreamPeerTCP::create_ref());
sem = Semaphore::create();
lockcount = 0;
}
@ -257,8 +258,8 @@ void FileAccessNetwork::_set_block(int p_offset, const Vector<uint8_t> &p_block)
}
buffer_mutex->lock();
pages.write[page].buffer = p_block;
pages.write[page].queued = false;
pages[page].buffer = p_block;
pages[page].queued = false;
buffer_mutex->unlock();
if (waiting_on_page == page) {
@ -388,7 +389,7 @@ void FileAccessNetwork::_queue_page(int p_page) const {
br.offset = size_t(p_page) * page_size;
br.size = page_size;
nc->block_requests.push_back(br);
pages.write[p_page].queued = true;
pages[p_page].queued = true;
nc->blockrequest_mutex->unlock();
DEBUG_PRINT("QUEUE PAGE POST");
nc->sem->post();
@ -432,12 +433,12 @@ int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const {
_queue_page(page + j);
}
buff = pages.write[page].buffer.ptrw();
buff = pages[page].buffer.ptrw();
//queue pages
buffer_mutex->unlock();
}
buff = pages.write[page].buffer.ptrw();
buff = pages[page].buffer.ptrw();
last_page_buff = buff;
last_page = page;
}
@ -500,9 +501,8 @@ uint64_t FileAccessNetwork::_get_modified_time(const String &p_file) {
void FileAccessNetwork::configure() {
GLOBAL_DEF("network/remote_fs/page_size", 65536);
ProjectSettings::get_singleton()->set_custom_property_info("network/remote_fs/page_size", PropertyInfo(Variant::INT, "network/remote_fs/page_size", PROPERTY_HINT_RANGE, "1,65536,1,or_greater")); //is used as denominator and can't be zero
GLOBAL_DEF("network/remote_fs/page_read_ahead", 4);
ProjectSettings::get_singleton()->set_custom_property_info("network/remote_fs/page_read_ahead", PropertyInfo(Variant::INT, "network/remote_fs/page_read_ahead", PROPERTY_HINT_RANGE, "0,8,1,or_greater"));
GLOBAL_DEF("network/remote_fs/max_pages", 20);
}
FileAccessNetwork::FileAccessNetwork() {
@ -520,6 +520,7 @@ FileAccessNetwork::FileAccessNetwork() {
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;

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,10 +31,10 @@
#ifndef FILE_ACCESS_NETWORK_H
#define FILE_ACCESS_NETWORK_H
#include "core/io/stream_peer_tcp.h"
#include "core/os/file_access.h"
#include "core/os/semaphore.h"
#include "core/os/thread.h"
#include "io/stream_peer_tcp.h"
#include "os/file_access.h"
#include "os/semaphore.h"
#include "os/thread.h"
class FileAccessNetwork;
@ -47,6 +47,8 @@ class FileAccessNetworkClient {
int size;
};
int ml;
List<BlockRequest> block_requests;
Semaphore *sem;
@ -98,6 +100,7 @@ class FileAccessNetwork : public FileAccess {
int page_size;
int read_ahead;
int max_pages;
mutable int waiting_on_page;
mutable int last_activity_val;

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -29,8 +29,7 @@
/*************************************************************************/
#include "file_access_pack.h"
#include "core/version.h"
#include "version.h"
#include <stdio.h>
@ -89,11 +88,7 @@ void PackedData::add_path(const String &pkg_path, const String &path, uint64_t o
}
}
}
String filename = path.get_file();
// Don't add as a file if the path points to a directory
if (!filename.empty()) {
cd->files.insert(filename);
}
cd->files.insert(path.get_file());
}
}
@ -169,11 +164,11 @@ bool PackedSourcePCK::try_open_pack(const String &p_path) {
uint32_t version = f->get_32();
uint32_t ver_major = f->get_32();
uint32_t ver_minor = f->get_32();
f->get_32(); // ver_rev
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));
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);
for (int i = 0; i < 16; i++) {
@ -272,7 +267,7 @@ int FileAccessPack::get_buffer(uint8_t *p_dst, int p_length) const {
if (eof)
return 0;
uint64_t to_read = p_length;
int64_t to_read = p_length;
if (to_read + pos > pf.size) {
eof = true;
to_read = int64_t(pf.size) - int64_t(pos);
@ -455,7 +450,7 @@ String DirAccessPack::get_current_dir() {
while (pd->parent) {
pd = pd->parent;
p = pd->name.plus_file(p);
p = pd->name + "/" + p;
}
return "res://" + p;
@ -463,15 +458,11 @@ String DirAccessPack::get_current_dir() {
bool DirAccessPack::file_exists(String p_file) {
p_file = fix_path(p_file);
return current->files.has(p_file);
}
bool DirAccessPack::dir_exists(String p_dir) {
p_dir = fix_path(p_dir);
return current->subdirs.has(p_dir);
}
@ -494,10 +485,6 @@ size_t DirAccessPack::get_space_left() {
return 0;
}
String DirAccessPack::get_filesystem_type() const {
return "PCK";
}
DirAccessPack::DirAccessPack() {
current = PackedData::get_singleton()->root;

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,11 +31,11 @@
#ifndef FILE_ACCESS_PACK_H
#define FILE_ACCESS_PACK_H
#include "core/list.h"
#include "core/map.h"
#include "core/os/dir_access.h"
#include "core/os/file_access.h"
#include "core/print_string.h"
#include "list.h"
#include "map.h"
#include "os/dir_access.h"
#include "os/file_access.h"
#include "print_string.h"
class PackSource;
@ -175,6 +175,7 @@ public:
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);
if (!E)
@ -221,8 +222,6 @@ public:
size_t get_space_left();
virtual String get_filesystem_type() const;
DirAccessPack();
~DirAccessPack();
};

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -43,31 +43,31 @@ static void *godot_open(void *data, const char *p_fname, int mode) {
if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
return NULL;
}
};
FileAccess *f = (FileAccess *)data;
f->open(p_fname, FileAccess::READ);
return f->is_open() ? data : NULL;
}
};
static uLong godot_read(void *data, void *fdata, void *buf, uLong 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) {
return 0;
}
};
static long godot_tell(voidpf opaque, voidpf stream) {
FileAccess *f = (FileAccess *)opaque;
return f->get_position();
}
};
static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
@ -84,36 +84,36 @@ static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
break;
default:
break;
}
};
f->seek(pos);
return 0;
}
};
static int godot_close(voidpf opaque, voidpf stream) {
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;
}
};
static voidpf godot_alloc(voidpf opaque, uInt items, uInt size) {
return memalloc(items * size);
}
};
static void godot_free(voidpf opaque, voidpf address) {
memfree(address);
}
};
} // extern "C"
}; // extern "C"
void ZipArchive::close_handle(unzFile p_file) const {
@ -122,7 +122,7 @@ void ZipArchive::close_handle(unzFile p_file) const {
unzCloseCurrentFile(p_file);
unzClose(p_file);
memdelete(f);
}
};
unzFile ZipArchive::get_file_handle(String p_file) const {
@ -155,10 +155,10 @@ unzFile ZipArchive::get_file_handle(String p_file) const {
unzClose(pkg);
ERR_FAIL_V(NULL);
}
};
return pkg;
}
};
bool ZipArchive::try_open_pack(const String &p_path) {
@ -168,10 +168,10 @@ bool ZipArchive::try_open_pack(const String &p_path) {
zlib_filefunc_def io;
FileAccess *fa = FileAccess::open(p_path, FileAccess::READ);
if (!fa)
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f)
return false;
io.opaque = fa;
io.opaque = f;
io.zopen_file = godot_open;
io.zread_file = godot_read;
io.zwrite_file = godot_write;
@ -215,36 +215,36 @@ bool ZipArchive::try_open_pack(const String &p_path) {
if ((i + 1) < gi.number_entry) {
unzGoToNextFile(zfile);
}
}
};
};
return true;
}
};
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) {
return memnew(FileAccessZip(p_path, *p_file));
}
};
ZipArchive *ZipArchive::get_singleton() {
if (instance == NULL) {
instance = memnew(ZipArchive);
}
};
return instance;
}
};
ZipArchive::ZipArchive() {
instance = this;
//fa_create_func = FileAccess::get_create_func();
}
};
ZipArchive::~ZipArchive() {
@ -253,10 +253,10 @@ ZipArchive::~ZipArchive() {
FileAccess *f = (FileAccess *)unzGetOpaque(packages[i].zfile);
unzClose(packages[i].zfile);
memdelete(f);
}
};
packages.clear();
}
};
Error FileAccessZip::_open(const String &p_path, int p_mode_flags) {
@ -272,7 +272,7 @@ Error FileAccessZip::_open(const String &p_path, int p_mode_flags) {
ERR_FAIL_COND_V(err != UNZ_OK, FAILED);
return OK;
}
};
void FileAccessZip::close() {
@ -283,50 +283,50 @@ void FileAccessZip::close() {
ERR_FAIL_COND(!arch);
arch->close_handle(zfile);
zfile = NULL;
}
};
bool FileAccessZip::is_open() const {
return zfile != NULL;
}
};
void FileAccessZip::seek(size_t p_position) {
ERR_FAIL_COND(!zfile);
unzSeekCurrentFile(zfile, p_position);
}
};
void FileAccessZip::seek_end(int64_t p_position) {
ERR_FAIL_COND(!zfile);
unzSeekCurrentFile(zfile, get_len() + p_position);
}
};
size_t FileAccessZip::get_position() const {
ERR_FAIL_COND_V(!zfile, 0);
return unztell(zfile);
}
};
size_t FileAccessZip::get_len() const {
ERR_FAIL_COND_V(!zfile, 0);
return file_info.uncompressed_size;
}
};
bool FileAccessZip::eof_reached() const {
ERR_FAIL_COND_V(!zfile, true);
return at_eof;
}
};
uint8_t FileAccessZip::get_8() const {
uint8_t ret = 0;
get_buffer(&ret, 1);
return ret;
}
};
int FileAccessZip::get_buffer(uint8_t *p_dst, int p_length) const {
@ -339,20 +339,20 @@ int FileAccessZip::get_buffer(uint8_t *p_dst, int p_length) const {
if (read < p_length)
at_eof = true;
return read;
}
};
Error FileAccessZip::get_error() const {
if (!zfile) {
return ERR_UNCONFIGURED;
}
};
if (eof_reached()) {
return ERR_FILE_EOF;
}
};
return OK;
}
};
void FileAccessZip::flush() {
@ -362,21 +362,22 @@ void FileAccessZip::flush() {
void FileAccessZip::store_8(uint8_t p_dest) {
ERR_FAIL();
}
};
bool FileAccessZip::file_exists(const String &p_name) {
return false;
}
};
FileAccessZip::FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file) :
zfile(NULL) {
FileAccessZip::FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file) {
zfile = NULL;
_open(p_path, FileAccess::READ);
}
};
FileAccessZip::~FileAccessZip() {
close();
}
};
#endif

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -34,7 +34,7 @@
#define FILE_ACCESS_ZIP_H
#include "core/io/file_access_pack.h"
#include "core/map.h"
#include "map.h"
#include "thirdparty/minizip/unzip.h"
@ -90,6 +90,8 @@ class FileAccessZip : public FileAccess {
mutable bool at_eof;
ZipArchive *archive;
public:
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -29,9 +29,7 @@
/*************************************************************************/
#include "http_client.h"
#include "core/io/stream_peer_ssl.h"
#include "core/version.h"
#include "io/stream_peer_ssl.h"
const char *HTTPClient::_methods[METHOD_MAX] = {
"GET",
@ -123,30 +121,16 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector
request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n";
}
bool add_clen = p_body.size() > 0;
bool add_uagent = true;
bool add_accept = true;
for (int i = 0; i < p_headers.size(); i++) {
request += p_headers[i] + "\r\n";
if (add_clen && p_headers[i].findn("Content-Length:") == 0) {
if (add_clen && p_headers[i].find("Content-Length:") == 0) {
add_clen = false;
}
if (add_uagent && p_headers[i].findn("User-Agent:") == 0) {
add_uagent = false;
}
if (add_accept && p_headers[i].findn("Accept:") == 0) {
add_accept = false;
}
}
if (add_clen) {
request += "Content-Length: " + itos(p_body.size()) + "\r\n";
// Should it add utf8 encoding?
}
if (add_uagent) {
request += "User-Agent: GodotEngine/" + String(VERSION_FULL_BUILD) + " (" + OS::get_singleton()->get_name() + ")\r\n";
}
if (add_accept) {
request += "Accept: */*\r\n";
}
request += "\r\n";
CharString cs = request.utf8();
@ -189,31 +173,17 @@ Error HTTPClient::request(Method p_method, const String &p_url, const Vector<Str
} else {
request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n";
}
bool add_uagent = true;
bool add_accept = true;
bool add_clen = p_body.length() > 0;
for (int i = 0; i < p_headers.size(); i++) {
request += p_headers[i] + "\r\n";
if (add_clen && p_headers[i].findn("Content-Length:") == 0) {
if (add_clen && p_headers[i].find("Content-Length:") == 0) {
add_clen = false;
}
if (add_uagent && p_headers[i].findn("User-Agent:") == 0) {
add_uagent = false;
}
if (add_accept && p_headers[i].findn("Accept:") == 0) {
add_accept = false;
}
}
if (add_clen) {
request += "Content-Length: " + itos(p_body.utf8().length()) + "\r\n";
// Should it add utf8 encoding?
}
if (add_uagent) {
request += "User-Agent: GodotEngine/" + String(VERSION_FULL_BUILD) + " (" + OS::get_singleton()->get_name() + ")\r\n";
}
if (add_accept) {
request += "Accept: */*\r\n";
}
request += "\r\n";
request += p_body;
@ -275,13 +245,10 @@ void HTTPClient::close() {
response_headers.clear();
response_str.clear();
body_size = -1;
body_size = 0;
body_left = 0;
chunk_left = 0;
chunk_trailer_part = 0;
read_until_eof = false;
response_num = 0;
handshaking = false;
}
Error HTTPClient::poll() {
@ -330,46 +297,16 @@ Error HTTPClient::poll() {
} break;
case StreamPeerTCP::STATUS_CONNECTED: {
if (ssl) {
Ref<StreamPeerSSL> ssl;
if (!handshaking) {
// Connect the StreamPeerSSL and start handshaking
ssl = Ref<StreamPeerSSL>(StreamPeerSSL::create());
ssl->set_blocking_handshake_enabled(false);
Error err = ssl->connect_to_stream(tcp_connection, ssl_verify_host, conn_host);
if (err != OK) {
close();
status = STATUS_SSL_HANDSHAKE_ERROR;
return ERR_CANT_CONNECT;
}
connection = ssl;
handshaking = true;
} else {
// We are already handshaking, which means we can use your already active SSL connection
ssl = static_cast<Ref<StreamPeerSSL> >(connection);
if (ssl.is_null()) {
close();
status = STATUS_SSL_HANDSHAKE_ERROR;
return ERR_CANT_CONNECT;
}
ssl->poll(); // Try to finish the handshake
}
if (ssl->get_status() == StreamPeerSSL::STATUS_CONNECTED) {
// Handshake has been successful
handshaking = false;
status = STATUS_CONNECTED;
return OK;
} else if (ssl->get_status() != StreamPeerSSL::STATUS_HANDSHAKING) {
// Handshake has failed
Ref<StreamPeerSSL> ssl = StreamPeerSSL::create();
Error err = ssl->connect_to_stream(tcp_connection, ssl_verify_host, ssl_verify_host ? conn_host : String());
if (err != OK) {
close();
status = STATUS_SSL_HANDSHAKE_ERROR;
return ERR_CANT_CONNECT;
}
// ... we will need to poll more for handshake to finish
} else {
status = STATUS_CONNECTED;
connection = ssl;
}
status = STATUS_CONNECTED;
return OK;
} break;
case StreamPeerTCP::STATUS_ERROR:
@ -381,20 +318,7 @@ Error HTTPClient::poll() {
} break;
}
} break;
case STATUS_BODY:
case STATUS_CONNECTED: {
// Check if we are still connected
if (ssl) {
Ref<StreamPeerSSL> tmp = connection;
tmp->poll();
if (tmp->get_status() != StreamPeerSSL::STATUS_CONNECTED) {
status = STATUS_CONNECTION_ERROR;
return ERR_CONNECTION_ERROR;
}
} else if (tcp_connection->get_status() != StreamPeerTCP::STATUS_CONNECTED) {
status = STATUS_CONNECTION_ERROR;
return ERR_CONNECTION_ERROR;
}
// Connection established, requests can now be made
return OK;
} break;
@ -424,21 +348,14 @@ Error HTTPClient::poll() {
String response;
response.parse_utf8((const char *)response_str.ptr());
Vector<String> responses = response.split("\n");
body_size = -1;
body_size = 0;
chunked = false;
body_left = 0;
chunk_left = 0;
chunk_trailer_part = false;
read_until_eof = false;
response_str.clear();
response_headers.clear();
response_num = RESPONSE_OK;
// Per the HTTP 1.1 spec, keep-alive is the default.
// Not following that specification breaks standard implemetations.
// Broken web servers should be fixed.
bool keep_alive = true;
for (int i = 0; i < responses.size(); i++) {
String header = responses[i].strip_edges();
@ -448,14 +365,13 @@ Error HTTPClient::poll() {
if (s.begins_with("content-length:")) {
body_size = s.substr(s.find(":") + 1, s.length()).strip_edges().to_int();
body_left = body_size;
}
} else if (s.begins_with("transfer-encoding:")) {
if (s.begins_with("transfer-encoding:")) {
String encoding = header.substr(header.find(":") + 1, header.length()).strip_edges();
if (encoding == "chunked") {
chunked = true;
}
} else if (s.begins_with("connection: close")) {
keep_alive = false;
}
if (i == 0 && responses[i].begins_with("HTTP")) {
@ -468,16 +384,11 @@ Error HTTPClient::poll() {
}
}
if (body_size != -1 || chunked) {
if (body_size == 0 && !chunked) {
status = STATUS_BODY;
} else if (!keep_alive) {
read_until_eof = true;
status = STATUS_BODY;
status = STATUS_CONNECTED; // Ready for new requests
} else {
status = STATUS_CONNECTED;
status = STATUS_BODY;
}
return OK;
}
@ -488,8 +399,7 @@ Error HTTPClient::poll() {
case STATUS_DISCONNECTED: {
return ERR_UNCONFIGURED;
} break;
case STATUS_CONNECTION_ERROR:
case STATUS_SSL_HANDSHAKE_ERROR: {
case STATUS_CONNECTION_ERROR: {
return ERR_CONNECTION_ERROR;
} break;
case STATUS_CANT_CONNECT: {
@ -512,37 +422,13 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
ERR_FAIL_COND_V(status != STATUS_BODY, PoolByteArray());
PoolByteArray ret;
Error err = OK;
if (chunked) {
while (true) {
if (chunk_trailer_part) {
// We need to consume the trailer part too or keep-alive will break
uint8_t b;
int rec = 0;
err = _get_http_data(&b, 1, rec);
if (rec == 0)
break;
chunk.push_back(b);
int cs = chunk.size();
if ((cs >= 2 && chunk[cs - 2] == '\r' && chunk[cs - 1] == '\n')) {
if (cs == 2) {
// Finally over
chunk_trailer_part = false;
status = STATUS_CONNECTED;
chunk.clear();
break;
} else {
// We do not process nor return the trailer data
chunk.clear();
}
}
} else if (chunk_left == 0) {
if (chunk_left == 0) {
// Reading length
uint8_t b;
int rec = 0;
@ -556,7 +442,7 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
if (chunk.size() > 32) {
ERR_PRINT("HTTP Invalid chunk hex len");
status = STATUS_CONNECTION_ERROR;
break;
return PoolByteArray();
}
if (chunk.size() > 2 && chunk[chunk.size() - 2] == '\r' && chunk[chunk.size() - 1] == '\n') {
@ -574,22 +460,22 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
else {
ERR_PRINT("HTTP Chunk len not in hex!!");
status = STATUS_CONNECTION_ERROR;
break;
return PoolByteArray();
}
len <<= 4;
len |= v;
if (len > (1 << 24)) {
ERR_PRINT("HTTP Chunk too big!! >16mb");
status = STATUS_CONNECTION_ERROR;
break;
return PoolByteArray();
}
}
if (len == 0) {
// End reached!
chunk_trailer_part = true;
status = STATUS_CONNECTED;
chunk.clear();
break;
return PoolByteArray();
}
chunk_left = len + 2;
@ -598,7 +484,7 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
} else {
int rec = 0;
err = _get_http_data(&chunk.write[chunk.size() - chunk_left], chunk_left, rec);
err = _get_http_data(&chunk[chunk.size() - chunk_left], chunk_left, rec);
if (rec == 0) {
break;
}
@ -609,13 +495,18 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
if (chunk[chunk.size() - 2] != '\r' || chunk[chunk.size() - 1] != '\n') {
ERR_PRINT("HTTP Invalid chunk terminator (not \\r\\n)");
status = STATUS_CONNECTION_ERROR;
break;
return PoolByteArray();
}
PoolByteArray ret;
ret.resize(chunk.size() - 2);
PoolByteArray::Write w = ret.write();
copymem(w.ptr(), chunk.ptr(), chunk.size() - 2);
{
PoolByteArray::Write w = ret.write();
copymem(w.ptr(), chunk.ptr(), chunk.size() - 2);
}
chunk.clear();
return ret;
}
break;
@ -624,7 +515,8 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
} else {
int to_read = !read_until_eof ? MIN(body_left, read_chunk_size) : read_chunk_size;
int to_read = MIN(body_left, read_chunk_size);
PoolByteArray ret;
ret.resize(to_read);
int _offset = 0;
while (to_read > 0) {
@ -633,25 +525,24 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
PoolByteArray::Write w = ret.write();
err = _get_http_data(w.ptr() + _offset, to_read, rec);
}
if (rec <= 0) { // Ended up reading less
ret.resize(_offset);
break;
} else {
_offset += rec;
if (rec > 0) {
body_left -= rec;
to_read -= rec;
if (!read_until_eof) {
body_left -= rec;
}
}
if (err != OK)
_offset += rec;
} else {
if (to_read > 0) // Ended up reading less
ret.resize(_offset);
break;
}
}
if (body_left == 0) {
status = STATUS_CONNECTED;
}
return ret;
}
if (err != OK) {
close();
if (err == ERR_FILE_EOF) {
status = STATUS_DISCONNECTED; // Server disconnected
@ -659,12 +550,12 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
status = STATUS_CONNECTION_ERROR;
}
} else if (body_left == 0 && !chunked && !read_until_eof) {
} else if (body_left == 0 && !chunked) {
status = STATUS_CONNECTED;
}
return ret;
return PoolByteArray();
}
HTTPClient::Status HTTPClient::get_status() const {
@ -686,24 +577,11 @@ Error HTTPClient::_get_http_data(uint8_t *p_buffer, int p_bytes, int &r_received
if (blocking) {
// We can't use StreamPeer.get_data, since when reaching EOF we will get an
// error without knowing how many bytes we received.
Error err = ERR_FILE_EOF;
int read = 0;
int left = p_bytes;
r_received = 0;
while (left > 0) {
err = connection->get_partial_data(p_buffer + r_received, left, read);
if (err == OK) {
r_received += read;
} else if (err == ERR_FILE_EOF) {
r_received += read;
return err;
} else {
return err;
}
left -= read;
}
Error err = connection->get_data(p_buffer, p_bytes);
if (err == OK)
r_received = p_bytes;
else
r_received = 0;
return err;
} else {
return connection->get_partial_data(p_buffer, p_bytes, r_received);
@ -717,20 +595,17 @@ void HTTPClient::set_read_chunk_size(int p_size) {
HTTPClient::HTTPClient() {
tcp_connection.instance();
tcp_connection = StreamPeerTCP::create_ref();
resolving = IP::RESOLVER_INVALID_ID;
status = STATUS_DISCONNECTED;
conn_port = -1;
body_size = -1;
body_size = 0;
chunked = false;
body_left = 0;
read_until_eof = false;
chunk_left = 0;
chunk_trailer_part = false;
response_num = 0;
ssl = false;
blocking = false;
handshaking = false;
read_chunk_size = 4096;
}
@ -743,27 +618,7 @@ String HTTPClient::query_string_from_dict(const Dictionary &p_dict) {
String query = "";
Array keys = p_dict.keys();
for (int i = 0; i < keys.size(); ++i) {
String encoded_key = String(keys[i]).http_escape();
Variant value = p_dict[keys[i]];
switch (value.get_type()) {
case Variant::ARRAY: {
// Repeat the key with every values
Array values = value;
for (int j = 0; j < values.size(); ++j) {
query += "&" + encoded_key + "=" + String(values[j]).http_escape();
}
break;
}
case Variant::NIL: {
// Add the key with no value
query += "&" + encoded_key;
break;
}
default: {
// Add the key-value pair
query += "&" + encoded_key + "=" + String(value).http_escape();
}
}
query += "&" + String(keys[i]).http_escape() + "=" + String(p_dict[keys[i]]).http_escape();
}
query.erase(0, 1);
return query;

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,10 +31,10 @@
#ifndef HTTP_CLIENT_H
#define HTTP_CLIENT_H
#include "core/io/ip.h"
#include "core/io/stream_peer.h"
#include "core/io/stream_peer_tcp.h"
#include "core/reference.h"
#include "io/ip.h"
#include "io/stream_peer.h"
#include "io/stream_peer_tcp.h"
#include "reference.h"
class HTTPClient : public Reference {
@ -165,17 +165,14 @@ private:
bool ssl;
bool ssl_verify_host;
bool blocking;
bool handshaking;
Vector<uint8_t> response_str;
bool chunked;
Vector<uint8_t> chunk;
int chunk_left;
bool chunk_trailer_part;
int body_size;
int body_left;
bool read_until_eof;
Ref<StreamPeerTCP> tcp_connection;
Ref<StreamPeer> connection;

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -30,15 +30,14 @@
#include "image_loader.h"
#include "core/print_string.h"
#include "print_string.h"
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()) {
if (E->get().nocasecmp_to(p_extension) == 0)
if (E->get().nocasecmp_to(p_extension.get_extension()) == 0)
return true;
}
@ -60,7 +59,7 @@ Error ImageLoader::load_image(String p_file, Ref<Image> p_image, FileAccess *p_c
String extension = p_file.get_extension();
for (int i = 0; i < loader.size(); i++) {
for (int i = 0; i < loader_count; i++) {
if (!loader[i]->recognize(extension))
continue;
@ -83,122 +82,28 @@ Error ImageLoader::load_image(String p_file, Ref<Image> p_image, FileAccess *p_c
void ImageLoader::get_recognized_extensions(List<String> *p_extensions) {
for (int i = 0; i < loader.size(); i++) {
for (int i = 0; i < loader_count; i++) {
loader[i]->get_recognized_extensions(p_extensions);
}
}
ImageFormatLoader *ImageLoader::recognize(const String &p_extension) {
bool ImageLoader::recognize(const String &p_extension) {
for (int i = 0; i < loader.size(); i++) {
for (int i = 0; i < loader_count; i++) {
if (loader[i]->recognize(p_extension))
return loader[i];
return true;
}
return NULL;
return false;
}
Vector<ImageFormatLoader *> ImageLoader::loader;
ImageFormatLoader *ImageLoader::loader[MAX_LOADERS];
int ImageLoader::loader_count = 0;
void ImageLoader::add_image_format_loader(ImageFormatLoader *p_loader) {
loader.push_back(p_loader);
}
void ImageLoader::remove_image_format_loader(ImageFormatLoader *p_loader) {
loader.erase(p_loader);
}
const Vector<ImageFormatLoader *> &ImageLoader::get_image_format_loaders() {
return loader;
}
void ImageLoader::cleanup() {
while (loader.size()) {
remove_image_format_loader(loader[0]);
}
}
/////////////////
RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_original_path, Error *r_error) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) {
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
return RES();
}
uint8_t header[4] = { 0, 0, 0, 0 };
f->get_buffer(header, 4);
bool unrecognized = header[0] != 'G' || header[1] != 'D' || header[2] != 'I' || header[3] != 'M';
if (unrecognized) {
memdelete(f);
if (r_error) {
*r_error = ERR_FILE_UNRECOGNIZED;
}
ERR_FAIL_V(RES());
}
String extension = f->get_pascal_string();
int idx = -1;
for (int i = 0; i < ImageLoader::loader.size(); i++) {
if (ImageLoader::loader[i]->recognize(extension)) {
idx = i;
break;
}
}
if (idx == -1) {
memdelete(f);
if (r_error) {
*r_error = ERR_FILE_UNRECOGNIZED;
}
ERR_FAIL_V(RES());
}
Ref<Image> image;
image.instance();
Error err = ImageLoader::loader[idx]->load_image(image, f, false, 1.0);
memdelete(f);
if (err != OK) {
if (r_error) {
*r_error = err;
}
return RES();
}
if (r_error) {
*r_error = OK;
}
return image;
}
void ResourceFormatLoaderImage::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("image");
}
bool ResourceFormatLoaderImage::handles_type(const String &p_type) const {
return p_type == "Image";
}
String ResourceFormatLoaderImage::get_resource_type(const String &p_path) const {
return p_path.get_extension().to_lower() == "image" ? "Image" : String();
ERR_FAIL_COND(loader_count >= MAX_LOADERS);
loader[loader_count++] = p_loader;
}

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,12 +31,10 @@
#ifndef IMAGE_LOADER_H
#define IMAGE_LOADER_H
#include "core/image.h"
#include "core/io/resource_loader.h"
#include "core/list.h"
#include "core/os/file_access.h"
#include "core/ustring.h"
#include "image.h"
#include "list.h"
#include "os/file_access.h"
#include "ustring.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@ -57,7 +55,6 @@ class ImageLoader;
class ImageFormatLoader {
friend class ImageLoader;
friend class ResourceFormatLoaderImage;
protected:
virtual Error load_image(Ref<Image> p_image, FileAccess *p_fileaccess, bool p_force_linear, float p_scale) = 0;
@ -70,30 +67,20 @@ public:
class ImageLoader {
static Vector<ImageFormatLoader *> loader;
friend class ResourceFormatLoaderImage;
enum {
MAX_LOADERS = 8
};
static ImageFormatLoader *loader[MAX_LOADERS];
static int loader_count;
protected:
public:
static Error load_image(String p_file, Ref<Image> p_image, FileAccess *p_custom = NULL, bool p_force_linear = false, float p_scale = 1.0);
static void get_recognized_extensions(List<String> *p_extensions);
static ImageFormatLoader *recognize(const String &p_extension);
static bool recognize(const String &p_extension);
static void add_image_format_loader(ImageFormatLoader *p_loader);
static void remove_image_format_loader(ImageFormatLoader *p_loader);
static const Vector<ImageFormatLoader *> &get_image_format_loaders();
static void cleanup();
};
class ResourceFormatLoaderImage : public ResourceFormatLoader {
GDCLASS(ResourceFormatLoaderImage, ResourceFormatLoader)
public:
virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
};
#endif

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -29,10 +29,9 @@
/*************************************************************************/
#include "ip.h"
#include "core/hash_map.h"
#include "core/os/semaphore.h"
#include "core/os/thread.h"
#include "hash_map.h"
#include "os/semaphore.h"
#include "os/thread.h"
VARIANT_ENUM_CAST(IP::ResolverStatus);
@ -118,7 +117,7 @@ IP_Address IP::resolve_hostname(const String &p_hostname, IP::Type p_type) {
resolver->mutex->lock();
String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type);
if (resolver->cache.has(key) && resolver->cache[key].is_valid()) {
if (resolver->cache.has(key)) {
IP_Address res = resolver->cache[key];
resolver->mutex->unlock();
return res;
@ -145,7 +144,7 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Typ
String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type);
resolver->queue[id].hostname = p_hostname;
resolver->queue[id].type = p_type;
if (resolver->cache.has(key) && resolver->cache[key].is_valid()) {
if (resolver->cache.has(key)) {
resolver->queue[id].response = resolver->cache[key];
resolver->queue[id].status = IP::RESOLVER_STATUS_DONE;
} else {

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,8 +31,8 @@
#ifndef IP_H
#define IP_H
#include "core/io/ip_address.h"
#include "core/os/os.h"
#include "io/ip_address.h"
#include "os/os.h"
struct _IP_ResolverPrivate;

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -184,7 +184,7 @@ bool IP_Address::is_ipv4() const {
}
const uint8_t *IP_Address::get_ipv4() const {
ERR_FAIL_COND_V(!is_ipv4(), &(field8[12])); // Not the correct IPv4 (it's an IPv6), but we don't want to return a null pointer risking an engine crash.
ERR_FAIL_COND_V(!is_ipv4(), 0);
return &(field8[12]);
}

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,7 +31,7 @@
#ifndef IP_ADDRESS_H
#define IP_ADDRESS_H
#include "core/ustring.h"
#include "ustring.h"
struct IP_Address {

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -29,8 +29,7 @@
/*************************************************************************/
#include "json.h"
#include "core/print_string.h"
#include "print_string.h"
const char *JSON::tk_name[TK_MAX] = {
"'{'",

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,7 +31,7 @@
#ifndef JSON_H
#define JSON_H
#include "core/variant.h"
#include "variant.h"
class JSON {

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -30,9 +30,9 @@
#include "logger.h"
#include "core/os/dir_access.h"
#include "core/os/os.h"
#include "core/print_string.h"
#include "os/dir_access.h"
#include "os/os.h"
#include "print_string.h"
// va_copy was defined in the C99, but not in C++ standards before C++11.
// When you compile C++ without --std=c++<XX> option, compilers still define
@ -45,10 +45,6 @@
#endif
#endif
#if defined(MINGW_ENABLED) || defined(_MSC_VER)
#define sprintf sprintf_s
#endif
bool Logger::should_log(bool p_err) {
return (!p_err || _print_error_enabled) && (p_err || _print_line_enabled);
}
@ -116,7 +112,7 @@ void RotatedFileLogger::clear_old_backups() {
int max_backups = max_files - 1; // -1 for the current file
String basename = base_path.get_file().get_basename();
String extension = base_path.get_extension();
String extension = "." + base_path.get_extension();
DirAccess *da = DirAccess::open(base_path.get_base_dir());
if (!da) {
@ -127,7 +123,7 @@ void RotatedFileLogger::clear_old_backups() {
String f = da->get_next();
Set<String> backups;
while (f != String()) {
if (!da->current_is_dir() && f.begins_with(basename) && f.get_extension() == extension && f != base_path.get_file()) {
if (!da->current_is_dir() && f.begins_with(basename) && f.ends_with(extension) && f != base_path.get_file()) {
backups.insert(f);
}
f = da->get_next();
@ -156,10 +152,7 @@ void RotatedFileLogger::rotate_file() {
OS::Time time = OS::get_singleton()->get_time();
sprintf(timestamp, "-%04d-%02d-%02d-%02d-%02d-%02d", date.year, date.month, date.day, time.hour, time.min, time.sec);
String backup_name = base_path.get_basename() + timestamp;
if (base_path.get_extension() != String()) {
backup_name += "." + base_path.get_extension();
}
String backup_name = base_path.get_basename() + timestamp + "." + base_path.get_extension();
DirAccess *da = DirAccess::open(base_path.get_base_dir());
if (da) {
@ -179,10 +172,11 @@ void RotatedFileLogger::rotate_file() {
file = FileAccess::open(base_path, FileAccess::WRITE);
}
RotatedFileLogger::RotatedFileLogger(const String &p_base_path, int p_max_files) :
base_path(p_base_path.simplify_path()),
max_files(p_max_files > 0 ? p_max_files : 1),
file(NULL) {
RotatedFileLogger::RotatedFileLogger(const String &p_base_path, int p_max_files) {
file = NULL;
base_path = p_base_path.simplify_path();
max_files = p_max_files > 0 ? p_max_files : 1;
rotate_file();
}
@ -239,8 +233,8 @@ void StdLogger::logv(const char *p_format, va_list p_list, bool p_err) {
StdLogger::~StdLogger() {}
CompositeLogger::CompositeLogger(Vector<Logger *> p_loggers) :
loggers(p_loggers) {
CompositeLogger::CompositeLogger(Vector<Logger *> p_loggers) {
loggers = p_loggers;
}
void CompositeLogger::logv(const char *p_format, va_list p_list, bool p_err) {

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,10 +31,9 @@
#ifndef LOGGER_H
#define LOGGER_H
#include "core/os/file_access.h"
#include "core/ustring.h"
#include "core/vector.h"
#include "os/file_access.h"
#include "ustring.h"
#include "vector.h"
#include <stdarg.h>
class Logger {
@ -49,11 +48,11 @@ public:
ERR_SHADER
};
virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0 = 0;
virtual void logv(const char *p_format, va_list p_list, bool p_err) = 0;
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
void logf(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
void logf_error(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
void logf(const char *p_format, ...);
void logf_error(const char *p_format, ...);
virtual ~Logger();
};
@ -64,7 +63,7 @@ public:
class StdLogger : public Logger {
public:
virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0;
virtual void logv(const char *p_format, va_list p_list, bool p_err);
virtual ~StdLogger();
};
@ -88,7 +87,7 @@ class RotatedFileLogger : public Logger {
public:
RotatedFileLogger(const String &p_base_path, int p_max_files = 10);
virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0;
virtual void logv(const char *p_format, va_list p_list, bool p_err);
virtual ~RotatedFileLogger();
};
@ -99,7 +98,7 @@ class CompositeLogger : public Logger {
public:
CompositeLogger(Vector<Logger *> p_loggers);
virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0;
virtual void logv(const char *p_format, va_list p_list, bool p_err);
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
void add_logger(Logger *p_logger);
@ -107,4 +106,4 @@ public:
virtual ~CompositeLogger();
};
#endif
#endif

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -29,19 +29,14 @@
/*************************************************************************/
#include "marshalls.h"
#include "core/os/keyboard.h"
#include "core/print_string.h"
#include "core/reference.h"
#include <limits.h>
#include "os/keyboard.h"
#include "print_string.h"
#include "reference.h"
#include <stdio.h>
void EncodedObjectAsID::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_object_id", "id"), &EncodedObjectAsID::set_object_id);
ClassDB::bind_method(D_METHOD("get_object_id"), &EncodedObjectAsID::get_object_id);
ADD_PROPERTY(PropertyInfo(Variant::INT, "object_id"), "set_object_id", "get_object_id");
}
void EncodedObjectAsID::set_object_id(ObjectID p_id) {
@ -53,13 +48,10 @@ ObjectID EncodedObjectAsID::get_object_id() const {
return id;
}
EncodedObjectAsID::EncodedObjectAsID() :
id(0) {
}
EncodedObjectAsID::EncodedObjectAsID() {
#define _S(a) ((int32_t)a)
#define ERR_FAIL_ADD_OF(a, b, err) ERR_FAIL_COND_V(_S(b) < 0 || _S(a) < 0 || _S(a) > INT_MAX - _S(b), err)
#define ERR_FAIL_MUL_OF(a, b, err) ERR_FAIL_COND_V(_S(a) < 0 || _S(b) <= 0 || _S(a) > INT_MAX / _S(b), err)
id = 0;
}
#define ENCODE_MASK 0xFF
#define ENCODE_FLAG_64 1 << 16
@ -68,31 +60,23 @@ EncodedObjectAsID::EncodedObjectAsID() :
static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r_string) {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
int32_t strlen = decode_uint32(buf);
int32_t pad = 0;
// Handle padding
if (strlen % 4) {
pad = 4 - strlen % 4;
}
uint32_t strlen = decode_uint32(buf);
buf += 4;
len -= 4;
// Ensure buffer is big enough
ERR_FAIL_ADD_OF(strlen, pad, ERR_FILE_EOF);
ERR_FAIL_COND_V(strlen < 0 || strlen + pad > len, ERR_FILE_EOF);
ERR_FAIL_COND_V((int)strlen > len, ERR_FILE_EOF);
String str;
ERR_FAIL_COND_V(str.parse_utf8((const char *)buf, strlen), ERR_INVALID_DATA);
str.parse_utf8((const char *)buf, strlen);
r_string = str;
// Add padding
strlen += pad;
//handle padding
if (strlen % 4) {
strlen += 4 - strlen % 4;
}
// Update buffer pos, left data count, and return size
buf += strlen;
len -= strlen;
if (r_len) {
(*r_len) += 4 + strlen;
}
@ -135,15 +119,14 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::INT: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
if (type & ENCODE_FLAG_64) {
ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
int64_t val = decode_uint64(buf);
r_variant = val;
if (r_len)
(*r_len) += 8;
} else {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
int32_t val = decode_uint32(buf);
r_variant = val;
if (r_len)
@ -153,14 +136,14 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::REAL: {
ERR_FAIL_COND_V(len < (int)4, ERR_INVALID_DATA);
if (type & ENCODE_FLAG_64) {
ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
double val = decode_double(buf);
r_variant = val;
if (r_len)
(*r_len) += 8;
} else {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
float val = decode_float(buf);
r_variant = val;
if (r_len)
@ -181,7 +164,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
// math types
case Variant::VECTOR2: {
ERR_FAIL_COND_V(len < 4 * 2, ERR_INVALID_DATA);
ERR_FAIL_COND_V(len < (int)4 * 2, ERR_INVALID_DATA);
Vector2 val;
val.x = decode_float(&buf[0]);
val.y = decode_float(&buf[4]);
@ -193,7 +176,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break; // 5
case Variant::RECT2: {
ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
ERR_FAIL_COND_V(len < (int)4 * 4, ERR_INVALID_DATA);
Rect2 val;
val.position.x = decode_float(&buf[0]);
val.position.y = decode_float(&buf[4]);
@ -207,7 +190,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::VECTOR3: {
ERR_FAIL_COND_V(len < 4 * 3, ERR_INVALID_DATA);
ERR_FAIL_COND_V(len < (int)4 * 3, ERR_INVALID_DATA);
Vector3 val;
val.x = decode_float(&buf[0]);
val.y = decode_float(&buf[4]);
@ -220,7 +203,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::TRANSFORM2D: {
ERR_FAIL_COND_V(len < 4 * 6, ERR_INVALID_DATA);
ERR_FAIL_COND_V(len < (int)4 * 6, ERR_INVALID_DATA);
Transform2D val;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
@ -237,7 +220,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::PLANE: {
ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
ERR_FAIL_COND_V(len < (int)4 * 4, ERR_INVALID_DATA);
Plane val;
val.normal.x = decode_float(&buf[0]);
val.normal.y = decode_float(&buf[4]);
@ -251,7 +234,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::QUAT: {
ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
ERR_FAIL_COND_V(len < (int)4 * 4, ERR_INVALID_DATA);
Quat val;
val.x = decode_float(&buf[0]);
val.y = decode_float(&buf[4]);
@ -265,7 +248,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::AABB: {
ERR_FAIL_COND_V(len < 4 * 6, ERR_INVALID_DATA);
ERR_FAIL_COND_V(len < (int)4 * 6, ERR_INVALID_DATA);
AABB val;
val.position.x = decode_float(&buf[0]);
val.position.y = decode_float(&buf[4]);
@ -281,7 +264,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::BASIS: {
ERR_FAIL_COND_V(len < 4 * 9, ERR_INVALID_DATA);
ERR_FAIL_COND_V(len < (int)4 * 9, ERR_INVALID_DATA);
Basis val;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
@ -298,7 +281,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::TRANSFORM: {
ERR_FAIL_COND_V(len < 4 * 12, ERR_INVALID_DATA);
ERR_FAIL_COND_V(len < (int)4 * 12, ERR_INVALID_DATA);
Transform val;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
@ -320,7 +303,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
// misc types
case Variant::COLOR: {
ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
ERR_FAIL_COND_V(len < (int)4 * 4, ERR_INVALID_DATA);
Color val;
val.r = decode_float(&buf[0]);
val.g = decode_float(&buf[4]);
@ -335,7 +318,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::NODE_PATH: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
int32_t strlen = decode_uint32(buf);
uint32_t strlen = decode_uint32(buf);
if (strlen & 0x80000000) {
//new format
@ -360,15 +343,31 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
for (uint32_t i = 0; i < total; i++) {
ERR_FAIL_COND_V((int)len < 4, ERR_INVALID_DATA);
strlen = decode_uint32(buf);
int pad = 0;
if (strlen % 4)
pad += 4 - strlen % 4;
buf += 4;
len -= 4;
ERR_FAIL_COND_V((int)strlen + pad > len, ERR_INVALID_DATA);
String str;
Error err = _decode_string(buf, len, r_len, str);
if (err)
return err;
str.parse_utf8((const char *)buf, strlen);
if (i < namecount)
names.push_back(str);
else
subnames.push_back(str);
buf += strlen + pad;
len -= strlen + pad;
if (r_len)
(*r_len) += 4 + strlen + pad;
}
r_variant = NodePath(names, subnames, flags & 1);
@ -376,7 +375,17 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} else {
//old format, just a string
ERR_FAIL_V(ERR_INVALID_DATA);
buf += 4;
len -= 4;
ERR_FAIL_COND_V((int)strlen > len, ERR_INVALID_DATA);
String str;
str.parse_utf8((const char *)buf, strlen);
r_variant = NodePath(str);
if (r_len)
(*r_len) += 4 + strlen;
}
} break;
@ -393,7 +402,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
if (type & ENCODE_FLAG_OBJECT_AS_ID) {
//this _is_ allowed
ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
ObjectID val = decode_uint64(buf);
if (r_len)
(*r_len) += 8;
@ -467,7 +475,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::DICTIONARY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
int32_t count = decode_uint32(buf);
uint32_t count = decode_uint32(buf);
// bool shared = count&0x80000000;
count &= 0x7FFFFFFF;
@ -480,7 +488,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
Dictionary d;
for (int i = 0; i < count; i++) {
for (uint32_t i = 0; i < count; i++) {
Variant key, value;
@ -512,7 +520,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::ARRAY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
int32_t count = decode_uint32(buf);
uint32_t count = decode_uint32(buf);
// bool shared = count&0x80000000;
count &= 0x7FFFFFFF;
@ -525,7 +533,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
Array varr;
for (int i = 0; i < count; i++) {
for (uint32_t i = 0; i < count; i++) {
int used = 0;
Variant v;
@ -547,17 +555,17 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::POOL_BYTE_ARRAY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
int32_t count = decode_uint32(buf);
uint32_t count = decode_uint32(buf);
buf += 4;
len -= 4;
ERR_FAIL_COND_V(count < 0 || count > len, ERR_INVALID_DATA);
ERR_FAIL_COND_V((int)count > len, ERR_INVALID_DATA);
PoolVector<uint8_t> data;
if (count) {
data.resize(count);
PoolVector<uint8_t>::Write w = data.write();
for (int32_t i = 0; i < count; i++) {
for (uint32_t i = 0; i < count; i++) {
w[i] = buf[i];
}
@ -577,11 +585,10 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::POOL_INT_ARRAY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
int32_t count = decode_uint32(buf);
uint32_t count = decode_uint32(buf);
buf += 4;
len -= 4;
ERR_FAIL_MUL_OF(count, 4, ERR_INVALID_DATA);
ERR_FAIL_COND_V(count < 0 || count * 4 > len, ERR_INVALID_DATA);
ERR_FAIL_COND_V((int)count * 4 > len, ERR_INVALID_DATA);
PoolVector<int> data;
@ -589,7 +596,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
//const int*rbuf=(const int*)buf;
data.resize(count);
PoolVector<int>::Write w = data.write();
for (int32_t i = 0; i < count; i++) {
for (uint32_t i = 0; i < count; i++) {
w[i] = decode_uint32(&buf[i * 4]);
}
@ -605,11 +612,10 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::POOL_REAL_ARRAY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
int32_t count = decode_uint32(buf);
uint32_t count = decode_uint32(buf);
buf += 4;
len -= 4;
ERR_FAIL_MUL_OF(count, 4, ERR_INVALID_DATA);
ERR_FAIL_COND_V(count < 0 || count * 4 > len, ERR_INVALID_DATA);
ERR_FAIL_COND_V((int)count * 4 > len, ERR_INVALID_DATA);
PoolVector<float> data;
@ -617,7 +623,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
//const float*rbuf=(const float*)buf;
data.resize(count);
PoolVector<float>::Write w = data.write();
for (int32_t i = 0; i < count; i++) {
for (uint32_t i = 0; i < count; i++) {
w[i] = decode_float(&buf[i * 4]);
}
@ -634,7 +640,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::POOL_STRING_ARRAY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
int32_t count = decode_uint32(buf);
uint32_t count = decode_uint32(buf);
PoolVector<String> strings;
buf += 4;
@ -644,14 +650,35 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
(*r_len) += 4;
//printf("string count: %i\n",count);
for (int32_t i = 0; i < count; i++) {
for (int i = 0; i < (int)count; i++) {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
uint32_t strlen = decode_uint32(buf);
buf += 4;
len -= 4;
ERR_FAIL_COND_V((int)strlen > len, ERR_INVALID_DATA);
//printf("loaded string: %s\n",(const char*)buf);
String str;
Error err = _decode_string(buf, len, r_len, str);
if (err)
return err;
str.parse_utf8((const char *)buf, strlen);
strings.push_back(str);
buf += strlen;
len -= strlen;
if (r_len)
(*r_len) += 4 + strlen;
if (strlen % 4) {
int pad = 4 - (strlen % 4);
buf += pad;
len -= pad;
if (r_len) {
(*r_len) += pad;
}
}
}
r_variant = strings;
@ -660,12 +687,11 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::POOL_VECTOR2_ARRAY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
int32_t count = decode_uint32(buf);
uint32_t count = decode_uint32(buf);
buf += 4;
len -= 4;
ERR_FAIL_MUL_OF(count, 4 * 2, ERR_INVALID_DATA);
ERR_FAIL_COND_V(count < 0 || count * 4 * 2 > len, ERR_INVALID_DATA);
ERR_FAIL_COND_V((int)count * 4 * 2 > len, ERR_INVALID_DATA);
PoolVector<Vector2> varray;
if (r_len) {
@ -676,7 +702,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
varray.resize(count);
PoolVector<Vector2>::Write w = varray.write();
for (int32_t i = 0; i < count; i++) {
for (int i = 0; i < (int)count; i++) {
w[i].x = decode_float(buf + i * 4 * 2 + 4 * 0);
w[i].y = decode_float(buf + i * 4 * 2 + 4 * 1);
@ -696,13 +722,11 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::POOL_VECTOR3_ARRAY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
int32_t count = decode_uint32(buf);
uint32_t count = decode_uint32(buf);
buf += 4;
len -= 4;
ERR_FAIL_MUL_OF(count, 4 * 3, ERR_INVALID_DATA);
ERR_FAIL_COND_V(count < 0 || count * 4 * 3 > len, ERR_INVALID_DATA);
ERR_FAIL_COND_V((int)count * 4 * 3 > len, ERR_INVALID_DATA);
PoolVector<Vector3> varray;
if (r_len) {
@ -713,7 +737,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
varray.resize(count);
PoolVector<Vector3>::Write w = varray.write();
for (int32_t i = 0; i < count; i++) {
for (int i = 0; i < (int)count; i++) {
w[i].x = decode_float(buf + i * 4 * 3 + 4 * 0);
w[i].y = decode_float(buf + i * 4 * 3 + 4 * 1);
@ -734,13 +758,11 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::POOL_COLOR_ARRAY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
int32_t count = decode_uint32(buf);
uint32_t count = decode_uint32(buf);
buf += 4;
len -= 4;
ERR_FAIL_MUL_OF(count, 4 * 4, ERR_INVALID_DATA);
ERR_FAIL_COND_V(count < 0 || count * 4 * 4 > len, ERR_INVALID_DATA);
ERR_FAIL_COND_V((int)count * 4 * 4 > len, ERR_INVALID_DATA);
PoolVector<Color> carray;
if (r_len) {
@ -751,7 +773,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
carray.resize(count);
PoolVector<Color>::Write w = carray.write();
for (int32_t i = 0; i < count; i++) {
for (int i = 0; i < (int)count; i++) {
w[i].r = decode_float(buf + i * 4 * 4 + 4 * 0);
w[i].g = decode_float(buf + i * 4 * 4 + 4 * 1);
@ -791,12 +813,12 @@ static void _encode_string(const String &p_string, uint8_t *&buf, int &r_len) {
while (r_len % 4) {
r_len++; //pad
if (buf) {
*(buf++) = 0;
buf++;
}
}
}
Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_full_objects) {
Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_object_as_id) {
uint8_t *buf = r_buffer;
@ -808,7 +830,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
case Variant::INT: {
int64_t val = p_variant;
if (val > (int64_t)INT_MAX || val < (int64_t)INT_MIN) {
if (val > 0x7FFFFFFF || val < -0x80000000) {
flags |= ENCODE_FLAG_64;
}
} break;
@ -821,11 +843,10 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
}
} break;
case Variant::OBJECT: {
if (!p_full_objects) {
if (p_object_as_id) {
flags |= ENCODE_FLAG_OBJECT_AS_ID;
}
} break;
default: {} // nothing to do at this stage
}
if (buf) {
@ -851,16 +872,17 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
} break;
case Variant::INT: {
if (flags & ENCODE_FLAG_64) {
int64_t val = p_variant;
if (val > 0x7FFFFFFF || val < -0x80000000) {
//64 bits
if (buf) {
encode_uint64(p_variant.operator int64_t(), buf);
encode_uint64(val, buf);
}
r_len += 8;
} else {
if (buf) {
encode_uint32(p_variant.operator int32_t(), buf);
encode_uint32(int32_t(val), buf);
}
r_len += 4;
@ -868,7 +890,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
} break;
case Variant::REAL: {
if (flags & ENCODE_FLAG_64) {
double d = p_variant;
float f = d;
if (double(f) != d) {
if (buf) {
encode_double(p_variant.operator double(), buf);
}
@ -891,11 +915,11 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
if (buf) {
encode_uint32(uint32_t(np.get_name_count()) | 0x80000000, buf); //for compatibility with the old format
encode_uint32(np.get_subname_count(), buf + 4);
uint32_t np_flags = 0;
uint32_t flags = 0;
if (np.is_absolute())
np_flags |= 1;
flags |= 1;
encode_uint32(np_flags, buf + 8);
encode_uint32(flags, buf + 8);
buf += 12;
}
@ -1088,8 +1112,22 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
} break;
case Variant::OBJECT: {
if (p_full_objects) {
if (p_object_as_id) {
if (buf) {
Object *obj = p_variant;
ObjectID id = 0;
if (obj && ObjectDB::instance_validate(obj)) {
id = obj->get_instance_id();
}
encode_uint64(id, buf);
}
r_len += 8;
} else {
Object *obj = p_variant;
if (!obj) {
if (buf) {
@ -1127,7 +1165,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
_encode_string(E->get().name, buf, r_len);
int len;
Error err = encode_variant(obj->get(E->get().name), buf, len, p_full_objects);
Error err = encode_variant(obj->get(E->get().name), buf, len, p_object_as_id);
if (err)
return err;
ERR_FAIL_COND_V(len % 4, ERR_BUG);
@ -1136,19 +1174,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
buf += len;
}
}
} else {
if (buf) {
Object *obj = p_variant;
ObjectID id = 0;
if (obj && ObjectDB::instance_validate(obj)) {
id = obj->get_instance_id();
}
encode_uint64(id, buf);
}
r_len += 8;
}
} break;
@ -1181,14 +1206,12 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len++; //pad
*/
int len;
encode_variant(E->get(), buf, len, p_full_objects);
encode_variant(E->get(), buf, len, p_object_as_id);
ERR_FAIL_COND_V(len % 4, ERR_BUG);
r_len += len;
if (buf)
buf += len;
Variant *v = d.getptr(E->get());
ERR_FAIL_COND_V(!v, ERR_BUG);
encode_variant(*v, buf, len, p_full_objects);
encode_variant(d[E->get()], buf, len, p_object_as_id);
ERR_FAIL_COND_V(len % 4, ERR_BUG);
r_len += len;
if (buf)
@ -1210,7 +1233,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
for (int i = 0; i < v.size(); i++) {
int len;
encode_variant(v.get(i), buf, len, p_full_objects);
encode_variant(v.get(i), buf, len, p_object_as_id);
ERR_FAIL_COND_V(len % 4, ERR_BUG);
r_len += len;
if (buf)
@ -1230,15 +1253,11 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
buf += 4;
PoolVector<uint8_t>::Read r = data.read();
copymem(buf, &r[0], datalen * datasize);
buf += datalen * datasize;
}
r_len += 4 + datalen * datasize;
while (r_len % 4) {
while (r_len % 4)
r_len++;
if (buf)
*(buf++) = 0;
}
} break;
case Variant::POOL_INT_ARRAY: {
@ -1302,7 +1321,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
while (r_len % 4) {
r_len++; //pad
if (buf)
*(buf++) = 0;
buf++;
}
}

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */
@ -31,10 +31,10 @@
#ifndef MARSHALLS_H
#define MARSHALLS_H
#include "core/reference.h"
#include "core/typedefs.h"
#include "core/variant.h"
#include "typedefs.h"
#include "reference.h"
#include "variant.h"
/**
* Miscellaneous helpers for marshalling data types, and encoding
* in an endian independent way
@ -199,7 +199,7 @@ public:
EncodedObjectAsID();
};
Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len = NULL, bool p_allow_objects = false);
Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_full_objects = false);
Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len = NULL, bool p_allow_objects = true);
Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_object_as_id = false);
#endif

View File

@ -1,888 +0,0 @@
/*************************************************************************/
/* multiplayer_api.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 "multiplayer_api.h"
#include "core/io/marshalls.h"
#include "scene/main/node.h"
_FORCE_INLINE_ bool _should_call_local(MultiplayerAPI::RPCMode mode, bool is_master, bool &r_skip_rpc) {
switch (mode) {
case MultiplayerAPI::RPC_MODE_DISABLED: {
// Do nothing.
} break;
case MultiplayerAPI::RPC_MODE_REMOTE: {
// Do nothing also. Remote cannot produce a local call.
} break;
case MultiplayerAPI::RPC_MODE_MASTERSYNC: {
if (is_master)
r_skip_rpc = true; // I am the master, so skip remote call.
FALLTHROUGH;
}
case MultiplayerAPI::RPC_MODE_REMOTESYNC:
case MultiplayerAPI::RPC_MODE_PUPPETSYNC: {
// Call it, sync always results in a local call.
return true;
} break;
case MultiplayerAPI::RPC_MODE_MASTER: {
if (is_master)
r_skip_rpc = true; // I am the master, so skip remote call.
return is_master;
} break;
case MultiplayerAPI::RPC_MODE_PUPPET: {
return !is_master;
} break;
}
return false;
}
_FORCE_INLINE_ bool _can_call_mode(Node *p_node, MultiplayerAPI::RPCMode mode, int p_remote_id) {
switch (mode) {
case MultiplayerAPI::RPC_MODE_DISABLED: {
return false;
} break;
case MultiplayerAPI::RPC_MODE_REMOTE:
case MultiplayerAPI::RPC_MODE_REMOTESYNC: {
return true;
} break;
case MultiplayerAPI::RPC_MODE_MASTERSYNC:
case MultiplayerAPI::RPC_MODE_MASTER: {
return p_node->is_network_master();
} break;
case MultiplayerAPI::RPC_MODE_PUPPETSYNC:
case MultiplayerAPI::RPC_MODE_PUPPET: {
return !p_node->is_network_master() && p_remote_id == p_node->get_network_master();
} break;
}
return false;
}
void MultiplayerAPI::poll() {
if (!network_peer.is_valid() || network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED)
return;
network_peer->poll();
if (!network_peer.is_valid()) // It's possible that polling might have resulted in a disconnection, so check here.
return;
while (network_peer->get_available_packet_count()) {
int sender = network_peer->get_packet_peer();
const uint8_t *packet;
int len;
Error err = network_peer->get_packet(&packet, len);
if (err != OK) {
ERR_PRINT("Error getting packet!");
}
rpc_sender_id = sender;
_process_packet(sender, packet, len);
rpc_sender_id = 0;
if (!network_peer.is_valid()) {
break; // It's also possible that a packet or RPC caused a disconnection, so also check here.
}
}
}
void MultiplayerAPI::clear() {
connected_peers.clear();
path_get_cache.clear();
path_send_cache.clear();
packet_cache.clear();
last_send_cache_id = 1;
}
void MultiplayerAPI::set_root_node(Node *p_node) {
root_node = p_node;
}
void MultiplayerAPI::set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_peer) {
if (p_peer == network_peer) return; // Nothing to do
if (network_peer.is_valid()) {
network_peer->disconnect("peer_connected", this, "_add_peer");
network_peer->disconnect("peer_disconnected", this, "_del_peer");
network_peer->disconnect("connection_succeeded", this, "_connected_to_server");
network_peer->disconnect("connection_failed", this, "_connection_failed");
network_peer->disconnect("server_disconnected", this, "_server_disconnected");
clear();
}
network_peer = p_peer;
ERR_EXPLAIN("Supplied NetworkedNetworkPeer must be connecting or connected.");
ERR_FAIL_COND(p_peer.is_valid() && p_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED);
if (network_peer.is_valid()) {
network_peer->connect("peer_connected", this, "_add_peer");
network_peer->connect("peer_disconnected", this, "_del_peer");
network_peer->connect("connection_succeeded", this, "_connected_to_server");
network_peer->connect("connection_failed", this, "_connection_failed");
network_peer->connect("server_disconnected", this, "_server_disconnected");
}
}
Ref<NetworkedMultiplayerPeer> MultiplayerAPI::get_network_peer() const {
return network_peer;
}
void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_packet_len) {
ERR_EXPLAIN("Multiplayer root node was not initialized. If you are using custom multiplayer, remember to set the root node via MultiplayerAPI.set_root_node before using it");
ERR_FAIL_COND(root_node == NULL);
ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(p_packet_len < 1);
uint8_t packet_type = p_packet[0];
switch (packet_type) {
case NETWORK_COMMAND_SIMPLIFY_PATH: {
_process_simplify_path(p_from, p_packet, p_packet_len);
} break;
case NETWORK_COMMAND_CONFIRM_PATH: {
_process_confirm_path(p_from, p_packet, p_packet_len);
} break;
case NETWORK_COMMAND_REMOTE_CALL:
case NETWORK_COMMAND_REMOTE_SET: {
ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(p_packet_len < 6);
Node *node = _process_get_node(p_from, p_packet, p_packet_len);
ERR_EXPLAIN("Invalid packet received. Requested node was not found.");
ERR_FAIL_COND(node == NULL);
// Detect cstring end.
int len_end = 5;
for (; len_end < p_packet_len; len_end++) {
if (p_packet[len_end] == 0) {
break;
}
}
ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(len_end >= p_packet_len);
StringName name = String::utf8((const char *)&p_packet[5]);
if (packet_type == NETWORK_COMMAND_REMOTE_CALL) {
_process_rpc(node, name, p_from, p_packet, p_packet_len, len_end + 1);
} else {
_process_rset(node, name, p_from, p_packet, p_packet_len, len_end + 1);
}
} break;
case NETWORK_COMMAND_RAW: {
_process_raw(p_from, p_packet, p_packet_len);
} break;
}
}
Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, int p_packet_len) {
uint32_t target = decode_uint32(&p_packet[1]);
Node *node = NULL;
if (target & 0x80000000) {
// Use full path (not cached yet).
int ofs = target & 0x7FFFFFFF;
ERR_EXPLAIN("Invalid packet received. Size smaller than declared.");
ERR_FAIL_COND_V(ofs >= p_packet_len, NULL);
String paths;
paths.parse_utf8((const char *)&p_packet[ofs], p_packet_len - ofs);
NodePath np = paths;
node = root_node->get_node(np);
if (!node)
ERR_PRINTS("Failed to get path from RPC: " + String(np));
} else {
// Use cached path.
int id = target;
Map<int, PathGetCache>::Element *E = path_get_cache.find(p_from);
ERR_EXPLAIN("Invalid packet received. Requests invalid peer cache.");
ERR_FAIL_COND_V(!E, NULL);
Map<int, PathGetCache::NodeInfo>::Element *F = E->get().nodes.find(id);
ERR_EXPLAIN("Invalid packet received. Unabled to find requested cached node.");
ERR_FAIL_COND_V(!F, NULL);
PathGetCache::NodeInfo *ni = &F->get();
// Do proper caching later.
node = root_node->get_node(ni->path);
if (!node)
ERR_PRINTS("Failed to get cached path from RPC: " + String(ni->path));
}
return node;
}
void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) {
ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(p_offset >= p_packet_len);
// Check that remote can call the RPC on this node.
RPCMode rpc_mode = RPC_MODE_DISABLED;
const Map<StringName, RPCMode>::Element *E = p_node->get_node_rpc_mode(p_name);
if (E) {
rpc_mode = E->get();
} else if (p_node->get_script_instance()) {
rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_name);
}
bool can_call = _can_call_mode(p_node, rpc_mode, p_from);
ERR_EXPLAIN("RPC '" + String(p_name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rpc_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
ERR_FAIL_COND(!can_call);
int argc = p_packet[p_offset];
Vector<Variant> args;
Vector<const Variant *> argp;
args.resize(argc);
argp.resize(argc);
p_offset++;
for (int i = 0; i < argc; i++) {
ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(p_offset >= p_packet_len);
int vlen;
Error err = decode_variant(args.write[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen, allow_object_decoding || network_peer->is_object_decoding_allowed());
ERR_EXPLAIN("Invalid packet received. Unable to decode RPC argument.");
ERR_FAIL_COND(err != OK);
argp.write[i] = &args[i];
p_offset += vlen;
}
Variant::CallError ce;
p_node->call(p_name, (const Variant **)argp.ptr(), argc, ce);
if (ce.error != Variant::CallError::CALL_OK) {
String error = Variant::get_call_error_text(p_node, p_name, (const Variant **)argp.ptr(), argc, ce);
error = "RPC - " + error;
ERR_PRINTS(error);
}
}
void MultiplayerAPI::_process_rset(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) {
ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(p_offset >= p_packet_len);
// Check that remote can call the RSET on this node.
RPCMode rset_mode = RPC_MODE_DISABLED;
const Map<StringName, RPCMode>::Element *E = p_node->get_node_rset_mode(p_name);
if (E) {
rset_mode = E->get();
} else if (p_node->get_script_instance()) {
rset_mode = p_node->get_script_instance()->get_rset_mode(p_name);
}
bool can_call = _can_call_mode(p_node, rset_mode, p_from);
ERR_EXPLAIN("RSET '" + String(p_name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rset_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
ERR_FAIL_COND(!can_call);
Variant value;
Error err = decode_variant(value, &p_packet[p_offset], p_packet_len - p_offset, NULL, allow_object_decoding || network_peer->is_object_decoding_allowed());
ERR_EXPLAIN("Invalid packet received. Unable to decode RSET value.");
ERR_FAIL_COND(err != OK);
bool valid;
p_node->set(p_name, value, &valid);
if (!valid) {
String error = "Error setting remote property '" + String(p_name) + "', not found in object of type " + p_node->get_class();
ERR_PRINTS(error);
}
}
void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len) {
ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(p_packet_len < 5);
int id = decode_uint32(&p_packet[1]);
String paths;
paths.parse_utf8((const char *)&p_packet[5], p_packet_len - 5);
NodePath path = paths;
if (!path_get_cache.has(p_from)) {
path_get_cache[p_from] = PathGetCache();
}
PathGetCache::NodeInfo ni;
ni.path = path;
ni.instance = 0;
path_get_cache[p_from].nodes[id] = ni;
// Encode path to send ack.
CharString pname = String(path).utf8();
int len = encode_cstring(pname.get_data(), NULL);
Vector<uint8_t> packet;
packet.resize(1 + len);
packet.write[0] = NETWORK_COMMAND_CONFIRM_PATH;
encode_cstring(pname.get_data(), &packet.write[1]);
network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE);
network_peer->set_target_peer(p_from);
network_peer->put_packet(packet.ptr(), packet.size());
}
void MultiplayerAPI::_process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len) {
ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(p_packet_len < 2);
String paths;
paths.parse_utf8((const char *)&p_packet[1], p_packet_len - 1);
NodePath path = paths;
PathSentCache *psc = path_send_cache.getptr(path);
ERR_EXPLAIN("Invalid packet received. Tries to confirm a path which was not found in cache.");
ERR_FAIL_COND(!psc);
Map<int, bool>::Element *E = psc->confirmed_peers.find(p_from);
ERR_EXPLAIN("Invalid packet received. Source peer was not found in cache for the given path.");
ERR_FAIL_COND(!E);
E->get() = true;
}
bool MultiplayerAPI::_send_confirm_path(NodePath p_path, PathSentCache *psc, int p_target) {
bool has_all_peers = true;
List<int> peers_to_add; // If one is missing, take note to add it.
for (Set<int>::Element *E = connected_peers.front(); E; E = E->next()) {
if (p_target < 0 && E->get() == -p_target)
continue; // Continue, excluded.
if (p_target > 0 && E->get() != p_target)
continue; // Continue, not for this peer.
Map<int, bool>::Element *F = psc->confirmed_peers.find(E->get());
if (!F || !F->get()) {
// Path was not cached, or was cached but is unconfirmed.
if (!F) {
// Not cached at all, take note.
peers_to_add.push_back(E->get());
}
has_all_peers = false;
}
}
// Those that need to be added, send a message for this.
for (List<int>::Element *E = peers_to_add.front(); E; E = E->next()) {
// Encode function name.
CharString pname = String(p_path).utf8();
int len = encode_cstring(pname.get_data(), NULL);
Vector<uint8_t> packet;
packet.resize(1 + 4 + len);
packet.write[0] = NETWORK_COMMAND_SIMPLIFY_PATH;
encode_uint32(psc->id, &packet.write[1]);
encode_cstring(pname.get_data(), &packet.write[5]);
network_peer->set_target_peer(E->get()); // To all of you.
network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE);
network_peer->put_packet(packet.ptr(), packet.size());
psc->confirmed_peers.insert(E->get(), false); // Insert into confirmed, but as false since it was not confirmed.
}
return has_all_peers;
}
void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount) {
if (network_peer.is_null()) {
ERR_EXPLAIN("Attempt to remote call/set when networking is not active in SceneTree.");
ERR_FAIL();
}
if (network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_CONNECTING) {
ERR_EXPLAIN("Attempt to remote call/set when networking is not connected yet in SceneTree.");
ERR_FAIL();
}
if (network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED) {
ERR_EXPLAIN("Attempt to remote call/set when networking is disconnected.");
ERR_FAIL();
}
if (p_argcount > 255) {
ERR_EXPLAIN("Too many arguments >255.");
ERR_FAIL();
}
if (p_to != 0 && !connected_peers.has(ABS(p_to))) {
if (p_to == network_peer->get_unique_id()) {
ERR_EXPLAIN("Attempt to remote call/set yourself! unique ID: " + itos(network_peer->get_unique_id()));
} else {
ERR_EXPLAIN("Attempt to remote call unexisting ID: " + itos(p_to));
}
ERR_FAIL();
}
NodePath from_path = (root_node->get_path()).rel_path_to(p_from->get_path());
ERR_EXPLAIN("Unable to send RPC. Relative path is empty. THIS IS LIKELY A BUG IN THE ENGINE!");
ERR_FAIL_COND(from_path.is_empty());
// See if the path is cached.
PathSentCache *psc = path_send_cache.getptr(from_path);
if (!psc) {
// Path is not cached, create.
path_send_cache[from_path] = PathSentCache();
psc = path_send_cache.getptr(from_path);
psc->id = last_send_cache_id++;
}
// Create base packet, lots of hardcode because it must be tight.
int ofs = 0;
#define MAKE_ROOM(m_amount) \
if (packet_cache.size() < m_amount) packet_cache.resize(m_amount);
// Encode type.
MAKE_ROOM(1);
packet_cache.write[0] = p_set ? NETWORK_COMMAND_REMOTE_SET : NETWORK_COMMAND_REMOTE_CALL;
ofs += 1;
// Encode ID.
MAKE_ROOM(ofs + 4);
encode_uint32(psc->id, &(packet_cache.write[ofs]));
ofs += 4;
// Encode function name.
CharString name = String(p_name).utf8();
int len = encode_cstring(name.get_data(), NULL);
MAKE_ROOM(ofs + len);
encode_cstring(name.get_data(), &(packet_cache.write[ofs]));
ofs += len;
if (p_set) {
// Set argument.
Error err = encode_variant(*p_arg[0], NULL, len, allow_object_decoding || network_peer->is_object_decoding_allowed());
ERR_EXPLAIN("Unable to encode RSET value. THIS IS LIKELY A BUG IN THE ENGINE!");
ERR_FAIL_COND(err != OK);
MAKE_ROOM(ofs + len);
encode_variant(*p_arg[0], &(packet_cache.write[ofs]), len, allow_object_decoding || network_peer->is_object_decoding_allowed());
ofs += len;
} else {
// Call arguments.
MAKE_ROOM(ofs + 1);
packet_cache.write[ofs] = p_argcount;
ofs += 1;
for (int i = 0; i < p_argcount; i++) {
Error err = encode_variant(*p_arg[i], NULL, len, allow_object_decoding || network_peer->is_object_decoding_allowed());
ERR_EXPLAIN("Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!");
ERR_FAIL_COND(err != OK);
MAKE_ROOM(ofs + len);
encode_variant(*p_arg[i], &(packet_cache.write[ofs]), len, allow_object_decoding || network_peer->is_object_decoding_allowed());
ofs += len;
}
}
// See if all peers have cached path (is so, call can be fast).
bool has_all_peers = _send_confirm_path(from_path, psc, p_to);
// Take chance and set transfer mode, since all send methods will use it.
network_peer->set_transfer_mode(p_unreliable ? NetworkedMultiplayerPeer::TRANSFER_MODE_UNRELIABLE : NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE);
if (has_all_peers) {
// They all have verified paths, so send fast.
network_peer->set_target_peer(p_to); // To all of you.
network_peer->put_packet(packet_cache.ptr(), ofs); // A message with love.
} else {
// Not all verified path, so send one by one.
// Append path at the end, since we will need it for some packets.
CharString pname = String(from_path).utf8();
int path_len = encode_cstring(pname.get_data(), NULL);
MAKE_ROOM(ofs + path_len);
encode_cstring(pname.get_data(), &(packet_cache.write[ofs]));
for (Set<int>::Element *E = connected_peers.front(); E; E = E->next()) {
if (p_to < 0 && E->get() == -p_to)
continue; // Continue, excluded.
if (p_to > 0 && E->get() != p_to)
continue; // Continue, not for this peer.
Map<int, bool>::Element *F = psc->confirmed_peers.find(E->get());
ERR_CONTINUE(!F); // Should never happen.
network_peer->set_target_peer(E->get()); // To this one specifically.
if (F->get()) {
// This one confirmed path, so use id.
encode_uint32(psc->id, &(packet_cache.write[1]));
network_peer->put_packet(packet_cache.ptr(), ofs);
} else {
// This one did not confirm path yet, so use entire path (sorry!).
encode_uint32(0x80000000 | ofs, &(packet_cache.write[1])); // Offset to path and flag.
network_peer->put_packet(packet_cache.ptr(), ofs + path_len);
}
}
}
}
void MultiplayerAPI::_add_peer(int p_id) {
connected_peers.insert(p_id);
path_get_cache.insert(p_id, PathGetCache());
emit_signal("network_peer_connected", p_id);
}
void MultiplayerAPI::_del_peer(int p_id) {
connected_peers.erase(p_id);
path_get_cache.erase(p_id); // I no longer need your cache, sorry.
emit_signal("network_peer_disconnected", p_id);
}
void MultiplayerAPI::_connected_to_server() {
emit_signal("connected_to_server");
}
void MultiplayerAPI::_connection_failed() {
emit_signal("connection_failed");
}
void MultiplayerAPI::_server_disconnected() {
emit_signal("server_disconnected");
}
void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount) {
ERR_EXPLAIN("Trying to call an RPC while no network peer is active.");
ERR_FAIL_COND(!network_peer.is_valid());
ERR_EXPLAIN("Trying to call an RPC on a node which is not inside SceneTree.");
ERR_FAIL_COND(!p_node->is_inside_tree());
ERR_EXPLAIN("Trying to call an RPC via a network peer which is not connected.");
ERR_FAIL_COND(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED);
int node_id = network_peer->get_unique_id();
bool skip_rpc = false;
bool call_local_native = false;
bool call_local_script = false;
bool is_master = p_node->is_network_master();
if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) {
// Check that send mode can use local call.
const Map<StringName, RPCMode>::Element *E = p_node->get_node_rpc_mode(p_method);
if (E) {
call_local_native = _should_call_local(E->get(), is_master, skip_rpc);
}
if (call_local_native) {
// Done below.
} else if (p_node->get_script_instance()) {
// Attempt with script.
RPCMode rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_method);
call_local_script = _should_call_local(rpc_mode, is_master, skip_rpc);
}
}
if (!skip_rpc) {
_send_rpc(p_node, p_peer_id, p_unreliable, false, p_method, p_arg, p_argcount);
}
if (call_local_native) {
Variant::CallError ce;
p_node->call(p_method, p_arg, p_argcount, ce);
if (ce.error != Variant::CallError::CALL_OK) {
String error = Variant::get_call_error_text(p_node, p_method, p_arg, p_argcount, ce);
error = "rpc() aborted in local call: - " + error;
ERR_PRINTS(error);
return;
}
}
if (call_local_script) {
Variant::CallError ce;
ce.error = Variant::CallError::CALL_OK;
p_node->get_script_instance()->call(p_method, p_arg, p_argcount, ce);
if (ce.error != Variant::CallError::CALL_OK) {
String error = Variant::get_call_error_text(p_node, p_method, p_arg, p_argcount, ce);
error = "rpc() aborted in script local call: - " + error;
ERR_PRINTS(error);
return;
}
}
}
void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value) {
ERR_EXPLAIN("Trying to RSET while no network peer is active.");
ERR_FAIL_COND(!network_peer.is_valid());
ERR_EXPLAIN("Trying to RSET on a node which is not inside SceneTree.");
ERR_FAIL_COND(!p_node->is_inside_tree());
ERR_EXPLAIN("Trying to send an RSET via a network peer which is not connected.");
ERR_FAIL_COND(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED);
int node_id = network_peer->get_unique_id();
bool is_master = p_node->is_network_master();
bool skip_rset = false;
if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) {
// Check that send mode can use local call.
bool set_local = false;
const Map<StringName, RPCMode>::Element *E = p_node->get_node_rset_mode(p_property);
if (E) {
set_local = _should_call_local(E->get(), is_master, skip_rset);
}
if (set_local) {
bool valid;
p_node->set(p_property, p_value, &valid);
if (!valid) {
String error = "rset() aborted in local set, property not found: - " + String(p_property);
ERR_PRINTS(error);
return;
}
} else if (p_node->get_script_instance()) {
// Attempt with script.
RPCMode rpc_mode = p_node->get_script_instance()->get_rset_mode(p_property);
set_local = _should_call_local(rpc_mode, is_master, skip_rset);
if (set_local) {
bool valid = p_node->get_script_instance()->set(p_property, p_value);
if (!valid) {
String error = "rset() aborted in local script set, property not found: - " + String(p_property);
ERR_PRINTS(error);
return;
}
}
}
}
if (skip_rset)
return;
const Variant *vptr = &p_value;
_send_rpc(p_node, p_peer_id, p_unreliable, true, p_property, &vptr, 1);
}
Error MultiplayerAPI::send_bytes(PoolVector<uint8_t> p_data, int p_to, NetworkedMultiplayerPeer::TransferMode p_mode) {
ERR_EXPLAIN("Trying to send an empty raw packet.");
ERR_FAIL_COND_V(p_data.size() < 1, ERR_INVALID_DATA);
ERR_EXPLAIN("Trying to send a raw packet while no network peer is active.");
ERR_FAIL_COND_V(!network_peer.is_valid(), ERR_UNCONFIGURED);
ERR_EXPLAIN("Trying to send a raw packet via a network peer which is not connected.");
ERR_FAIL_COND_V(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED);
MAKE_ROOM(p_data.size() + 1);
PoolVector<uint8_t>::Read r = p_data.read();
packet_cache.write[0] = NETWORK_COMMAND_RAW;
memcpy(&packet_cache.write[1], &r[0], p_data.size());
network_peer->set_target_peer(p_to);
network_peer->set_transfer_mode(p_mode);
return network_peer->put_packet(packet_cache.ptr(), p_data.size() + 1);
}
void MultiplayerAPI::_process_raw(int p_from, const uint8_t *p_packet, int p_packet_len) {
ERR_EXPLAIN("Invalid packet received. Size too small.");
ERR_FAIL_COND(p_packet_len < 2);
PoolVector<uint8_t> out;
int len = p_packet_len - 1;
out.resize(len);
{
PoolVector<uint8_t>::Write w = out.write();
memcpy(&w[0], &p_packet[1], len);
}
emit_signal("network_peer_packet", p_from, out);
}
int MultiplayerAPI::get_network_unique_id() const {
ERR_EXPLAIN("No network peer is assigned. Unable to get unique network ID.");
ERR_FAIL_COND_V(!network_peer.is_valid(), 0);
return network_peer->get_unique_id();
}
bool MultiplayerAPI::is_network_server() const {
// XXX Maybe fail silently? Maybe should actually return true to make development of both local and online multiplayer easier?
ERR_EXPLAIN("No network peer is assigned. I can't be a server.");
ERR_FAIL_COND_V(!network_peer.is_valid(), false);
return network_peer->is_server();
}
void MultiplayerAPI::set_refuse_new_network_connections(bool p_refuse) {
ERR_EXPLAIN("No network peer is assigned. Unable to set 'refuse_new_connections'.");
ERR_FAIL_COND(!network_peer.is_valid());
network_peer->set_refuse_new_connections(p_refuse);
}
bool MultiplayerAPI::is_refusing_new_network_connections() const {
ERR_EXPLAIN("No network peer is assigned. Unable to get 'refuse_new_connections'.");
ERR_FAIL_COND_V(!network_peer.is_valid(), false);
return network_peer->is_refusing_new_connections();
}
Vector<int> MultiplayerAPI::get_network_connected_peers() const {
ERR_EXPLAIN("No network peer is assigned. Assume no peers are connected.");
ERR_FAIL_COND_V(!network_peer.is_valid(), Vector<int>());
Vector<int> ret;
for (Set<int>::Element *E = connected_peers.front(); E; E = E->next()) {
ret.push_back(E->get());
}
return ret;
}
void MultiplayerAPI::set_allow_object_decoding(bool p_enable) {
allow_object_decoding = p_enable;
}
bool MultiplayerAPI::is_object_decoding_allowed() const {
return allow_object_decoding;
}
void MultiplayerAPI::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_root_node", "node"), &MultiplayerAPI::set_root_node);
ClassDB::bind_method(D_METHOD("send_bytes", "bytes", "id", "mode"), &MultiplayerAPI::send_bytes, DEFVAL(NetworkedMultiplayerPeer::TARGET_PEER_BROADCAST), DEFVAL(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE));
ClassDB::bind_method(D_METHOD("has_network_peer"), &MultiplayerAPI::has_network_peer);
ClassDB::bind_method(D_METHOD("get_network_peer"), &MultiplayerAPI::get_network_peer);
ClassDB::bind_method(D_METHOD("get_network_unique_id"), &MultiplayerAPI::get_network_unique_id);
ClassDB::bind_method(D_METHOD("is_network_server"), &MultiplayerAPI::is_network_server);
ClassDB::bind_method(D_METHOD("get_rpc_sender_id"), &MultiplayerAPI::get_rpc_sender_id);
ClassDB::bind_method(D_METHOD("_add_peer", "id"), &MultiplayerAPI::_add_peer);
ClassDB::bind_method(D_METHOD("_del_peer", "id"), &MultiplayerAPI::_del_peer);
ClassDB::bind_method(D_METHOD("set_network_peer", "peer"), &MultiplayerAPI::set_network_peer);
ClassDB::bind_method(D_METHOD("poll"), &MultiplayerAPI::poll);
ClassDB::bind_method(D_METHOD("clear"), &MultiplayerAPI::clear);
ClassDB::bind_method(D_METHOD("_connected_to_server"), &MultiplayerAPI::_connected_to_server);
ClassDB::bind_method(D_METHOD("_connection_failed"), &MultiplayerAPI::_connection_failed);
ClassDB::bind_method(D_METHOD("_server_disconnected"), &MultiplayerAPI::_server_disconnected);
ClassDB::bind_method(D_METHOD("get_network_connected_peers"), &MultiplayerAPI::get_network_connected_peers);
ClassDB::bind_method(D_METHOD("set_refuse_new_network_connections", "refuse"), &MultiplayerAPI::set_refuse_new_network_connections);
ClassDB::bind_method(D_METHOD("is_refusing_new_network_connections"), &MultiplayerAPI::is_refusing_new_network_connections);
ClassDB::bind_method(D_METHOD("set_allow_object_decoding", "enable"), &MultiplayerAPI::set_allow_object_decoding);
ClassDB::bind_method(D_METHOD("is_object_decoding_allowed"), &MultiplayerAPI::is_object_decoding_allowed);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_object_decoding"), "set_allow_object_decoding", "is_object_decoding_allowed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", 0), "set_network_peer", "get_network_peer");
ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("network_peer_disconnected", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("network_peer_packet", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::POOL_BYTE_ARRAY, "packet")));
ADD_SIGNAL(MethodInfo("connected_to_server"));
ADD_SIGNAL(MethodInfo("connection_failed"));
ADD_SIGNAL(MethodInfo("server_disconnected"));
BIND_ENUM_CONSTANT(RPC_MODE_DISABLED);
BIND_ENUM_CONSTANT(RPC_MODE_REMOTE);
BIND_ENUM_CONSTANT(RPC_MODE_MASTER);
BIND_ENUM_CONSTANT(RPC_MODE_PUPPET);
BIND_ENUM_CONSTANT(RPC_MODE_SLAVE); // Deprecated.
BIND_ENUM_CONSTANT(RPC_MODE_REMOTESYNC);
BIND_ENUM_CONSTANT(RPC_MODE_SYNC); // Deprecated.
BIND_ENUM_CONSTANT(RPC_MODE_MASTERSYNC);
BIND_ENUM_CONSTANT(RPC_MODE_PUPPETSYNC);
}
MultiplayerAPI::MultiplayerAPI() :
allow_object_decoding(false) {
rpc_sender_id = 0;
root_node = NULL;
clear();
}
MultiplayerAPI::~MultiplayerAPI() {
clear();
}

View File

@ -1,139 +0,0 @@
/*************************************************************************/
/* multiplayer_api.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 MULTIPLAYER_PROTOCOL_H
#define MULTIPLAYER_PROTOCOL_H
#include "core/io/networked_multiplayer_peer.h"
#include "core/reference.h"
class MultiplayerAPI : public Reference {
GDCLASS(MultiplayerAPI, Reference);
private:
//path sent caches
struct PathSentCache {
Map<int, bool> confirmed_peers;
int id;
};
//path get caches
struct PathGetCache {
struct NodeInfo {
NodePath path;
ObjectID instance;
};
Map<int, NodeInfo> nodes;
};
Ref<NetworkedMultiplayerPeer> network_peer;
int rpc_sender_id;
Set<int> connected_peers;
HashMap<NodePath, PathSentCache> path_send_cache;
Map<int, PathGetCache> path_get_cache;
int last_send_cache_id;
Vector<uint8_t> packet_cache;
Node *root_node;
bool allow_object_decoding;
protected:
static void _bind_methods();
void _process_packet(int p_from, const uint8_t *p_packet, int p_packet_len);
void _process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len);
void _process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len);
Node *_process_get_node(int p_from, const uint8_t *p_packet, int p_packet_len);
void _process_rpc(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset);
void _process_rset(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset);
void _process_raw(int p_from, const uint8_t *p_packet, int p_packet_len);
void _send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount);
bool _send_confirm_path(NodePath p_path, PathSentCache *psc, int p_from);
public:
enum NetworkCommands {
NETWORK_COMMAND_REMOTE_CALL,
NETWORK_COMMAND_REMOTE_SET,
NETWORK_COMMAND_SIMPLIFY_PATH,
NETWORK_COMMAND_CONFIRM_PATH,
NETWORK_COMMAND_RAW,
};
enum RPCMode {
RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default)
RPC_MODE_REMOTE, // Using rpc() on it will call method / set property in all remote peers
RPC_MODE_MASTER, // Using rpc() on it will call method on wherever the master is, be it local or remote
RPC_MODE_PUPPET, // Using rpc() on it will call method for all puppets
RPC_MODE_SLAVE = RPC_MODE_PUPPET, // Deprecated, same as puppet
RPC_MODE_REMOTESYNC, // Using rpc() on it will call method / set property in all remote peers and locally
RPC_MODE_SYNC = RPC_MODE_REMOTESYNC, // Deprecated. Same as RPC_MODE_REMOTESYNC
RPC_MODE_MASTERSYNC, // Using rpc() on it will call method / set property in the master peer and locally
RPC_MODE_PUPPETSYNC, // Using rpc() on it will call method / set property in all puppets peers and locally
};
void poll();
void clear();
void set_root_node(Node *p_node);
void set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_peer);
Ref<NetworkedMultiplayerPeer> get_network_peer() const;
Error send_bytes(PoolVector<uint8_t> p_data, int p_to = NetworkedMultiplayerPeer::TARGET_PEER_BROADCAST, NetworkedMultiplayerPeer::TransferMode p_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE);
// Called by Node.rpc
void rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount);
// Called by Node.rset
void rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value);
void _add_peer(int p_id);
void _del_peer(int p_id);
void _connected_to_server();
void _connection_failed();
void _server_disconnected();
bool has_network_peer() const { return network_peer.is_valid(); }
Vector<int> get_network_connected_peers() const;
int get_rpc_sender_id() const { return rpc_sender_id; }
int get_network_unique_id() const;
bool is_network_server() const;
void set_refuse_new_network_connections(bool p_refuse);
bool is_refusing_new_network_connections() const;
void set_allow_object_decoding(bool p_enable);
bool is_object_decoding_allowed() const;
MultiplayerAPI();
~MultiplayerAPI();
};
VARIANT_ENUM_CAST(MultiplayerAPI::RPCMode);
#endif // MULTIPLAYER_PROTOCOL_H

View File

@ -1,42 +0,0 @@
/*************************************************************************/
/* net_socket.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 "net_socket.h"
NetSocket *(*NetSocket::_create)() = NULL;
NetSocket *NetSocket::create() {
if (_create)
return _create();
ERR_PRINT("Unable to create network socket, platform not supported");
return NULL;
}

View File

@ -1,79 +0,0 @@
/*************************************************************************/
/* net_socket.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 NET_SOCKET_H
#define NET_SOCKET_H
#include "core/io/ip.h"
#include "core/reference.h"
class NetSocket : public Reference {
protected:
static NetSocket *(*_create)();
public:
static NetSocket *create();
enum PollType {
POLL_TYPE_IN,
POLL_TYPE_OUT,
POLL_TYPE_IN_OUT
};
enum Type {
TYPE_NONE,
TYPE_TCP,
TYPE_UDP,
};
virtual Error open(Type p_type, IP::Type &ip_type) = 0;
virtual void close() = 0;
virtual Error bind(IP_Address p_addr, uint16_t p_port) = 0;
virtual Error listen(int p_max_pending) = 0;
virtual Error connect_to_host(IP_Address p_addr, uint16_t p_port) = 0;
virtual Error poll(PollType p_type, int timeout) const = 0;
virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read) = 0;
virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) = 0;
virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent) = 0;
virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) = 0;
virtual Ref<NetSocket> accept(IP_Address &r_ip, uint16_t &r_port) = 0;
virtual bool is_open() const = 0;
virtual int get_available_bytes() const = 0;
virtual void set_broadcasting_enabled(bool p_enabled) = 0;
virtual void set_blocking_enabled(bool p_enabled) = 0;
virtual void set_ipv6_only_enabled(bool p_enabled) = 0;
virtual void set_tcp_no_delay_enabled(bool p_enabled) = 0;
virtual void set_reuse_address_enabled(bool p_enabled) = 0;
};
#endif // NET_SOCKET_H

View File

@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 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 */

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