Compare commits

..

419 Commits

Author SHA1 Message Date
Rémi Verschelde
c508b5b2e1 Release 2.1.2-stable 2017-01-21 14:43:37 +01:00
Rémi Verschelde
b65e553440 classref: Sync with current source 2017-01-21 14:06:17 +01:00
Rémi Verschelde
7c47769aa2 Remove Quick Filter Files and fix FS search hotkey
The new Quick Filter Files behaviour since 8b47e26 had not been implemented,
so this implements it and makes it an editor hotkey instead of a menu entry.
Fixes #7582.

(cherry picked from commit c4d6e54e93)
2017-01-21 13:44:27 +01:00
Rémi Verschelde
0669c9816e Merge pull request #7557 from RandomShaper/ordered-image-group-files-2.1
Make image-groups map in export.cfg ordered (2.1)
2017-01-16 21:05:28 +01:00
Rémi Verschelde
23789f49dd Merge pull request #7561 from eska014/web-presentation-2.1
Cherry-pick usability fixes in web export presentation
[ci skip]
2017-01-16 20:13:19 +01:00
Pedro J. Estébanez
8e380677cb Make image-groups map in export.cfg ordered
This improves the VCS experience because otherwise they change their order everytime producing spurious changes.
2017-01-16 19:00:48 +01:00
eska
e4bbc1067a Improve usability in web export presentation
- Make canvas support check message visible
 - Make it obvious status can be closed by clicking
 - Don't use status to display non-critical errors
 - Fix setting total memory

(cherry picked from commit 1f7d4c4d0e)
2017-01-16 18:39:04 +01:00
Rémi Verschelde
5aac8eeb0f Merge pull request #7549 from RandomShaper/cp-usability-2.1
Cherry-pick node creation usability enhancements (2.1)
2017-01-16 18:05:56 +01:00
Rémi Verschelde
b351d4cbc1 zlib: Update to upstream version 1.2.11
(cherry picked from commit 6a3dae5be9)
2017-01-16 17:58:43 +01:00
Rémi Verschelde
1f2293d5cc Merge pull request #7554 from Faless/2.1-tcp-winfix
2.1.x - Fix bug in windows TCP poll function
2017-01-16 16:00:27 +01:00
Fabio Alessandrelli
8322c1aa64 Fix bug in windows TCP poll function
Bug introduced when implementing TCP disconnection detection.
(too much yank-paste).
Fixes #7545

(cherry picked from commit c356ec5e8b)
2017-01-16 15:51:43 +01:00
Pedro J. Estébanez
8fca6870c4 Added favorites and recent history to create dialog
Cherry-picked from 8d785812351a0a3eca88214f2436bb7574d55873 and 827a9aa829
2017-01-16 12:38:46 +01:00
Juan Linietsky
9f3c594f9e Making bits of docs appear in different dialogues is made easier with EditorHelpBit 2017-01-16 11:56:00 +01:00
Pedro J. Estébanez
b3d0596c4b Add EditorNode::set_visible_editor()
Cherry-picked from d8af6330e5
2017-01-16 11:56:00 +01:00
Rémi Verschelde
6b5a852bd8 Merge pull request #7522 from Faless/2.1-split
2.1.x Cherry pick patch to enable 2D split screen. ( #6486 )
2017-01-16 10:11:39 +01:00
Juan Linietsky
25a62a3e32 Added a few functions to make 2D split screen easier.
(cherry picked from commit a4156f1f0a)
2017-01-12 20:53:03 +01:00
Fabio Alessandrelli
b61d7e6261 Restore viewport set_world_2d functionality
(cherry picked from commit 97cf3eba56)
2017-01-12 19:44:22 +01:00
Fabio Alessandrelli
9c8ecb45f8 Improvements to scons defined WINVER/_WIN32_WINNT
(cherry picked from commit 65483d57bf)
2017-01-12 19:15:30 +01:00
Ignacio Etcheverry
8a5596322d Detect bits when building with MinGW
(cherry picked from commit 460f030b73)
2017-01-12 19:15:30 +01:00
Rémi Verschelde
93a83c81f0 Windows: Workaround missing includes in MinGW-w64 < 4
The MinGW-w64 version we have on our Travis build environment (Ubuntu 12.04,
mingw-w64 2.0.1, gcc 4.6) is old and has some missing includes in the
dependencies of the `tcpmib.h` header [0] [1] [2].
Those were not triggered before 6323779596
probably due to conflicting WINVER definitions which prevented triggering the code
specific to >= 0x0600 (Vista). We ensure it won't be triggered by defining the
_WIN32_WINNT macro to Windows XP compatibility.
(cherry picked from commit b24fe6879a)
2017-01-12 19:15:30 +01:00
Rémi Verschelde
af7fd899f4 opus: Update to upstream opusfile 0.8
Had missed it in the previous commit as the upstream website is outdated.

(cherry picked from commit c2310b41fa)
2017-01-12 19:15:30 +01:00
Rémi Verschelde
d66740175e Windows: Define _WIN32_WINRT to 0x0600 (Vista)
Passed as a compiler define to be sure it is always define before windows.h
is loaded. This means that Godot officially requires Vista API or later, it will
not work on Windows XP or earlier.

Also fix a bogus check for Windows 7 API.

(cherry picked from commit 6323779596)
2017-01-12 19:15:30 +01:00
Rémi Verschelde
5672852351 x11: Improve logic for cross-dependencies between freetype, zlib and libpng
Fixes #7373.

(cherry picked from commit d945c4e58e)
2017-01-12 19:15:30 +01:00
Rémi Verschelde
349e62835b i18n: Add support for Scots (sco) language
Fixes #6931.

(cherry picked from commit ede36aca8d)
2017-01-12 19:15:30 +01:00
Rémi Verschelde
ff490e42da Move core engine tests to main
(cherry picked from commits 790f629e5e
and 8b7a86ec7b)
2017-01-12 19:15:30 +01:00
karroffel
b1fc41a301 exposed OS.set_exit_code and OS.get_exit_code to ObjectTypeDB
(cherry picked from commit fbfcc981d9)
2017-01-12 19:15:30 +01:00
Rémi Verschelde
3cd976366e opus: Update to upstream libopus 1.1.3
(cherry picked from commit 9845bdde8d)
2017-01-12 19:15:30 +01:00
Rémi Verschelde
6e9584e0c5 zlib: Update to upstream 1.2.10
(cherry picked from commit 2ca0337f5f)
2017-01-12 19:15:30 +01:00
Rémi Verschelde
c24c2ca17b libpng: Update to upstream 1.6.28
Fixes a NULL pointer dereference bug (CVE-2016-10087).

(cherry picked from commit a0141fa823)
2017-01-12 19:15:30 +01:00
lonesurvivor
d2240404e3 Fix for the huge audio latency of the SamplePlayer (>200 ms)
- fixes PulseAudio, ALSA and RtAudio driver
- cleans up the driver files for better readability (mostly whitespace-related stuff)
- makes ALSA and Pulseaudio actually use the global setting "audio/mix_rate" for the sample rate instead of a
fixed value (RtAudio did this already)

(cherry picked from commit da6b6c2dd7)
2017-01-12 19:15:30 +01:00
Bruno Ortiz
01b8beb023 Making deselect work for TreeItem when select_mode is SELECT_SINGLE and item_selected is now properly emitted
(cherry picked from commit 4b9a96859b)
2017-01-12 19:15:30 +01:00
Bruno Ortiz
4f35fdd1e3 Exposing edit_resource method of EditorNode in the EditorPlugin (#7355)
(cherry picked from commit 7e0d0d0bb9)
2017-01-12 19:15:30 +01:00
Wilhem Barbier
0b6d4e92b5 Add the 'finished' signal to AnimatedSprite
(cherry picked from commit f6262fde11)
2017-01-12 19:15:30 +01:00
Rémi Verschelde
d8223ffa75 Welcome in 2017, dear changelog reader!
That year should bring the long-awaited OpenGL ES 3.0 compatible renderer
with state-of-the-art rendering techniques tuned to work as low as middle
end handheld devices - without compromising with the possibilities given
for higher end desktop games of course. Great times ahead for the Godot
community and the gamers that will play our games!

(cherry picked from commit c7bc44d5ad)
2017-01-12 19:15:30 +01:00
Ignacio Etcheverry
b5bdc60f58 TileMap: _update_dirty_quadrants() cancel pending update pre return
(cherry picked from commit 5b3acd287d)
2017-01-12 19:15:29 +01:00
Marc Gilleron
ba50bb9cb1 Added option to toggle bucket fill preview
(cherry picked from commit 39771f22b6)
2017-01-12 19:15:29 +01:00
Marc Gilleron
2a60bf1cd9 Added bucket fill preview
(cherry picked from commit 36d0281a2b)
2017-01-12 19:15:29 +01:00
ktksgit
1bb1b6986c Update DebugMesh when NavMesh changes
Fixes #7371
(cherry picked from commit 2807507325)
2017-01-12 19:15:29 +01:00
Bojidar Marinov
4c9c43735a Disallow assignment to expressions
Fixes #6824

(cherry picked from commits 0b077162a3
and dcc4ee21c1)
2017-01-12 19:15:28 +01:00
Fabio Alessandrelli
6940830627 Properly localize absolute path.
Calling localize_path will return a localized path in res:// if the
path starts with the resource file-system/folder, and will return
the unchanged absolute path otherwise.

Closes #6979 and #7161.

(cherry picked from commit cdc97ca453)
2017-01-12 19:15:28 +01:00
Bojidar Marinov
27a801df99 Fix #7098 by not accepting right clicks while dragging the range
(cherry picked from commit d40eb1565e)
2017-01-12 19:15:28 +01:00
volzhs
f520e7788e Show visual notice for visibility on Scene Dock
(cherry picked from commit f33e21e7af)
2017-01-12 19:15:28 +01:00
volzhs
580031e6f5 Able to change visibility when ancestor node is hidden
(cherry picked from commit 792ff11642)
2017-01-12 19:15:28 +01:00
volzhs
d5e4011bc3 Scroll horizontally with mouse wheel when horizontal enabled only
(cherry picked from commit 22b76511fb)
2017-01-12 19:15:28 +01:00
chanon
1397019424 fix ColorPicker not correctly updating after pasting hex html color
(cherry picked from commit 0bf5d86546)
2017-01-12 19:15:28 +01:00
Guilherme Felipe
eea6c43676 Add new option to always open output on play
(cherry picked from commit faf6f865dd)
2017-01-12 19:15:28 +01:00
Guilherme Felipe
3a4c412153 Fix visibility of bottom panel when start playing
(cherry picked from commit 83b82fc267)
2017-01-12 19:15:28 +01:00
Elia Argentieri
9b0be3753b Expose set_bone_name and get_bone_name to GDscript
(cherry picked from commit b96e2e1126)
2017-01-12 19:15:28 +01:00
volzhs
5698571235 Update libwebp to 0.5.2
(cherry picked from commit e04c7e11ec)
2017-01-12 19:15:28 +01:00
Ivan P. Skodje
0701e7c2d8 PopupMenu upgrade: Hide on item selection (#7306)
* Added the option to set hide on item selection. Usable in GDScript and from within the source code when you want to specify popup menus you don't want to close immediately when selecting an item

* Renamed getter from get_ to is_, fixed parent/child behavior, renamed bool variable to match most code and added ADD_PROPERTYNO to save some memory

(cherry picked from commit da950cd0f2)
2017-01-12 19:15:28 +01:00
REBELLIOUSX\Rebel_X
2fbae72d14 Fix issue #7331
A Drive with "Z" letter assigned to it on Windows will be shown.

(cherry picked from commit 20d6af6028)
2017-01-12 19:15:28 +01:00
volzhs
dbeb1ca114 Fix duplicated string on RichTextLabel if starts with '\n'
Fix #6212, #3773

(cherry picked from commit 0ecc968c5c)
2017-01-12 19:15:28 +01:00
bebae
0aebdb346a Allows to start the scene with custom arguments within the editor
fixes #7346

Path from the current scene isn't added too the argumens anymore by default and needs to be added throug the custom arguments, with $scene. Matches the behaviour of the executable without any arguments.
Custom Arguments are read from editor/main_run_args

(cherry picked from commit abdedc3522)
2017-01-12 19:15:28 +01:00
Bojidar Marinov
71b35c527f Remove extraneous line in .po reader, which caused it to disregard first line
Fixes #7337

(cherry picked from commit 474eafbbf6)
2017-01-12 19:15:28 +01:00
Ignacio Etcheverry
a282579f5c Register SpatialGizmo as a scene type
(cherry picked from commit ce41464fc0)
2017-01-12 19:15:27 +01:00
Johnson Earls
f08aa02688 Fix search to find "whole" words at end of line
Fix `_get_column_pos_of_word` so that the `SEARCH_WHOLE_WORDS` flag will properly find words that are at the end of a line.

Fixes #7326 .
(cherry picked from commit d1cf29fe99)
2017-01-12 19:15:27 +01:00
Jerome67000
a8bc2f64ad doc improvement for get_colliding_bodies() methods
(cherry picked from commit 3cd5c86b1a)
2017-01-12 19:15:27 +01:00
Bojidar Marinov
85585c7fc5 Add named colors to GDScript/core.
Names and values taken from https://en.wikipedia.org/wiki/X11_color_names

(cherry picked from commit 23381a530b)
2017-01-12 19:15:27 +01:00
Bojidar Marinov
c5bff5073e Fix #7303, Quad node mesh data leak
(cherry picked from commit 7504a015aa)
2017-01-12 19:15:27 +01:00
Gustav Lund
f10a78e5c0 fix for crash when no ALSA or Pulse installed on linux
(cherry picked from commit 2495e8a941)
2017-01-12 19:15:27 +01:00
Ignacio Etcheverry
5354d7ddcc KinematicBody: Fix wrong method bind return type
(cherry picked from commit d579d0a814)
2017-01-12 19:15:27 +01:00
Patrick Reh
ff3891f88e small improvement to y_sort: make clear which item has to be drawn first when two have the same y-coordinate
(cherry picked from commit 4118b21e43)
2017-01-12 19:15:27 +01:00
Andreas Haas
5bfd0bbe5e TextureRegionEditor: Fix mouse wheel scroll speed.
Any given mouse wheel input will generate two InputEvents in godot.
The zoom methods here acted on both ones, effectively giving a step value of 4 instead of 2.
Fixes #7236

(cherry picked from commit c2040324be)
2017-01-12 19:15:27 +01:00
Andreas Haas
fa816730c0 Curve2D/3D: Add clear_points method.
Adds a method to the Curve2D and Curve3D classes to easily clear the curve.
So you don't have to remove each point manually.

(cherry picked from commit e741da869a)
2017-01-12 19:15:27 +01:00
Andreas Haas
01f3399ed0 Particles2D: Fix initial size randomness property having no effect.
It was just a little typo :p

(cherry picked from commit 4dd6bead1f)
2017-01-12 19:15:27 +01:00
Andreas Haas
1e34e8d5e1 Fix crash on project importing by dragging a folder.
Fixes #7226

(cherry picked from commit d82c2687f3)
2017-01-12 19:15:27 +01:00
volzhs
f184455187 Show selected node in Scene dock when parent node is folded
Fix #7228

(cherry picked from commit a192e0785e)
2017-01-12 19:15:27 +01:00
volzhs
c07fe5e8de Check keystore field when export Android release apk
(cherry picked from commit 36b4b45170)
2017-01-12 19:15:27 +01:00
Rémi Verschelde
5b27f05e7e Fix console output for MinGW compilers
Reworked patch from @jay3d (#7116).
(cherry picked from commit f28ff8a208)
2017-01-12 19:15:27 +01:00
volzhs
2e74bdab35 Add alert window on Android
(cherry picked from commit 9a20068ab7)
2017-01-12 19:15:26 +01:00
volzhs
916e79a5bf Fix scroll bar moving in AnimationPlayer editor
Fix #7196

(cherry picked from commit babc5048dd)
2017-01-12 19:15:26 +01:00
volzhs
f95694ee86 Fix color selected with mouse scroll
Fix #7192

(cherry picked from commit d9048309e4)
2017-01-12 19:15:26 +01:00
Dmitry Kram
6227e8f343 Fix snap mode selector sticking in texture region module
When changing snap mode in texture region plugin ticks was not updating. Issue fixed changing order of setting checked status and setting snap mode.

(cherry picked from commit d766738991)
2017-01-12 19:15:26 +01:00
volzhs
608e3f3097 Prevent Spinbox value update while not focused or disabled
(cherry picked from commit 4df33cbcb3)
2017-01-12 19:15:26 +01:00
BastiaanOlij
ef009a8b91 Set minimum version to 10.9 building OSX
(cherry picked from commit da5651fbb9)
2017-01-12 19:15:26 +01:00
romeojulietthotel
1a41d3351a Correct description for the return values from get_status. (#7137)
(cherry picked from commit f8d523b68b)
2017-01-12 19:15:26 +01:00
Zher Huei Lee
17399de0e1 Reused Button styleboxes for ButtonArray
Plus other tweaks to make it look more similar to a VBoxContainer of
Buttons.

(cherry picked from commit 191fdc873e)
2017-01-12 19:15:26 +01:00
Zher Huei Lee
fe81402257 Flat button support in ButtonArray. Fixes #7153
(cherry picked from commit 4b7443aeea)
2017-01-12 19:15:26 +01:00
Kazuo256
b56c00cc56 Add Array.front() and Array.back()
(cherry picked from commit bf4fda64fd)
2017-01-12 19:15:26 +01:00
Bojidar Marinov
13cdc2a6f5 Guard agains duplicate calling of _ready when instanced in _enter_tree
Fixes #6005

(cherry picked from commit 184173a9b9)
2017-01-12 19:15:26 +01:00
volzhs
fd5e01d1cd Select exactly matched file automatically in FileDialog
(cherry picked from commit ff4f04e878)
2017-01-12 19:15:26 +01:00
Rémi Verschelde
b328d2eb00 Merge pull request #7494 from RandomShaper/cherry-pick-backcompat-stuff
Cherry pick backcompat stuff (2.1)
2017-01-11 10:35:36 +01:00
Rémi Verschelde
fde651ebf8 Merge pull request #7495 from RandomShaper/more-uniform-reuse-fix
More uniform reuse fix (2.1)
2017-01-11 10:34:41 +01:00
Emmanuel Leblond
39ce4a49fa Add Node2D's set_global_rot get_global_rot set_global_rotd get_global_rotd set_global_scale get_global_scale methods. 2017-01-10 17:15:28 +01:00
Bojidar Marinov
6ad84850ab Ternary operator in GDScript (a if x else b)
Fixes #1961
2017-01-10 17:09:26 +01:00
Bojidar Marinov
c0743f898a Allow for linebreaks in function calls and definitions and yeild/signal.
(Plus maybe a few other things)
2017-01-10 17:08:50 +01:00
Pedro J. Estébanez
8589a1b117 Fix uniforms with the same name shadowing others
Follow-up of #7344
2017-01-10 17:05:31 +01:00
Rémi Verschelde
40de567297 classref: Sync with current code 2017-01-08 12:36:38 +01:00
Emmanuel Leblond
1e646e2797 Fix codeblock tag in classes.xml for EditorSettings
(cherry picked from commit 28d7486267)
2017-01-08 12:35:02 +01:00
Rémi Verschelde
4a7d5f7b0e i18n: Sync translations with Weblate
Adds 100% complete Bengali translation.
2017-01-08 12:16:19 +01:00
Rémi Verschelde
a86dae5761 Merge pull request #7141 from Faless/2.1.x-ipv6
Cherry pick IPv6 patches to 2.1.x
2017-01-04 08:38:28 +01:00
Fabio Alessandrelli
7a77fd1cd5 Expose HTTP classes' set_ip_type to scripting
(cherry picked from commit d194e1c48e)
2017-01-04 00:46:33 +01:00
Fabio Alessandrelli
ac9f0aea1a Remove old unused AI_V4MAPPED flag to getaddrinfo
(cherry picked from commit de23ce11b5)
2017-01-04 00:46:33 +01:00
Fabio Alessandrelli
3bb1709fd7 Separate hostname resolve cache based on ip_type
(cherry picked from commit c1c1ec690e)
2017-01-04 00:46:33 +01:00
Fabio Alessandrelli
00fdcf3cd0 IP_Address now handle IPv4 and IPv6 transparently
IP_Address changes:
- Converts to and from String transparently while handling IPv4 as IPv6
  mapped (::ffff:[IP]) address internally.
- Completely remove AddrType enum.
- Setting/Getting of ip array is now only possible through dedicated functions
  (ie. set_ipv4, get_ipv4, set_ipv6, get_ipv6)
- Add function to know if the address is a valid IPv4 (for IP implementation and enet)

(cherry picked from commit 1aff508dd9)
2017-01-04 00:46:33 +01:00
Fabio Alessandrelli
7ef71b9013 Allow setting ip_type for TCP/UDP and HTTP classes
(cherry picked from commit a77a0118f6)
2017-01-04 00:46:33 +01:00
Fabio Alessandrelli
e8a6cbc897 Migrate int.IP_TYPE_ constants to IP.TYPE_
(cherry picked from commit c18c5013f8)
2017-01-04 00:46:32 +01:00
Fabio Alessandrelli
47ae6c6507 Move V6ONLY flag selection inside helpers
(cherry picked from commit 4d90a4fcd5)
2017-01-04 00:46:32 +01:00
Fabio Alessandrelli
5e79ac72b7 Automatically map IPv4 address to IPv6 when needed
(cherry picked from commit 9200da58e4)
2017-01-04 00:46:32 +01:00
Fabio Alessandrelli
a46a643f90 Use an instance variable for ip_type in raw sockets
PacketPeerUDP/StreamPeerTCP/TCP_Server now uses an instance variable
to store the selected ip_type (IPv4/IPv6/ANY, where ANY = dual stack).
All calls to resolve addresses, sending/receving data, connecting/listening
will use that socket type.

(cherry picked from commit 95bdd97768)
2017-01-04 00:46:32 +01:00
Fabio Alessandrelli
c030e602e5 Properly handle tcp connection failure
(cherry picked from commit 4f07b595a1)
2017-01-04 00:46:32 +01:00
Fabio Alessandrelli
19b31297ec Fix _set_ip_addr_port not setting the address.
(cherry picked from commit cdc1ca0f13)
2017-01-04 00:46:32 +01:00
Fabio Alessandrelli
4635671de5 Fix getaddrinfo failing on android
(cherry picked from commit 311f1f165b)
2017-01-04 00:46:32 +01:00
Rémi Verschelde
8f23be8752 Merge pull request #7344 from RandomShaper/fix-uniform-reuse-2.1
Fix error when fragment and lighting code share an uniform
2016-12-23 15:57:31 +01:00
Pedro J. Estébanez
490f51a202 Fix error when fragment and lighting code share an uniform 2016-12-21 02:24:47 +01:00
Fabio Alessandrelli
1a7f14b206 [IPv6] Fix windows build script (link to ws2_32) 2016-12-11 18:12:46 +01:00
Fabio Alessandrelli
e1dfaaf786 Define IPV6_V6ONLY flag if not defined on windows (old mingw versions)
(cherry picked from commit bdc7ca84ca)
2016-12-11 18:12:46 +01:00
Fabio Alessandrelli
3f6fe2f3f1 Update docs to IPv6
(cherry picked from commit 7f42da0330)
2016-12-11 18:12:46 +01:00
Fabio Alessandrelli
2fff8e8cde Set proper ip_type default for listen() and resolve_hostname()
(cherry picked from commit 7eef15b734)
2016-12-11 18:12:46 +01:00
Fabio Alessandrelli
754e9aa60a TCP/UDP Listen sockets can now be set to IPv6 only
(cherry picked from commit eb27e993f0)
2016-12-11 18:12:46 +01:00
Fabio Alessandrelli
a2048efd72 Add optional IP type param in TCP/UDP connect/set_send_address
(cherry picked from commit 2f1c859272)
2016-12-11 18:12:45 +01:00
Fabio Alessandrelli
70a6791150 Fix windows debugger connection problems.
Unify network socket creation between platform.
Ensure IPV6_V6ONLY flag is not set on sockets (allow IPv4 connection in IPv6 socket, dual-stack).

(cherry picked from commit 812908e236)
2016-12-11 18:12:45 +01:00
Fabio Alessandrelli
6e0de0cce8 TCPServer listen now default to IP type ANY (v6 socket with v4 support)
(cherry picked from commit ee69bd81cf)
2016-12-11 18:12:45 +01:00
Fabio Alessandrelli
04def2161e Fix PacketPeerUDP get_packet_port()
Properly convert port field from network to system ordering on incoming packets.

(cherry picked from commit 25e29972a9)
2016-12-11 18:12:45 +01:00
Fabio Alessandrelli
b3443fd848 Pass correct address size (ipv4,ipv6) to socket connect, bind, sendto
The address size passed to network system calls now reflects the the actual IP type (v4 or v6).
Fix Windows and OSX ipv6 sockets

(cherry picked from commit 80e911647c)
2016-12-11 12:35:06 +01:00
Ariel Manzur
5546929712 added implementation of is_valid_ip_address()
(cherry picked from commit a3131a6b5b)
2016-12-11 12:35:06 +01:00
Ariel Manzur
d8b0070b8c added windows support for ipv6, cleaned up unix code
(cherry picked from commit 672225b710)
2016-12-11 12:35:06 +01:00
Ariel Manzur
904285f4b4 address type for http client
(cherry picked from commit 1c2ac490cf)
2016-12-11 12:35:06 +01:00
Ariel Manzur
53fea7f196 fixed some byte order and parsing problems
(cherry picked from commit 1d45f35a4a)
2016-12-11 12:35:06 +01:00
Ariel Manzur
fd1022fd29 adding ipv6
(cherry picked from commit 887a897c02)
2016-12-11 12:35:06 +01:00
Rémi Verschelde
24a440a34f Merge pull request #7239 from eska014/2.1-asmjs
Backport web export changes for 2.1
2016-12-08 07:46:37 +01:00
eska
5ede1a1226 Emit asm.js code into a dedicated file for asm.js export
This helps prevent browser lockups during start-up at the cost of having
to distribute an extra file.
2016-12-04 02:52:14 +01:00
eska
17422f1f86 Add fullscreen features in web export
- Implement fullscreen control, get_window_size, get_screen_size
 - Fix fullscreen resolution
2016-12-04 02:52:14 +01:00
eska
49e22aa83f Fix some mouse bugs in WebAssembly/asm.js
- Emit mouse wheel release events
 - Set button masks, fixes #5092
2016-12-03 15:33:59 +01:00
eska
6d86a63648 OS additions and fixes for WebAssembly/asm.js
- Implement alert, shell_open, set_window_title
 - Add locale lookup, fixes #2477
 - Print without color control sequences
 - Move get_executable_path implementation to OS_JavaScript
2016-12-03 15:33:32 +01:00
Rémi Verschelde
a3582fa3cb png: Allow building shared freetype with bundled libpng
This was the behaviour when building Godot 2.1, which allows to build against
Ubuntu 12.04 and its freetype that links old libpng12, while still bundling
libpng16.

(cherry picked from commit 4965ddfaa1)
2016-11-19 14:09:12 +01:00
Rémi Verschelde
326978dcce Revert "libpng: Fix erroneously linking against libpng12 on old distros"
This reverts commits 5fa1bb331a
and ec4be71fad.

Looks like Debian/Ubuntu are not even shipping libpng16 nowadays in their
stable releases, we'll have to go back to statically linking our own
libpng16 to wait for them to stop being 5 years behind everybody.

(cherry picked from commit c32766a482)
2016-11-19 13:40:53 +01:00
Rémi Verschelde
76233a3022 libpng: Same fix as previous commit for server platform
(cherry picked from commit ec4be71fad)
2016-11-19 13:26:30 +01:00
Andreas Haas
ed2c369785 Fix Script Editor drawing over Dialogs.
Resets the z-index when focus is lost and the completion is shown.

Fixes #6769

(cherry picked from commit f73b501d6f)
2016-11-19 13:04:02 +01:00
Rémi Verschelde
220bcbf7c0 libpng: Fix erroneously linking against libpng12 on old distros
This bit us for 2.1.1 binaries built on Ubuntu 12.04 LTS where
libpng.pc apparently prioritizes libpng12.

(cherry picked from commit 5fa1bb331a)
2016-11-19 13:00:17 +01:00
Rémi Verschelde
3e2247ca53 Release 2.1.1-stable 2016-11-15 09:14:21 +01:00
Rémi Verschelde
bf3cf5505e classref: Sync with current source 2016-11-15 09:14:02 +01:00
Rémi Verschelde
bcc887bbe5 i18n: Sync translations with Weblate and update template 2016-11-15 09:10:37 +01:00
Rémi Verschelde
9b32df9cab i18n: Remove translations below 20% completion
They are of course kept in master to be synced in Weblate.
2016-11-15 09:07:53 +01:00
Ben Hickling
601f056b6f Added snapping to 3D path handles to bring it in line with its 2D counterpart
(cherry picked from commit 4d1acab79b)
2016-11-15 08:44:53 +01:00
volzhs
14b46c4263 Check entered and trimmed path when create, import, install project
(cherry picked from commit 2d9e89ea2a)
2016-11-15 08:44:53 +01:00
khairul169
8a813e2a1e Uncomment debug properties of HTTP Request
(cherry picked from commit 6a7aebdf6c)
2016-11-15 08:44:53 +01:00
volzhs
679e9f413c Fix crash when select target path on import 3d scene window
(cherry picked from commit b0cf201ea3)
2016-11-15 08:44:53 +01:00
Pedro J. Estébanez
19ce11b908 Update/fix Android build
Fix wrong path for 32-bit Windows, which fixes #7084
Exclude 32-bit Windows from multi-threaded linking because it's not supported by the NDK
Remove 32-bit Linux as there is no NDK variant for it
(cherry picked from commit 5a26459c06)
2016-11-15 08:44:53 +01:00
eska
28944e95e7 Clarify a NULL comparison
'TreeItem::get_children()' does not return the child count, but rather
a pointer to the children.

This comparison caused an error during WebAssembly builds using the
LLVM backend path.

(cherry picked from commit 31f929caa2)
2016-11-15 08:37:53 +01:00
volzhs
2d6dabc68e Prevent to select children if selection lock or instanced scene
Fix #7086

(cherry picked from commit c3f4d676c0)
2016-11-15 08:37:48 +01:00
volzhs
9219ac7e44 Fix resetting to default value in EditorSettings
(cherry picked from commit 70cce6152d)
2016-11-15 08:36:53 +01:00
Elia Argentieri
e3dc319f78 Make the step property useful for sliders as described in #5773
(cherry picked from commit 0955371447)
2016-11-15 08:36:18 +01:00
Pedro J. Estébanez
221346521c Make Android export quicker (especially on Windows)
(cherry picked from commit 56721e5d9d)
2016-11-15 08:35:15 +01:00
Pawel Kowal
f1c2d70f1a Export immediately if only one device present
(cherry picked from commit 938f9388dd)
2016-11-15 08:35:01 +01:00
volzhs
3e127ce3fd Fix Directory.dir_exist/get_current_dir for 'res://' on Android
Fix #7014

(cherry picked from commit 8d454ed9a7)
2016-11-15 08:34:51 +01:00
ISylvox
0413d85add vsnc --> vsync
(cherry picked from commit b5c383fd61)
2016-11-15 08:34:43 +01:00
volzhs
7d09222b37 Set project name as directory name instead of '.'
(cherry picked from commit 571f33f863)
2016-11-15 08:34:38 +01:00
volzhs
dd8b87f58e Select newly created or imported project automatically
(cherry picked from commit b8f80e9450)
2016-11-15 08:34:32 +01:00
volzhs
36a4c54593 Fix Label valign position
Fix #7055

(cherry picked from commit c0e87f2a24)
2016-11-15 08:34:26 +01:00
SPTelur
51fe9fc132 Some missing License notice has been added
(cherry picked from commit df737ebb46)
2016-11-15 08:34:16 +01:00
Paulb23
9e1e5daddf Caret blink will no longer cause redraw without focus, issue 6167
(cherry picked from commit 7b036a94bf)
2016-11-15 08:34:01 +01:00
DTV96Calibre
bc8dabf3d2 Fixed minor typo
(cherry picked from commit 37098419c5)
2016-11-15 08:30:35 +01:00
Pedro J. Estébanez
fada9d7a8e Clean/fix triangulation internals
Drop unused variable
Remove commented-out code
Fix leak by using Vector instead of raw memory

(cherry picked from commit 0e1972aa51)
2016-11-15 08:30:09 +01:00
volzhs
82b458f160 Fix updating value of SpinBox with prefix
(cherry picked from commit 80b6507071)
2016-11-15 08:30:02 +01:00
volzhs
64f38490df Prevent to make UndoRedo for duplicate if no selected node
(cherry picked from commit d82928eb49)
2016-11-15 08:29:56 +01:00
ScotFlux
c282ac8ec7 fix a tiny typo
(cherry picked from commit 8639d6e806)
2016-11-15 08:29:30 +01:00
Rémi Verschelde
210618c5e2 Rewrite the README to be more descriptive
(cherry picked from commit ab9fa604d1)
2016-11-15 08:29:23 +01:00
volzhs
2b00fdc679 Fix wrong number for ERR_* on comment
(cherry picked from commit 42f2380190)
2016-11-15 08:29:09 +01:00
Tim Roes
d7ec768805 Fix typos and missing newlines in --help
(cherry picked from commit c34aa331ec)
2016-11-15 08:28:58 +01:00
Keetz
86c6aabf27 Fix scene tree drag & drop places node as child (#6912)
(cherry picked from commit 2afcbc4b1f)
2016-11-15 08:28:52 +01:00
Saracen
e5f210693c Fixed flag for importing animation and skipping value tracks.
(cherry picked from commit 0063471edd)
2016-11-15 08:28:26 +01:00
Ignacio Etcheverry
7e3360ae01 Keep groups when replacing nodes
(cherry picked from commit 305956bf70)
2016-11-15 08:28:11 +01:00
Ariel Manzur
67f65f6639 memory ops implemented as OS functions by default 2016-11-08 19:04:56 -03:00
Ariel Manzur
dbca4ee3fe adding get_stored_values method
changed order name
2016-11-08 18:14:10 -03:00
Rémi Verschelde
cd828bd5fc server: Allow building against system libraries
(cherry picked from commit 5e360fe178)
2016-11-03 22:55:24 +01:00
Rémi Verschelde
da4a870bc4 opus: Move public headers to match system install
(cherry picked from commit 611a94e3a6)
2016-11-03 21:22:56 +01:00
Rémi Verschelde
ce54b6ea8b scons: Reorder options for clarity
Also prefix all thirdparty-related toggles with `builtin`.

(cherry picked from commit cc95d4448c)
2016-11-03 08:41:10 +01:00
Rémi Verschelde
5ee9a9962f libpng: Update to upstream 1.6.26
(cherry picked from commit 7504a85e5a)
2016-11-03 08:34:19 +01:00
Pedro J. Estébanez
f629b1fd3e Improve Android build (Clang + tidyness)
(cherry picked from commit b18ff942be)
2016-11-02 22:34:17 +01:00
Rémi Verschelde
eaf803f71e style: Various other PEP8 fixes in Python files
Done with `autopep8 --select=E7`, fixes:

- E701 - Put colon-separated compound statement on separate lines.
- E702 - Put semicolon-separated compound statement on separate lines.
- E703 - Put semicolon-separated compound statement on separate lines.
- E711 - Fix comparison with None.
- E712 - Fix (trivial case of) comparison with boolean.
- E713 - Fix (trivial case of) non-membership check.
- E721 - Fix various deprecated code (via lib2to3).
2016-11-02 22:30:34 +01:00
Rémi Verschelde
a7389217f8 style: Fix PEP8 blank lines issues in Python files
Done with `autopep8 --select=E3,W3`, fixes:

- E301 - Add missing blank line.
- E302 - Add missing 2 blank lines.
- E303 - Remove extra blank lines.
- E304 - Remove blank line following function decorator.
- E309 - Add missing blank line.
- W391 - Remove trailing blank lines.
2016-11-02 22:29:36 +01:00
Rémi Verschelde
e259bf8bbb style: Fix PEP8 whitespace issues in Python files
Done with `autopep8 --select=E2,W2`, fixes:

- E201 - Remove extraneous whitespace.
- E202 - Remove extraneous whitespace.
- E203 - Remove extraneous whitespace.
- E211 - Remove extraneous whitespace.
- E221 - Fix extraneous whitespace around keywords.
- E222 - Fix extraneous whitespace around keywords.
- E223 - Fix extraneous whitespace around keywords.
- E224 - Remove extraneous whitespace around operator.
- E225 - Fix missing whitespace around operator.
- E226 - Fix missing whitespace around operator.
- E227 - Fix missing whitespace around operator.
- E228 - Fix missing whitespace around operator.
- E231 - Add missing whitespace.
- E231 - Fix various deprecated code (via lib2to3).
- E241 - Fix extraneous whitespace around keywords.
- E242 - Remove extraneous whitespace around operator.
- E251 - Remove whitespace around parameter '=' sign.
- E261 - Fix spacing after comment hash.
- E262 - Fix spacing after comment hash.
- E265 - Format block comments.
- E271 - Fix extraneous whitespace around keywords.
- E272 - Fix extraneous whitespace around keywords.
- E273 - Fix extraneous whitespace around keywords.
- E274 - Fix extraneous whitespace around keywords.
- W291 - Remove trailing whitespace.
- W293 - Remove trailing whitespace.
2016-11-02 22:28:28 +01:00
Rémi Verschelde
561c1f17a1 style: Start applying PEP8 to Python files, indentation issues
Done with `autopep8 --select=E1`, fixes:

- E101 - Reindent all lines.
- E112 - Fix under-indented comments.
- E113 - Fix over-indented comments.
- E115 - Fix under-indented comments.
- E116 - Fix over-indented comments.
- E121 - Fix a badly indented line.
- E122 - Fix a badly indented line.
- E123 - Fix a badly indented line.
- E124 - Fix a badly indented line.
- E125 - Fix indentation undistinguish from the next logical line.
- E126 - Fix a badly indented line.
- E127 - Fix a badly indented line.
- E128 - Fix a badly indented line.
- E129 - Fix a badly indented line.
2016-11-02 22:26:55 +01:00
volzhs
7c92b401f1 Fix to fit stylebox with ItemList
(cherry picked from commit 4c9b00b508)
2016-11-02 22:18:34 +01:00
m4nu3lf
d44e6ea268 Fixed Mix nodes in Animation Tree Player
(cherry picked from commit 40ba6d328b)
2016-11-02 22:18:28 +01:00
Rémi Verschelde
1185da656f Merge pull request #6988 from RandomShaper/2.1
Fix shader tokenizer/compiler reporting wrong error location (2.1)
2016-11-02 22:10:00 +01:00
Rémi Verschelde
c78aef5812 Fix usage of 3.0 naming API in 1038c1f8 2016-10-31 08:39:45 +01:00
volzhs
91af714d39 Fix memory leak with drag & drop on 2D viewport
(cherry picked from commit a7d492eb53)
2016-10-31 07:55:23 +01:00
Andreas Haas
5033fc92f4 Ability to drag script files from Filesystem dock to SceneTree dock.
Allows to attach scripts by dragging them onto the target Node.

(cherry picked from commit a3944e66da)
2016-10-31 07:55:03 +01:00
volzhs
1038c1f856 Improve drag and drop on 2D viewport
(cherry picked from commit eed9179ea3)
2016-10-31 07:53:31 +01:00
Rémi Verschelde
8087be05c7 scons: msvc_is_detected not available in 2.1 2016-10-31 07:52:40 +01:00
Rémi Verschelde
a20da0c048 classref: Sync with current sources 2016-10-31 00:15:54 +01:00
volzhs
d67bbd183e Fix p_index out of size error when closing script
(cherry picked from commit 707185d9d8)
2016-10-31 00:07:56 +01:00
volzhs
647b287a1e Fix Accept/ConfirmationDialog UI broken
(cherry picked from commit 8d5644c4b2)
2016-10-31 00:07:47 +01:00
volzhs
91df1ebff6 Revert "Place child control under label in AcceptDialog."
This reverts commit 3ef2722904.

(cherry picked from commit 3f15a65307)
2016-10-31 00:07:40 +01:00
Rémi Verschelde
62d1e39113 scons: Move lib splitting method to methods.py
Apparently it might still be necessary for some console ports.

(cherry picked from commit e34a5324c8)
2016-10-31 00:07:29 +01:00
Pedro J. Estébanez
b492dd78bd Adopt simpler strategy for big libs on Windows
(cherry picked from commit 51ad1c1668)
2016-10-31 00:05:42 +01:00
rdb
a27aee241c Add "Never" underline mode to LinkButton
(cherry picked from commit d517bc908f)
2016-10-31 00:05:32 +01:00
Damon
e3be51f87c Fix locale for macOS-style locales
(cherry picked from commit 1e7f078ce9)
2016-10-31 00:04:39 +01:00
Damon Myers
68b6b50d28 Change set_locale to fallback to the global language (#6910)
(cherry picked from commit 470ead74db)
2016-10-31 00:04:26 +01:00
volzhs
06c47e6f8a Remove dead code in FileSystemDock
(cherry picked from commit 9605a1d0da)
2016-10-31 00:02:12 +01:00
volzhs
e56961f58b Fix comparison bug with InputEvent
(cherry picked from commit b76a0ca40c)
2016-10-31 00:02:04 +01:00
Błażej Szczygieł
b0013f32bf "CCFLAGS" are for C and C++ compiler
(cherry picked from commit ace18d28d2)
2016-10-31 00:01:41 +01:00
Henrique Lacreta Alves
58daf901f9 Prevent unwanted script editor input on game crash
Fixes #6530.
(cherry picked from commit 853d1ce9f3)
2016-10-31 00:01:11 +01:00
Pedro J. Estébanez
887b1de1db Add/expose VisualServer::get_default_clear_color()
(cherry picked from commit 753ba67d65)
2016-10-31 00:00:55 +01:00
yg2f
caf42f77d2 Fixes #6487, GDscript compiler ignores OPCODE_LINE and OPCODE_BREAKPOINT in Release mode
When godot is in release mode, GDscript compiler does not generate
bytecodes for OPCODE_LINE and OPCODE_BREAKPOINT anymore.

This optimizes GDscript execution speed when the script contains a lot
of comments in blocs executed in loops.

Fixes #6487

(cherry picked from commit 217e09c79d)
2016-10-31 00:00:46 +01:00
Karol Walasek
9f9d1eed7b Added general notes on RayCast[2D] updating behaviour and force_raycast_update()
(cherry picked from commit 8d57640d37)
2016-10-31 00:00:34 +01:00
Karol Walasek
0af331d1c0 Added force_raycast_update GDScript method for RayCast[2D]
(cherry picked from commit 7494a8c3c6)
2016-10-31 00:00:23 +01:00
George Marques
7a17d72e84 Fix extraneous NULL character on HTML export
Fix #2801

(cherry picked from commit 604ddd691c)
2016-10-30 23:58:41 +01:00
George Marques
52bf8bd168 Fix the hiding of mouse cursor before interaction
Fix part of #6633

(cherry picked from commit 414d58e6c0)
2016-10-30 23:58:32 +01:00
George Marques
f3b42e049d Fix output binary paths for VS project generation
(cherry picked from commit c8093678a0)
2016-10-30 23:57:54 +01:00
Pedro J. Estébanez
a130520a7c Fix shader tokenizer/compiler reporting wrong error location
Raname shader tokenizer methods for clarity
2016-10-30 22:09:23 +01:00
Błażej Szczygieł
85a7105345 SCons: Use colored output if available, change "colored"->"verbose"
(cherry picked from commit 2bf4553fe0)
2016-10-30 14:51:34 +01:00
Błażej Szczygieł
dcd4b80c13 Disable asserts in release mode
(cherry picked from commit 639ea563e0)
2016-10-30 14:51:34 +01:00
Rémi Verschelde
5a49e45d21 SCsub: Add python shebang as a hint for syntax highlighting
Also switch existing shebangs to "better" /usr/bin/env python.

(cherry picked from commit fc8ccd5b8c)
2016-10-30 14:51:34 +01:00
Błażej Szczygieł
7143401e25 Theora: Don't compile unnecessary files, rename "x86_opt_*"
(cherry picked from commit 4ffa8f224d)
2016-10-30 14:51:34 +01:00
Rémi Verschelde
f4414e3e03 png: Try to fix neon issue on iphone armv7
(cherry picked from commit e57042e8a9)
2016-10-30 14:51:34 +01:00
Rémi Verschelde
aa1367595e drivers: Refactor SCsub and drop redundant env_drivers clone
The reordering of the SConscript includes allows to ensure that
stuff like the builtin zlib headers will be available for libpng.

Also moved glew back into global env, otherwise windows seems
not to find it... Kind of shooting in the dark with this multi-env
setup.

(cherry picked from commit 248bc9159c)
2016-10-30 14:51:34 +01:00
Rémi Verschelde
d96842b80e freetype: Make it a module and split thirdparty library
Comment out the weird workaround for building on Windows at it might
not be needed anymore. Testing needed to confirm.

(cherry picked from commit edbc0c0d0b)
2016-10-30 14:51:33 +01:00
Rémi Verschelde
8bf3bc3449 chibi: Move to a module
(cherry picked from commit e6dc51a0f7)
2016-10-30 14:51:33 +01:00
Rémi Verschelde
f1bd2f6f56 zlib: Split thirdparty files, simplify scons option
(cherry picked from commit cbf52606f4)
2016-10-30 14:51:33 +01:00
Rémi Verschelde
e04ec9565b glew: Split thirdparty files and isolate env
Not fully happy about the way this one interacts with the various
platforms. Maybe the platform_config.h should be generated by the
SCsub instead of passing a define just to know where is the header.

(cherry picked from commit 36738ddda4)
2016-10-30 14:51:33 +01:00
Rémi Verschelde
8263fca121 squish: Update to upstream 1.14
Sources are untouched, tarball from https://sourceforge.net/projects/libsquish

(cherry picked from commit 249836e530)
2016-10-30 14:51:33 +01:00
Rémi Verschelde
1022705707 squish: Move to a module and split thirdparty lib
(cherry picked from commit 8311a78df5)
2016-10-30 14:51:33 +01:00
Rémi Verschelde
4ff4177acc rtaudio: Split thirdparty files
(cherry picked from commit 8981ff8a84)
2016-10-30 14:51:33 +01:00
Rémi Verschelde
c8a97c3678 mpc: Move to a module and split thirdparty libmpcdec
(cherry picked from commit 5c12c9e69b)
2016-10-30 14:51:33 +01:00
Rémi Verschelde
82e8721715 theora: Move to a module and split thirdparty lib
Same rationale as the previous commits.

(cherry picked from commit cfcc8a20e8)
2016-10-30 14:51:32 +01:00
Rémi Verschelde
bfea3f1d9a modules: Clone env in each module
This allows to pass include paths and flags only to a given thirdparty
library, thus preventing conflicts between their files (e.g. between
opus and openssl which both provide modes.h.

This also has the nice effect of making the compilation command smaller
for each module as it no longer related to all other modules, only the
final linking brings them together.

This however requires adding manually the ogg include path in opus
and vorbis when building against the builtin ogg, since it is no longer
in the global env.

Also simplified template 'thirdparty_<module>_sources' to
'thirdparty_sources'.

"Core" modules like cscript, gdscript, gridmap, ik and virtual_script
still use the main env_modules, but it could be changed if need be.

(cherry picked from commit da09c6131b)

Obviously removed the parts about enet and visual_script.
2016-10-30 14:51:32 +01:00
Rémi Verschelde
4cd640f684 openssl: Move to a module and split thirdparty lib
Same rationale as the previous commits.

(cherry picked from commit 422196759f)

Removed the winrt-specific parts.
2016-10-30 14:51:32 +01:00
Rémi Verschelde
995dcb610c ogg/vorbis/opus/speex: Make them modules and unbundle thirdparty libs
Took the opportunity to undo the Godot changed made to the
opus source. The opus module should eventually be built in its
own environment to avoid polluting others with too many include
dirs and defines.

TODO: Fix the platform/ stuff for opus.
(cherry picked from commit d9a291f641)

speex module was only added while cherry-picking, as speex is removed
in the master branch but we don't want to break compatibility in 2.1.x.
Unbundling wasn't done as the module uses the internal speex_free,
so it would require some more work.
2016-10-30 14:51:31 +01:00
Rémi Verschelde
55414bc573 webp: Make it a module and unbundle libwebp thirdparty files
Note that there are two Godot-specific changes made to libwebp
for the javascript/HTML5 platform. They are documented in the
README.md.

(cherry picked from commit ee3cf211c6)
2016-10-30 14:51:30 +01:00
Rémi Verschelde
819ccdd340 dds/etc1/pbm/pvr: Make those modules and split thirdparty files
They are not particularly packaged in Linux distros so we do not
facilitate unbundling via SCons. There could be done if/when there
is interest.

Also s/pnm/pbm/, long-lived typo :)

(cherry picked from commit b1e8889d96)
2016-10-30 14:51:30 +01:00
Rémi Verschelde
ea1e180e4a jpg: Make it a module and split jpgd thirdparty files
Similar rationale as in previous commit.

(cherry picked from commit 16ba665db6)
2016-10-30 14:51:30 +01:00
Rémi Verschelde
575e986bde png: Split library to thirdparty dir and allow unbundling
Uses the new structure agreed upon in #6157, but the thirdparty/ folder
does not behave following a logic similar to that of modules/ yet.

The png driver can't be moved to a module as discussed in #6157, as it's
required by core together with a few other ImageLoader implementations
(see drivers/register_driver_types.cpp:register_core_driver_types())

Dropped the possibility to disable PNG support, it's a core component
of Godot.

(cherry picked from commit 5fef84a135)
2016-10-30 14:51:30 +01:00
Rémi Verschelde
846db09038 Drop nedmalloc which is apparently not used anymore
(cherry picked from commit f63bf12193)
2016-10-30 14:51:30 +01:00
Zher Huei Lee
fae2863a5e Added support for tooltips in ButtonArray. Fixes #6597
(cherry picked from commit 38caa4ef91)
2016-10-30 14:51:30 +01:00
Rémi Verschelde
56b03e7208 Merge pull request #6877 from ranmaru90/2.1
Fixed tiny error in detect.py causing compilation for Android to fail.
2016-10-22 13:03:35 +02:00
Randy Tan Shaoxian
c9d7f77c6f Fixed tiny error in detect.py causing compilation for Android to fail. 2016-10-20 21:17:21 +08:00
Rémi Verschelde
14e45a55d4 Revert "Tween reset/stop/resume/remove for all object properties at once"
This reverts commit 6fc894d652.
It caused a regression, cf. #6863.
2016-10-18 21:43:46 +02:00
Juan Linietsky
7d25d20861 Added a generic AStar implementation to Godot.
It's pretty fast, use it for games where Navigation does not cut it.

(cherry picked from commit 827a9aa829)
2016-10-18 18:35:44 +02:00
Andreas Haas
e88a540b91 osx: Support gamepad input.
Fixes #3881

Vibration support is not optimal yet as it doesn't try to emulate the "weak" and "strong" motor strength,
but just takes the parameter with the highest value for the vibration gain.

(cherry picked from commit 8c886b9d7a)
2016-10-18 18:34:16 +02:00
Rémi Verschelde
2287bac8f7 classref: Sync with current source 2016-10-17 21:07:01 +02:00
volzhs
00b0f3dfde Fix crash when using Directory.dir_exists(path) on Android
(cherry picked from commit 4a57821349)
2016-10-17 20:50:57 +02:00
Andreas Haas
64b083b496 Allow whitespace in Gamepad mappings.
Previously, mappings that contained whitespace (most likely after a comma seperator) would not parse
correctly.
Consider the following mapping as an example:

"_test_guid_, test controller, a:b0, b:b1, leftx:a0 ,"

(cherry picked from commit fa502b7ccc)
2016-10-17 20:50:43 +02:00
volzhs
9b71cae50f Add option for root node name on Import 3D scene window
(cherry picked from commit dd04ac7ba9)
2016-10-17 20:50:20 +02:00
Karol Walasek
8a8ace8fa0 Fixed Particle2D docs - radians to degrees for some params
(cherry picked from commit 5687fa4709)
2016-10-17 20:49:52 +02:00
Pedro J. Estébanez
2261c65f19 Adapt overlooked instances of zero-based column numbers
(cherry picked from commit 1b3dcac281)
2016-10-17 20:49:28 +02:00
Andreas Haas
a418304def Only show AnimationEditor automatically when an Animplayer is selected.
Previous behaviour was to show it when an AnimationPlayer has been detected in the scene, now you actually have to select it.
Fixes #6213

(cherry picked from commit 86fd40b06c)
2016-10-17 20:49:18 +02:00
Fabio Alessandrelli
ea48675ffa Properly handle absolute paths in Globals::localize_path
This give a proper fix for #4280 - #3106 , allowing absolute paths
that starts from the file system, not the resource folder

(cherry picked from commit 2f2cea070e)
2016-10-17 20:49:12 +02:00
Fabio Alessandrelli
d5ee98bb2c Revert "Add warning when (pre)loading paths with leading / (#4280 - #3106)"
Also closes: #6801

This reverts commit e59820ac94.

(cherry picked from commit 11349a786b)
2016-10-17 20:48:52 +02:00
volzhs
728ac94313 Add "button_selected" signal to ButtonGroup
(cherry picked from commit 870ed6f2fa)
2016-10-17 20:48:36 +02:00
Zher Huei Lee
a8502ae6f6 Fixes for ButtonArray
Fixed hover sometimes not resetting when mouse leaves widget.
Fixed text position not taking into account stylebox's content margins.

(cherry picked from commit f5830e0973)
2016-10-17 20:48:25 +02:00
Răzvan Cosmin Rădulescu
04255541a0 Fixes hash float negative 0 problem
Before this was giving an error:

var a = {Vector2(1, 0): 5, Vector2(-1, 0): 7}
    print(a)
    print(a[Vector2(1, 0)])
    print(a[-Vector2(1, 0)])

This simple commit fixes the issue.

(cherry picked from commit 9ad0850301)
2016-10-17 20:48:15 +02:00
Mateusz Adamczyk
17edff2f84 Possibility to write node path by hand in exported NodePath variable (#3486)
(cherry picked from commit cf4f3815b3)
2016-10-17 20:48:10 +02:00
Anthony Fieroni
b4edaa892d Correct OS architecture detection
Signed-off-by: Anthony Fieroni <bvbfan@abv.bg>
(cherry picked from commit f87e32696d)
2016-10-17 20:48:05 +02:00
volzhs
81bc271619 Replace a node with saved branch scene instance
(cherry picked from commit cc33c528eb)
2016-10-17 20:47:49 +02:00
Andreas Haas
5f540a17cc Sprite: Fix inspector not showing changes on "frame" property.
Fixes #6562

(cherry picked from commit 9d67895c7c)
2016-10-17 20:47:27 +02:00
Andreas Haas
4b6809a2b3 Refresh TextureRegionEditor when region has been changed externally.
Now the TextureRegionEditor updates when you change the region_rect either via the inspector or via
undo/redo.

Fixes #6772

(cherry picked from commit 094073e4b2)
2016-10-17 20:47:14 +02:00
Pawel Kowal
280728c0c7 New load icon, removed unused open icon
(cherry picked from commit ed1e71a77e)
2016-10-17 20:46:34 +02:00
Pawel Kowal
35cdb1a49b Fix #5959, contrasting texture for toggled button
(cherry picked from commit d3a8087659)
2016-10-17 20:46:10 +02:00
Pedro J. Estébanez
3df8f79c9f Allow step for integer properties
Small readability improvement

(cherry picked from commit 7b293aa4d4)
2016-10-17 20:44:54 +02:00
Pedro J. Estébanez
99d82f3033 Make text column numbers one-based
Make one-based the column number on the code editor

Make one-based the column number for GDScript error messages

Make one-based the column number for shader code error messages

(cherry picked from commit 2f80965845)
2016-10-17 20:44:47 +02:00
Anthony Fieroni
f250c0cf50 Button focus hovering
Signed-off-by: Anthony Fieroni bvbfan@abv.bg
(cherry picked from commit 6d21fd42d3)
2016-10-17 20:43:36 +02:00
Ignacio Etcheverry
55a5631986 Bindings: Fix missing default value
(cherry picked from commit 068b58b3ce)
2016-10-17 20:43:25 +02:00
George Marques
8cb09bf9d0 Fix Android build detection on Windows
(cherry picked from commit 4bdbafabce)
2016-10-17 20:43:03 +02:00
Mateusz Adamczyk
58e2652f94 Place child control under label in AcceptDialog.
Fixes #6199.

(cherry picked from commit 3ef2722904)
2016-10-17 20:42:51 +02:00
Rémi Verschelde
3f941faf4d i18n: Sync translations from Weblate and merge with current code 2016-10-09 18:23:26 +02:00
Rémi Verschelde
b3bf3c392a i18n: Fix string that broke msgmerge
(cherry picked from commit 2fb5a00305)
2016-10-09 18:21:59 +02:00
Rémi Verschelde
c757787fed classref: Sync with current 2.1 branch 2016-10-09 17:50:09 +02:00
J08nY
1ae1deabfa editor_node: add an option to stop the update spinner from spinning, fixes #6653
(cherry picked from commit 4527fbcfa1)
2016-10-09 17:41:04 +02:00
Pedro J. Estébanez
22680a30f1 Fix reparent undo not renaming back
(cherry picked from commit 88a32c11f1)
2016-10-09 17:40:49 +02:00
Mateusz Adamczyk
ce1138cb02 Added simple check to viewport, if matrix32 is invesile (https://github.com/godotengine/godot/issues/6296).
(cherry picked from commit 8671836b76)
2016-10-09 17:40:37 +02:00
Bojidar Marinov
a139c7afe6 Attempt to fix travis builds for android
Using travis_wait command
(cherry picked from commit f73f554cc0)
2016-10-09 17:40:25 +02:00
Fabio Alessandrelli
e51cd3d454 Throw an error when exporting a resource class
"export var tex = Texture"
will now throw an error to avoid crashing the editor:
"Exported constant not a type or resource"

Fixes #6719 . Closes #6729

(cherry picked from commit ee7df2c89a)
2016-10-09 17:40:19 +02:00
Andreas Haas
a7d6894a9f Project manager: grab focus on ok button after path selection.
Slight usability improvement: grabs focus on the Import/Create button after engine.cfg/path selection.
So then I can just press enter to create the project ^^

(cherry picked from commit 36d2dd5318)
2016-10-09 17:40:10 +02:00
Răzvan Cosmin Rădulescu
6775cce469 fixes #6695 - MultiNodeEdit edit path in exported NodePath
(cherry picked from commit ced8fb4806)
2016-10-09 17:40:03 +02:00
Andreas Haas
9e20b39b3d Fix code completion drawing under other gui elements.
Raises the z-index of the Script editor when the completion is shown.

fixes #1257
fixes #6690

(cherry picked from commit 6dfa405eac)
2016-10-09 17:39:56 +02:00
Andreas Haas
0462bf01a2 Prevent crash on focus change when no valid next control has been found.
Fixes the crash discussed in #6714.

(cherry picked from commit 8dd026e4f9)
2016-10-09 17:39:39 +02:00
Ariel Manzur
cf427eeb7a bind method canvas_item_set_sort_children_by_y
(cherry picked from commit 1f9e16119f)
2016-10-09 17:39:17 +02:00
Adham Zahran
cd03f8cce2 fix #6012 exposed setters and getters of Camera H/V offset to GDScript
(cherry picked from commit cbb0ea315b)
2016-10-09 17:39:06 +02:00
Fabio Alessandrelli
d0ff75c91c Add shortcut to reset cursor position in 3D Editor ( #166 )
The shortcut will focus the origin after you moved around with shift + mouse3.
The default shortcut is the letter "O", like "F" for focus.
This can be customized in the editor shortcuts menu.

Closes #166

(cherry picked from commit 63abe3dcd0)
2016-10-09 17:39:00 +02:00
Pedro J. Estébanez
82dfaf7af6 Fix compile flags not getting to the Android build
(cherry picked from commit 7f51bb7b1c)
2016-10-09 17:34:36 +02:00
Pedro J. Estébanez
c0ba08b8d5 Add editor_only param to Light2D
(cherry picked from commit 34c02fad5a)
2016-10-09 17:34:29 +02:00
Fabio Alessandrelli
ba095b8dcc Add warning when (pre)loading paths with leading / (#4280 - #3106)
(cherry picked from commit e59820ac94)
2016-10-09 17:34:23 +02:00
Andreas Haas
9593863a92 ConnectionDialog: Don't allow connecting to a Node without a script if target method is invalid.
Shows a warning now.
Fixes #6656

(cherry picked from commit 5b7021434f)
2016-10-09 17:34:12 +02:00
Răzvan Cosmin Rădulescu
97ebfddaaf fixes #6331, Variant::can_convert
(cherry picked from commit f2af5ab949)
2016-10-09 17:34:00 +02:00
J08nY
342b1408d5 light: respect editor_only setting in release build and dont show the light
(cherry picked from commit af35130b50)
2016-10-09 17:33:54 +02:00
Fabio Alessandrelli
359b5f3b25 Expose more 2D/3D physics options in project settings
(cherry picked from commit 1d09c27ba4)
2016-10-09 17:33:47 +02:00
J08nY
5b942f056a Vector3: added angle_to(Vector3 other)
(cherry picked from commit deb36b44d1)
2016-10-09 17:33:36 +02:00
J08nY
44ba542de6 Vector3: format properly, fix indents
(cherry picked from commit f468cfc379)
2016-10-09 17:33:30 +02:00
mookiexl
f63b338e0f Limit directional shadow draw distance, fixes #559, optimization (#1991)
* Shadow fadeout exponent hardcoded for now, should be user configurable.
* optimization - skip shadows outside visible range
(cherry picked from commit 0b12ebba11)
2016-10-09 17:33:20 +02:00
Błażej Szczygieł
13108317ae Fixes in Theora SCsub
- properly pass x86 assembly define to the compiler,
- don't compile unnecessary/encoder files.

(cherry picked from commit 75299cf334)
2016-10-09 17:33:12 +02:00
Pedro J. Estébanez
12d4d65668 Improve debug focus behavior
Fix focusing debugged game on Windows
Add re-focusing editor on continue

(cherry picked from commit 66dac878ac)
2016-10-09 17:29:59 +02:00
Fabio Alessandrelli
56dc7aa568 Properly encode InputEvent of type NONE. Fix #5987
In the editor settings you can disable default editor shortcuts.
When a default shortcut is disabled an InputEvent of type NONE must
be stored in the config file to allow the editor to remember that setting.
variant_parser.cpp was not properly encoding InputEvent of type NONE causing
the "corruption" of the editor settings file.

(cherry picked from commit 941f460384)
2016-10-09 17:29:27 +02:00
J08nY
f315d352ec PCKPacker: moved from tools into core, fixes #4129
(cherry picked from commit b1fba2e013)
2016-10-09 17:28:11 +02:00
J08nY
ef0bcc7e20 PopupMenu: added toggle_item_checked and exposed set_item_tooltip and get_item_tooltip
(cherry picked from commit 6b283ae293)
2016-10-09 17:26:14 +02:00
Karol Walasek
b2a58da321 Filled blanks and normalized documentation on RayCast[2D]
(cherry picked from commit db0a46d7f7)
2016-10-09 17:25:07 +02:00
Pedro J. Estébanez
de13e52b9b Respect texture .flags files on export
(cherry picked from commit 11cbbeb17e)
2016-10-09 17:24:10 +02:00
volzhs
73e7ccabf5 Fix typo for word_wrap
(cherry picked from commit c333659ebc)
2016-10-09 17:23:58 +02:00
volzhs
721599c797 Fix error when using 2 or more slashes on resource path
(cherry picked from commit 0866f49f4e)
2016-10-09 17:23:53 +02:00
Pawel Kowal
ab231cd3fb Fix #6480, area duplicated param
(cherry picked from commit f9a21baa26)
2016-10-09 17:23:43 +02:00
Marc Gilleron
268b3446c6 Windows: prevent huge prints from crashing the engine
(cherry picked from commit 0c09de3ef1)
2016-10-09 17:23:08 +02:00
Pawel Kowal
d7925ca09d LineEdit long indicator, fix #6624
(cherry picked from commit 3edc0a4832)
2016-10-09 17:23:02 +02:00
Błażej Szczygieł
d613952300 Don't crash when video is stopped and played again
(cherry picked from commit 5585bc1c38)
2016-10-09 17:22:54 +02:00
Victor Seiji Hariki
a3c58999e2 Now ignoring remaining collision shapes.
(cherry picked from commit e5edd50d62)
2016-10-09 17:22:48 +02:00
syskrank
4b2243f82e removed confusing "if(true)" statement with empty "else" block
(cherry picked from commit af4b0db1e4)
2016-10-09 17:22:36 +02:00
Pawel Kowal
6fc894d652 Tween reset/stop/resume/remove for all object properties at once
(cherry picked from commit acc242fd6a)
2016-10-09 17:22:16 +02:00
Andreas Haas
5adb75c2e7 Throw error when trying to emit a non-existing signal.
closes #6017

(cherry picked from commit 276087e92d)
2016-10-09 17:22:08 +02:00
Błażej Szczygieł
a827734e03 Don't crash in "_process_hdr()" if "framebuffer.luminance" is empty
If "glFramebufferTexture2D()" fails on old drivers the Vector is empty.
Don't allow to read from empty Vector (NULL pointer).

(cherry picked from commit 7b8fe97888)
2016-10-09 17:22:01 +02:00
Błażej Szczygieł
f4f5855168 Don't crach when OpenGL version is unsupported
(cherry picked from commit ca3b8deb78)
2016-10-09 17:21:48 +02:00
Błażej Szczygieł
f4da1e9ed2 Add compatibility with old OpenGL 2.1 drivers
If ARB_framebuffer_object is not supported, try to fall-back to
EXT_framebuffer_object if present.

In current version of godot, the way framebuffers are used is backward
compatible with the older EXT_framebuffer_object extension.

Fixes #6591
Done with SuperUserNameMan

(cherry picked from commit a27fafb273)
2016-10-09 17:21:41 +02:00
Emmanuel Leblond
a5fe7ffbcd Add CC parameter to allow use of custom C compiler
(cherry picked from commit cfd17de230)
2016-10-09 17:21:33 +02:00
Andreas Haas
02487a4be1 AnimationEditor: zoom using ctrl+wheel
closes #6585

(cherry picked from commit 3cce39c2d3)
2016-10-09 17:21:26 +02:00
romeojulietthotel
228ee4363e Use pkgconfig to locate ALSA libs (#6119)
* This allows building when ALSA libs are in a non-standard location. PKG_CONFIG_PATH alone is not enough as the final link fails. Adding this makes the final link succeed.

* The extra LIBS flag for alsa is not needed so removing.

(cherry picked from commit 94d6757a0d)
2016-10-09 17:21:17 +02:00
yg2f
36b1521cdc expose GeometryInstance.get_aabb() etc fixes #6587
expose ``GeometryInstance.get_aabb();`` to gdscript
expose ``VisualInstance.get_transformed_aabb();`` to gdscript
and debug ``ImmediateGeometry::add_vertex()``;

(cherry picked from commit c1e2358914)
2016-10-09 17:21:07 +02:00
Andreas Haas
d1ad94acf0 x11: Fix event.is_action() for release of modifier keys
The bug was that the release events for these also had the modifier state set, so the event comparison
failed.

Fixes #5901

(cherry picked from commit 6fcf2b2bd8)
2016-10-09 17:20:57 +02:00
George Marques
63b5a80088 Fix crash when disabling main screen plugin
(cherry picked from commit 0ec2b7baea)
2016-10-09 17:20:38 +02:00
Pedro J. Estébanez
45a5769162 Fix manifest generation bug in Android export
(cherry picked from commit 2c9d98bb48)
2016-10-09 17:20:27 +02:00
knd
b9399e93ad removed redundant assign operation in mesh_add_surface: elem_count is reassigned a value before the old one has been used.
(cherry picked from commit 708a028ce8)
2016-10-09 17:20:20 +02:00
Andreas Haas
33223e7a8a Add function to get readable names for joystick events
Closes #6476

(cherry picked from commit e0fcd9331a)
2016-10-09 17:19:57 +02:00
anneomcl
12edde80f2 Fix for #6158. Converting Vector2 to Size2 for scaling functions.
(cherry picked from commit aa5ade834c)
2016-10-09 17:18:54 +02:00
Pawel Kowal
c8299249e4 Show True/False tooltip in property editor for bool values
(cherry picked from commit 623c483eba)
2016-10-09 17:18:43 +02:00
George Marques
1d175be921 Add docs for XMLparser, VideoPlayer and most of Tree
(cherry picked from commit 7cd64c3c8d)
2016-10-09 17:18:36 +02:00
Andreas Haas
94e5c48004 Expose Vector2::clamped() to scripts
Needed this and wondered that there's no built-in function for it.
So I wanted to implement it and saw that it's actually already there, just wasn't bound ^^

(cherry picked from commit c21412fa7e)
2016-10-09 17:18:29 +02:00
Andreas Haas
4084ec4869 Make the choosable default editor layout the same as the actual default one.
Fixes #6266

(cherry picked from commit a2bff72eee)
2016-10-09 17:18:02 +02:00
Andreas Haas
d3b549f2a3 Fix ability to cut/paste text in LineEdit/TextEdit in readonly mode.
Fixes #6466

(cherry picked from commit 9c71e5a9df)
2016-10-09 17:17:54 +02:00
Pawel Kowal
4ca83c635f Add scrolling to Tree control in Drag and Drop mode
(cherry picked from commit 9e5aaa27bc)
2016-10-09 17:17:04 +02:00
Andreas Haas
e788ffff65 Fix input action pressed state not changing for quick joystick movements.
fixes #6488
Also removes a bunch of dead code related to checking if a joystick axis is pressed.

(cherry picked from commit 84783fe77b)
2016-10-09 17:16:19 +02:00
George Marques
6a0d47f34c Add a function to plugin get the main screen parent
- Fix a bug where the main screen button did not disappear when the plugin
  was deactivated.

(cherry picked from commit 98e7c1edba)
2016-10-09 17:12:15 +02:00
Brickcaster
e6d49fb54c Fix for issue #6496
Canged order of NOTIFICATION_DRAW to update scrollbar before scrollbar
is checked to see which list elements to display.

(cherry picked from commit cc7bc07e33)
2016-10-09 17:11:54 +02:00
Rémi Verschelde
eed5d878e8 classref: Sync with current source 2016-09-19 09:08:12 +02:00
Andreas Haas
521b5bd90f Update documentation on joystick vibration.
Added a note that long vibration durations are not recommended because of hardware limitations.
For example, my ps4 controller can only vibrate for ~3s on linux.

(cherry picked from commit cef70a5f8b)
2016-09-18 23:22:14 +02:00
Paulb23
8dca3f3f42 Fix highlight current script when script temputure is disabled
(cherry picked from commit fbd0b6f995)
2016-09-18 23:21:48 +02:00
Błażej Szczygieł
d2aa006ddb Vorbis: Don't compile unnecessary encoder files
(cherry picked from commit 222bc07874)
2016-09-18 23:21:36 +02:00
sanikoyes
ec32c33799 fix ScrollContainer cannot scroll when scroll bar is hidden
(cherry picked from commit b548ef0009)
2016-09-18 23:20:37 +02:00
Paulb23
9b9870ed9f Update current script color on change
(cherry picked from commit a0136838b3)
2016-09-18 23:19:58 +02:00
Juan Linietsky
a72945f4e3 Added constants from types in code completion, somehow this was never added.
Stuff like Label.ALIGN_CENTER or Mesh.PRIMITIVE_TRIANGLES did not complete..

(cherry picked from commit b83350f4b2)
2016-09-18 23:19:04 +02:00
Juan Linietsky
3ff8dea5f9 Fix Viewport.get_mouse_pos() for specific situations, closes #1885
(cherry picked from commit b16f41a10a)
2016-09-18 23:17:07 +02:00
Pawel Kowal
2b43d0a028 ScrollContainer expand children bug fix
(cherry picked from commit 853161a000)
2016-09-18 23:16:33 +02:00
George Marques
ee23649813 Fix the Windows environment in SCons spawn function
Properly fix #2974 as discussed there.

(cherry picked from commit aad87ab1b6)
2016-09-18 23:15:56 +02:00
sanikoyes
75f51aece9 Tween: fix non-repeat interpolate_callback does not delete after call triggered
(cherry picked from commit cccea7e0b4)
2016-09-18 23:15:43 +02:00
Ovnuniarchos
5653ac41f9 Mouse hotspot is not honored.
(cherry picked from commit 8fcd92c38a)
2016-09-18 23:15:32 +02:00
Ralf Hölzemer
6c22cab856 Move hardcoded theme colors from editor_node into editor_themes
(cherry picked from commit 991a433cb3)
2016-09-18 23:13:46 +02:00
Paulb23
71dc733ad2 Added ItemList get_v_scroll to docs
(cherry picked from commit 7d455fca71)
2016-09-18 23:13:40 +02:00
Paulb23
04ade4d639 Added get_v_scroll to item list, issue 5343
(cherry picked from commit 63fd8f863b)
2016-09-18 23:13:34 +02:00
Paulb23
20c3b35dd5 Added customisable grid color, issue 3781
(cherry picked from commit a82ecf6d80)
2016-09-18 23:13:13 +02:00
Andreas Haas
323dec7dd5 x11: fix x360 wireless gamepad mapping.
Uses hat values instead of buttons for the dpad now.
Fixes #6419

(cherry picked from commit 20bad652ef)
2016-09-18 23:13:06 +02:00
Gastronok
3b691907e9 Change the documentation to reflect that Directory.list_dir_begin()
returns true (not false) when a stream could not be initialized. (See, for
example,
https://github.com/godotengine/godot/blob/master/drivers/windows/dir_access_windows.cpp#L76
)

(cherry picked from commit cd82fafd58)
2016-09-18 23:12:55 +02:00
MarianoGNU
85eca7bc93 Explicitly initialize TextureProgress's initial angle value.
(Hopefully)
Fixes #3856
Fixes #6426
Fixes #6344

(cherry picked from commit ae4f7cbc2c)
2016-09-18 23:12:48 +02:00
bebae
2e6ce4b362 fixed wrong placement of AcceptDialog Buttons issue-6143
(cherry picked from commit dd9189aac4)
2016-09-18 23:12:39 +02:00
Paulb23
a1df4f138c Document itemlist disable tooltip
(cherry picked from commit 607d602493)
2016-09-18 23:12:30 +02:00
Paulb23
0aad82e921 Ability to disable item list tooltip, issue 6240
(cherry picked from commit 62a968b1c6)
2016-09-18 23:12:23 +02:00
Paulb23
aae720e488 Added setting to change current script background color, issue 5450
(cherry picked from commit 9e92fcaef9)
2016-09-18 23:12:15 +02:00
Geequlim
772a590261 Fix dialogs in ProjectManage don't with editor theme issue
(cherry picked from commit c1f23bb6af)
2016-09-18 23:11:50 +02:00
Pedro J. Estébanez
f90370886f Fix (potentially) Android libs packaging issue (#5645)
(cherry picked from commit e9065632c6)
2016-09-18 23:11:18 +02:00
Pedro J. Estébanez
c44757c2b7 Expose light shadow color to canvas item shaders
(cherry picked from commit 0960887625)
2016-09-18 23:11:08 +02:00
Pedro J. Estébanez
ffe5ecd67d Rename misleading define
The macro USE_LIGHT_SHADOW_COLOR actually was being defined when the shader used SHADOW (the output shadow color), not the shadow color set for the light so it's better named USE_OUTPUT_SHADOW_COLOR. In 3D there's not that difference but renaming as well for consistency.

(cherry picked from commit b69e422af9)
2016-09-18 23:10:26 +02:00
Juan Linietsky
e0ddef3164 Do not expose resource/ properties in sectioned property editor, closes #6396
(cherry picked from commit 0094c30938)
2016-09-18 23:10:14 +02:00
Juan Linietsky
7178399548 Added option for UVs (and tangents) in adding sphere for ImmediateGeometry, closes #6398
(cherry picked from commit f31400c04d)
2016-09-18 23:09:41 +02:00
supaiku
c007d31e52 Always show output panel when debugging
(cherry picked from commit 8514eaf34b)
2016-09-18 23:07:06 +02:00
supaiku
3f30a22cb0 Show object string cast instead of object id in debugger
(cherry picked from commit 0108e7c33a)
2016-09-18 23:06:51 +02:00
volzhs
d6dc8f4644 Select newly created folder on Directory dialog
(cherry picked from commit 28a0ed75ba)
2016-09-18 23:06:46 +02:00
Răzvan Cosmin Rădulescu
c4f79716d3 Clean up GDScript template
(cherry picked from commit 00e743b76a)
2016-09-18 23:05:45 +02:00
Kazuo256
4a9461fded Add http method and request data parameters
For HTTPRequest::request

(cherry picked from commit c53e5c555a)
2016-09-18 23:05:40 +02:00
Rémi Verschelde
49dd7b38bc Remove tools/script_plugins, demos of the old plugin API
They are superseded by the official demos in
https://github.com/godotengine/godot-demo-projects/tree/master/plugins

(cherry picked from commit 3b3502b758)
2016-09-18 23:05:16 +02:00
Rémi Verschelde
bfcfb58efc Merge tools/docdump in tools/doc
Reduces clutter in the tools folder.

(cherry picked from commit 6a4ba76836)
2016-09-18 23:05:07 +02:00
Rémi Verschelde
ed96689d8c Move various scripts to the "scripts" folder
Thus cleaning up the "tools" folder a bit.

(cherry picked from commit ae9729b6df)
2016-09-18 23:05:00 +02:00
Rémi Verschelde
125a9f0b06 Remove obsolete Win32 libraries that everyone had forgotten about
(cherry picked from commit 08e5e8794a)
2016-09-18 23:04:52 +02:00
Rémi Verschelde
fd58f8dce8 Move templates and distribution stuff to tools/dist
Also removed the obsolete iOS xcode template.

(cherry picked from commit 3efe1231f0)
2016-09-18 23:04:26 +02:00
Andreas Haas
adcf45b627 Update gamepad mappings from community db.
(cherry picked from commit 808bd53934)
2016-09-18 23:03:22 +02:00
Rémi Verschelde
48d1e8bd4e InputEvent: Fix event comparisons when type is NONE
Was a regression from 2e5a4cb5ca.
Fixes #6376.

(cherry picked from commit eff6519aaf)
2016-09-18 23:03:10 +02:00
Waldson Patrício
73b40d1457 Fixes LineEdit text selection with mouse selecting more than intended
(cherry picked from commit 3d84973184)
2016-09-18 23:02:57 +02:00
Joscha
e7772e43d3 Tilemap editor: Bucket tool - allow deleting and replacing of tiles
(cherry picked from commit acd41d964a)
2016-09-18 23:02:46 +02:00
Rémi Verschelde
de5f49aac5 i18n: Update list of supported locales based off glibc
Fixes #5733, fixes #6214.

(cherry picked from commit 54e97e5ee6)
2016-09-18 23:02:14 +02:00
Rémi Verschelde
2ab7e6daab i18n: Sync translations from Weblate
Translator credits added manually based on Weblate git log.
Adds Catalan, Danish and Norwegian Bokmål initial translations.

Those were initially translations for the master branch, merged
against the 2.1 template.
2016-09-01 19:33:28 +02:00
Rémi Verschelde
68c7da5a35 classref: Sync with current source 2016-09-01 18:56:48 +02:00
Mark Nokalt
a3a065b458 editor: Add mouse position information in TileMap
(cherry picked from commit cd71fcb097)
2016-09-01 08:46:23 +02:00
Mario Schlack
9ea76ff46d Hide the mouse cursor when MOUSE_MODE_CAPTURED is activated.
(cherry picked from commit f0b6a242cc)
2016-09-01 08:46:03 +02:00
Andreas Haas
cd6afd5f1d Fix crash when trying to access the guid of an unavailable Gamepad.
Throws an error now.

(cherry picked from commit 02a8604906)
2016-09-01 08:45:51 +02:00
volzhs
265715f5b2 Show last added action on Input Map and implement InputEvent "=="
(cherry picked from commit 2e5a4cb5ca)
2016-09-01 08:45:37 +02:00
volzhs
cd8beea3bf Prevent to add node to selection when node is not inside tree
(cherry picked from commit 4857eabddb)
2016-09-01 08:45:15 +02:00
George Marques
0657d43960 Better document the BaseButton signals
(cherry picked from commit 141360ed82)
2016-09-01 08:44:52 +02:00
George Marques
a21b9caa2a Add button_down and button_up signals
(cherry picked from commit 8a1b1ab6d6)
2016-09-01 08:44:45 +02:00
caryoscelus
83864514f9 fix string iterator
Since strings are null-terminated, size() returns incorrect length,
so use length() instead.

fixes #6287

(cherry picked from commit 810fbb70ae)
2016-09-01 08:44:30 +02:00
Ignacio Etcheverry
b1ea299edf Matrix32: Add constructor that takes six real_t params
(cherry picked from commit 3578800230)
2016-09-01 08:44:22 +02:00
Ignacio Etcheverry
103b04e529 DocData: Fix null reference not detected correctly
(cherry picked from commit b81725b203)
2016-09-01 08:44:08 +02:00
Mason Ashbridge
07caf4438d Slider value accounts for grabber offset
(cherry picked from commit fb54ba6397)
2016-09-01 08:43:59 +02:00
volzhs
6df46803a7 Make LineEdit not to cover whole line when rename node
(cherry picked from commit ff22db3b21)
2016-09-01 08:42:49 +02:00
Pedro J. Estébanez
cccc35e427 Improve/fix GridMap editor
Fix cursor/palette update on tile eyedropping
Fix editor not cleaning its state when becoming inactive, which leaves indicators behind among other issues
Fix/improve menu/keyboard shortcuts
Merge 'Gridmap Editor' and 'Grid Map' settings into the latter

(cherry picked from commit 7d35973486)
2016-09-01 08:41:31 +02:00
Gau o fthe Veldt
fa1f5e55de Documentation for most of ItemList control.
The icon stuff is incomplete since I haven't used icons.

(cherry picked from commit f9e931bf12)
2016-09-01 08:41:18 +02:00
Ignacio Etcheverry
6a563949c7 DocData: Fix duplicated parenthesis for default values
(cherry picked from commit 9e6b53c8dd)
2016-09-01 08:41:12 +02:00
Franklin Sobrinho
f9aeb91850 Implemented UndoRedo mergeable modes
(cherry picked from commit debf574df3)
2016-09-01 08:41:04 +02:00
Franklin Sobrinho
71a9efe604 Update Globals and EditorSettings docs
(cherry picked from commit 038e99e107)
2016-09-01 08:40:54 +02:00
Franklin Sobrinho
5f9e6d2b48 Added add_property_info function to Globals and EditorSettings classes
(cherry picked from commit 9f242ed6e5)
2016-09-01 08:40:49 +02:00
Franklin Sobrinho
6327fc47c8 Better editor settings for the FileSystem dock
* Save the current display mode when changing it from the dock

(cherry picked from commit f6b39827b1)
2016-09-01 08:40:23 +02:00
Franklin Sobrinho
3cbd6b8701 Fix editor glitches when the mesh/material preview is shown
(cherry picked from commit a4c3d2dc89)
2016-09-01 08:40:16 +02:00
Franklin Sobrinho
4890db7fef Small usability improvements on the TileMap editor tile palette.
* The column width changes with the zoom, now the icons don't overlap.
  * Added a tile hsepation setting.
  * Added a setting to show/hide tile names.

(cherry picked from commit 0fa26cd850)
2016-09-01 08:40:08 +02:00
Franklin Sobrinho
df3d2b25d8 Update EditorPlugin doc
(cherry picked from commit a27d2e4c29)
2016-09-01 08:39:58 +02:00
Franklin Sobrinho
743c63670e Expose additional functions for the EditorPlugin class
(cherry picked from commit 104653f9eb)
2016-09-01 08:39:52 +02:00
Daniel J. Ramirez
e26acc39da 2d collision shape icons now uses the color for shape icons
(cherry picked from commit cbad6b3fae)
2016-09-01 08:39:09 +02:00
Ignacio Etcheverry
1a53c4d3c2 Confirm code completion with numpad key ENTER
(cherry picked from commit e9f9e00bd9)
2016-09-01 08:38:34 +02:00
Andreas Haas
37fc61f986 x11: Use proper sonames for loading libXrandr.
(cherry picked from commit f59860f464)
2016-09-01 08:38:24 +02:00
Daniel J. Ramirez
16fc229e5d Zoom texture region via mouse wheel
(cherry picked from commit 1e7d0c6ac1)
2016-09-01 08:37:55 +02:00
Ignacio Etcheverry
4f07998552 Device Input dialog now uses containers
(cherry picked from commit 9483d3cbf9)
2016-09-01 08:34:05 +02:00
Rémi Verschelde
3b7ab73cab i18n: Merge PO files with current template 2016-08-10 21:31:06 +02:00
Rémi Verschelde
bbb543735c i18n: Sync template with current source 2016-08-10 21:30:57 +02:00
Rémi Verschelde
ed931d3b59 i18n: Sync translations from Weblate
Translator credits added manually based on Weblate git log.

(cherry picked from commit 221d81a26d)
2016-08-10 21:28:05 +02:00
Rémi Verschelde
720305d98e classref: Sync with current source 2016-08-10 21:28:01 +02:00
Rémi Verschelde
676b60a8b5 i18n: Add a README file to point to the Weblate repo
(cherry picked from commit 807c615148)
2016-08-10 21:27:45 +02:00
marcelofg55
0c76ba32cc Crashfix for OSX on Sierra beta
(cherry picked from commit bf320fd4ea)
2016-08-09 18:47:13 +02:00
Rémi Verschelde
c5e2c83dcd Release 2.1-stable
\o/
2016-08-09 09:52:15 +02:00
Rémi Verschelde
9cc700a0ab OSX Info.plist: no longer dev version
This should really be dehardcoded somehow.
2016-08-09 09:51:58 +02:00
Juan Linietsky
569966f3bb prevent bug due to scripts not working in editor and notifier sending signals to it.
(cherry picked from commit 37b5e99bc2)
2016-08-09 00:13:31 +02:00
Juan Linietsky
58556f5f95 Fixed bug in make_dir_recursive, closes #6016
(cherry picked from commit df6dbadc3e)
2016-08-08 23:45:39 +02:00
Rémi Verschelde
229b172977 Merge pull request #6078 from eska014/2.1-fix-call_func
Revert documentation of return type for FuncRef::call_func from b80c42e
2016-08-08 18:23:43 +02:00
Skyfrit
c56ea7cf91 Android: Rename values-zh to values-zh-rCN (#6063)
(cherry picked from commit 4f6a21b0df)
2016-08-08 18:15:55 +02:00
Skyfrit
1913e4a040 Android: Add support for Traditional Chinese (HK) (#6061)
(cherry picked from commit 664b5b5137)
2016-08-08 18:15:49 +02:00
Skyfrit
2b35ba4815 Android: Add support for Traditional Chinese (TW) (#6061)
(cherry picked from commit 8ab4acd17f)
2016-08-08 18:15:43 +02:00
Ignacio Etcheverry
d853eb2fb7 Project Manager: Fix and improve unhandled input
(cherry picked from commit f3a75a42dd)
2016-08-08 18:15:03 +02:00
Andreas Haas
36eeedb357 Remove unused function in Project Manager.
This has been deprecated by #5993

(cherry picked from commit 0df40cc29b)
2016-08-08 18:14:57 +02:00
Andreas Haas
5f18c5cb46 Fix steam controller gamepad mapping
The left stick click was missing

(cherry picked from commit e52567bd29)
2016-08-08 18:14:51 +02:00
Bojidar Marinov
f25e9a08e1 Fix #5891 by not expecting the script instance to be a GDInstance
It could be a placeholder instance as well

(cherry picked from commit 76ea995228)
2016-08-08 18:14:44 +02:00
MSC
4f8f9a4dbf Some additions to the OS documentation (#6037)
(cherry picked from commit 7b05b4c83c)
2016-08-08 18:14:35 +02:00
Saracen
dd97502788 TextureRegionEditor snap_mode fix.
(cherry picked from commit b578cf4da8)
2016-08-08 18:14:29 +02:00
Hubert Jarosz
d55304c56f [ci skip] update Raycast documentation
clarification that set_cast_to needs LOCAL point
and get_collision_point gives GLOBAL point

(cherry picked from commit 1445553fea)
2016-08-08 18:14:14 +02:00
eska
03a4b8cbc8 Revert documentation of return type for FuncRef::call_func from b80c42e
bind_native_method doesn't support this style of return type documentation.
2016-08-08 17:49:30 +02:00
Rémi Verschelde
2f0df52fe7 Bump version to 2.1-rc2 2016-08-03 17:53:53 +02:00
marcelofg55
fd6f62fd9a Fix set_window_size not setting the correct size on OSX
(cherry picked from commit 38de4d24ef)
2016-08-03 17:52:10 +02:00
11068 changed files with 1198368 additions and 5680315 deletions

View File

@@ -1,189 +0,0 @@
# Commented out parameters are those with the same value as base LLVM style.
# We can uncomment them if we want to change their value, or enforce the
# chosen value in case the base style changes (last sync: Clang 13.0).
---
### General config, applies to all languages ###
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: DontAlign
# AlignArrayOfStructures: None
# AlignConsecutiveMacros: None
# AlignConsecutiveAssignments: None
# AlignConsecutiveBitFields: None
# AlignConsecutiveDeclarations: None
# AlignEscapedNewlines: Right
AlignOperands: DontAlign
AlignTrailingComments: false
# AllowAllArgumentsOnNextLine: true
# AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: false
# AllowShortEnumsOnASingleLine: true
# AllowShortBlocksOnASingleLine: Never
# AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
# AllowShortLambdasOnASingleLine: All
# AllowShortIfStatementsOnASingleLine: Never
# AllowShortLoopsOnASingleLine: false
# AlwaysBreakAfterDefinitionReturnType: None
# AlwaysBreakAfterReturnType: None
# AlwaysBreakBeforeMultilineStrings: false
# AlwaysBreakTemplateDeclarations: MultiLine
# AttributeMacros:
# - __capability
# BinPackArguments: true
# BinPackParameters: true
# BraceWrapping:
# AfterCaseLabel: false
# AfterClass: false
# AfterControlStatement: Never
# AfterEnum: false
# AfterFunction: false
# AfterNamespace: false
# AfterObjCDeclaration: false
# AfterStruct: false
# AfterUnion: false
# AfterExternBlock: false
# BeforeCatch: false
# BeforeElse: false
# BeforeLambdaBody: false
# BeforeWhile: false
# IndentBraces: false
# SplitEmptyFunction: true
# SplitEmptyRecord: true
# SplitEmptyNamespace: true
# BreakBeforeBinaryOperators: None
# BreakBeforeConceptDeclarations: true
# BreakBeforeBraces: Attach
# BreakBeforeInheritanceComma: false
# BreakInheritanceList: BeforeColon
# BreakBeforeTernaryOperators: true
# BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: AfterColon
# BreakStringLiterals: true
ColumnLimit: 0
# CommentPragmas: '^ IWYU pragma:'
# CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
# DeriveLineEnding: true
# DerivePointerAlignment: false
# DisableFormat: false
# EmptyLineAfterAccessModifier: Never
# EmptyLineBeforeAccessModifier: LogicalBlock
# ExperimentalAutoDetectBinPacking: false
# FixNamespaceComments: true
# ForEachMacros:
# - foreach
# - Q_FOREACH
# - BOOST_FOREACH
# IfMacros:
# - KJ_IF_MAYBE
# IncludeBlocks: Preserve
IncludeCategories:
- Regex: '".*"'
Priority: 1
- Regex: '^<.*\.h>'
Priority: 2
- Regex: '^<.*'
Priority: 3
# IncludeIsMainRegex: '(Test)?$'
# IncludeIsMainSourceRegex: ''
# IndentAccessModifiers: false
IndentCaseLabels: true
# IndentCaseBlocks: false
# IndentGotoLabels: true
# IndentPPDirectives: None
# IndentExternBlock: AfterExternBlock
# IndentRequires: false
IndentWidth: 4
# IndentWrappedFunctionNames: false
# InsertTrailingCommas: None
# JavaScriptQuotes: Leave
# JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
# LambdaBodyIndentation: Signature
# MacroBlockBegin: ''
# MacroBlockEnd: ''
# MaxEmptyLinesToKeep: 1
# NamespaceIndentation: None
# PenaltyBreakAssignment: 2
# PenaltyBreakBeforeFirstCallParameter: 19
# PenaltyBreakComment: 300
# PenaltyBreakFirstLessLess: 120
# PenaltyBreakString: 1000
# PenaltyBreakTemplateDeclaration: 10
# PenaltyExcessCharacter: 1000000
# PenaltyReturnTypeOnItsOwnLine: 60
# PenaltyIndentedWhitespace: 0
# PointerAlignment: Right
# PPIndentWidth: -1
# ReferenceAlignment: Pointer
# ReflowComments: true
# ShortNamespaceLines: 1
# SortIncludes: CaseSensitive
# SortJavaStaticImport: Before
# SortUsingDeclarations: true
# SpaceAfterCStyleCast: false
# SpaceAfterLogicalNot: false
# SpaceAfterTemplateKeyword: true
# SpaceBeforeAssignmentOperators: true
# SpaceBeforeCaseColon: false
# SpaceBeforeCpp11BracedList: false
# SpaceBeforeCtorInitializerColon: true
# SpaceBeforeInheritanceColon: true
# SpaceBeforeParens: ControlStatements
# SpaceAroundPointerQualifiers: Default
# SpaceBeforeRangeBasedForLoopColon: true
# SpaceInEmptyParentheses: false
# SpacesBeforeTrailingComments: 1
# SpaceInEmptyBlock: false
# SpaceInEmptyParentheses: false
# SpacesBeforeTrailingComments: 1
# SpacesInAngles: Never
# SpacesInContainerLiterals: true
# SpacesInConditionalStatement: false
# SpacesInContainerLiterals: true
# SpacesInCStyleCastParentheses: false
## Godot TODO: We'll want to use a min of 1, but we need to see how to fix
## our comment capitalization at the same time.
SpacesInLineCommentPrefix:
Minimum: 0
Maximum: -1
# SpacesInParentheses: false
# SpacesInSquareBrackets: false
# SpaceBeforeSquareBrackets: false
# BitFieldColonSpacing: Both
# StatementAttributeLikeMacros:
# - Q_EMIT
# StatementMacros:
# - Q_UNUSED
# - QT_REQUIRE_VERSION
TabWidth: 4
# UseCRLF: false
UseTab: Always
# WhitespaceSensitiveMacros:
# - STRINGIZE
# - PP_STRINGIZE
# - BOOST_PP_STRINGIZE
# - NS_SWIFT_NAME
# - CF_SWIFT_NAME
---
### C++ specific config ###
Language: Cpp
Standard: c++14
---
### ObjC specific config ###
Language: ObjC
# ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 4
# ObjCBreakBeforeNestedBlockParam: true
# ObjCSpaceAfterProperty: false
# ObjCSpaceBeforeProtocolList: true
---
### Java specific config ###
Language: Java
# BreakAfterJavaFieldAnnotations: false
JavaImportGroups: ['org.godotengine', 'android', 'androidx', 'com.android', 'com.google', 'java', 'javax']
...

View File

@@ -1,44 +0,0 @@
---
Checks: 'clang-diagnostic-*,clang-analyzer-*,-*,modernize-redundant-void-arg,modernize-use-bool-literals,modernize-use-nullptr,readability-braces-around-statements'
WarningsAsErrors: ''
HeaderFilterRegex: '.*'
AnalyzeTemporaryDtors: false
FormatStyle: none
CheckOptions:
CheckOptions:
- key: cert-dcl16-c.NewSuffixes
value: 'L;LL;LU;LLU'
- key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
value: '0'
- key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors
value: '1'
- key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
value: '1'
- key: google-readability-function-size.StatementThreshold
value: '800'
- key: google-readability-namespace-comments.ShortNamespaceLines
value: '10'
- key: google-readability-namespace-comments.SpacesBeforeComments
value: '2'
- key: modernize-loop-convert.MaxCopySize
value: '16'
- key: modernize-loop-convert.MinConfidence
value: reasonable
- key: modernize-loop-convert.NamingStyle
value: CamelCase
- key: modernize-pass-by-value.IncludeStyle
value: llvm
- key: modernize-replace-auto-ptr.IncludeStyle
value: llvm
- key: modernize-use-bool-literals.IgnoreMacros
value: '0'
- key: modernize-use-default-member-init.IgnoreMacros
value: '0'
- key: modernize-use-default-member-init.UseAssignment
value: '1'
- key: modernize-use-nullptr.NullMacros
value: 'NULL'
- key: readability-braces-around-statements.ShortStatementLines
value: '0'
...

View File

@@ -4,20 +4,7 @@ root = true
charset = utf-8
end_of_line = lf
indent_style = tab
insert_final_newline = true
[*.{cpp,hpp,c,h,mm}]
trim_trailing_whitespace = true
[{*.gradle,AndroidManifest.xml}]
indent_style = space
indent_size = 4
[{*.py,SConstruct,SCsub}]
indent_style = space
indent_size = 4
# YAML requires indentation with spaces instead of tabs.
[*.{yml,yaml}]
[.travis.yml]
indent_style = space
indent_size = 2

18
.gitattributes vendored
View File

@@ -1,17 +1,9 @@
# Properly detect languages on Github
*.h linguist-language=cpp
*.inc linguist-language=cpp
thirdparty/* linguist-vendored
drivers/* linguist-vendored
# Normalize EOL for all files that Git considers text files
* text=auto eol=lf
# Except for bat files, which are Windows only files
*.bat eol=crlf
# The above only works properly for Git 2.10+, so for older versions
# we need to manually list the binary files we don't want modified.
*.icns binary
*.ico binary
*.jar binary
*.png binary
*.ttf binary
*.cpp eol=lf
*.h eol=lf
*.py eol=lf
*.hpp eol=lf

174
.github/CODEOWNERS vendored
View File

@@ -1,174 +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
# Buildsystem
.* @godotengine/buildsystem
.github/ @godotengine/buildsystem
*.py @godotengine/buildsystem
SConstruct @godotengine/buildsystem
SCsub @godotengine/buildsystem
# Core
/core/ @godotengine/core
/core/crypto/ @godotengine/network
/core/input*.* @godotengine/input
# Doc
/doc/ @godotengine/documentation
doc_classes/* @godotengine/documentation
# Drivers
## Audio
/drivers/alsa/ @godotengine/audio
/drivers/alsamidi/ @godotengine/audio
/drivers/coreaudio/ @godotengine/audio
/drivers/coremidi/ @godotengine/audio
/drivers/pulseaudio/ @godotengine/audio
/drivers/wasapi/ @godotengine/audio
/drivers/winmidi/ @godotengine/audio
/drivers/xaudio2/ @godotengine/audio
## Rendering
/drivers/dummy/ @godotengine/rendering
/drivers/gl_context/ @godotengine/rendering
/drivers/gles2/ @godotengine/rendering
/drivers/gles3/ @godotengine/rendering
/drivers/gles_common/ @godotengine/rendering
## OS
/drivers/unix/ @godotengine/_platforms
/drivers/windows/ @godotengine/windows
## Misc
/drivers/png/ @godotengine/import
# Editor
/editor/*debugger* @godotengine/debugger
/editor/icons/ @godotengine/usability
/editor/import/ @godotengine/import
/editor/plugins/*2d_*.* @godotengine/2d-editor
/editor/plugins/script_*.* @godotengine/script-editor
/editor/plugins/*shader*.* @godotengine/shaders
/editor/code_editor.* @godotengine/script-editor
/editor/*dock*.* @godotengine/docks
# Main
/main/ @godotengine/core
/main/tests/ @godotengine/tests
# Misc
/misc/ @godotengine/buildsystem
# Modules
## Audio (+ video)
/modules/minimp3/ @godotengine/audio
/modules/ogg/ @godotengine/audio
/modules/opus/ @godotengine/audio
/modules/stb_vorbis/ @godotengine/audio
/modules/theora/ @godotengine/audio
/modules/vorbis/ @godotengine/audio
/modules/webm/ @godotengine/audio
## Import
/modules/basis_universal/ @godotengine/import
/modules/bmp/ @godotengine/import
/modules/cvtt/ @godotengine/import
/modules/dds/ @godotengine/import
/modules/etc/ @godotengine/import
/modules/fbx/ @godotengine/import
/modules/gltf/ @godotengine/import
/modules/hdr/ @godotengine/import
/modules/jpg/ @godotengine/import
/modules/pvr/ @godotengine/import
/modules/squish/ @godotengine/import
/modules/svg/ @godotengine/import
/modules/tga/ @godotengine/import
/modules/tinyexr/ @godotengine/import
/modules/webp/ @godotengine/import
## Network
/modules/enet/ @godotengine/network
/modules/mbedtls/ @godotengine/network
/modules/upnp/ @godotengine/network
/modules/webrtc/ @godotengine/network
/modules/websocket/ @godotengine/network
## Rendering
/modules/denoise/ @godotengine/rendering
/modules/glslang/ @godotengine/rendering
/modules/lightmapper_cpu/ @godotengine/rendering
/modules/meshoptimizer/ @godotengine/rendering
/modules/raycast/ @godotengine/rendering
/modules/vhacd/ @godotengine/rendering
/modules/xatlas_unwrap/ @godotengine/rendering
## Scripting
/modules/gdnative/ @godotengine/gdnative
/modules/gdscript/ @godotengine/gdscript
/modules/jsonrpc/ @godotengine/gdscript
/modules/mono/ @godotengine/mono
/modules/visual_script/ @godotengine/visualscript
## Text
/modules/freetype/ @godotengine/buildsystem
/modules/gdnative/text/ @godotengine/gui-nodes
/modules/text_server_adv/ @godotengine/gui-nodes
/modules/text_server_fb/ @godotengine/gui-nodes
## XR
/modules/camera/ @godotengine/xr
/modules/gdnative/arvr/ @godotengine/xr
/modules/mobile_vr/ @godotengine/xr
/modules/webxr/ @godotengine/xr
## Misc
/modules/bullet/ @godotengine/physics
/modules/csg/ @godotengine/3d-nodes
/modules/gridmap/ @godotengine/3d-nodes
/modules/opensimplex/ @godotengine/3d-nodes
/modules/recast/ @godotengine/navigation
/modules/regex/ @godotengine/core
# Platform
/platform/android/ @godotengine/android
/platform/iphone/ @godotengine/ios
/platform/javascript/ @godotengine/html5
/platform/x11/ @godotengine/linux-bsd
/platform/osx/ @godotengine/macos
/platform/uwp/ @godotengine/uwp
/platform/windows/ @godotengine/windows
# Scene
/scene/2d/ @godotengine/2d-nodes
/scene/3d/ @godotengine/3d-nodes
/scene/animation/ @godotengine/animation
/scene/audio/ @godotengine/audio
/scene/debugger/ @godotengine/debugger
/scene/gui/ @godotengine/gui-nodes
/scene/main/ @godotengine/core
/scene/resources/default_theme/ @godotengine/gui-nodes
/scene/resources/font.* @godotengine/gui-nodes
/scene/resources/visual_shader*.* @godotengine/shaders
# Servers
/servers/arvr* @godotengine/xr
/servers/audio* @godotengine/audio
/servers/camera* @godotengine/xr
/servers/physics* @godotengine/physics
/servers/visual* @godotengine/rendering
# Thirdparty
/thirdparty/ @godotengine/buildsystem

View File

@@ -1,18 +0,0 @@
---
name: Bug report
about: Report a bug in Godot
title: ''
labels: ''
assignees: ''
---
**Godot version:**
**OS/device including version:**
**Issue description:**
**Steps to reproduce:**
**Minimal reproduction project:**

View File

@@ -1,19 +0,0 @@
---
name: Feature / Enhancement Request
about: Adding new features or improving existing ones.
title: 'IMPORTANT: This repository no longer accepts feature / enhancement requests.'
labels: ''
assignees: ''
---
**IMPORTANT, PLEASE READ**
Feature / Enhancement requests are no longer accepted in the main Godot repository.
Please open an item by filling the relevant fields in the *Proposals* repository:
https://github.com/godotengine/godot-proposals/issues/new/choose
Do not submit to this repository or your issue will be closed.
**IMPORTANT, PLEASE READ**

View File

@@ -1,36 +0,0 @@
name: Build Godot
description: Build Godot with the provided options.
inputs:
target:
description: The scons target (debug/release_debug/release).
default: "debug"
tools:
description: If tools are to be built.
default: false
tests:
description: If tests are to be built.
default: false
platform:
description: The Godot platform to build.
required: false
sconsflags:
default: ""
scons-cache:
description: The scons cache path.
default: "${{ github.workspace }}/.scons-cache/"
scons-cache-limit:
description: The scons cache size limit.
default: 4096
runs:
using: "composite"
steps:
- name: Scons Build
shell: sh
env:
SCONSFLAGS: ${{ inputs.sconsflags }}
SCONS_CACHE: ${{ inputs.scons-cache }}
SCONS_CACHE_LIMIT: ${{ inputs.scons-cache-limit }}
run: |
echo "Building with flags:" ${{ env.SCONSFLAGS }}
scons p=${{ inputs.platform }} target=${{ inputs.target }} tools=${{ inputs.tools }} tests=${{ inputs.tests }} --jobs=2 ${{ env.SCONSFLAGS }}
ls -l bin/

View File

@@ -1,22 +0,0 @@
name: Setup Godot build cache
description: Setup Godot build cache.
inputs:
cache-name:
description: The cache base name (job name by default).
default: "${{github.job}}"
scons-cache:
description: The scons cache path.
default: "${{github.workspace}}/.scons-cache/"
runs:
using: "composite"
steps:
# Upload cache on completion and check it out now
- name: Load .scons_cache directory
uses: actions/cache@v2
with:
path: ${{inputs.scons-cache}}
key: ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
restore-keys: |
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}

View File

@@ -1,27 +0,0 @@
name: Setup python and scons
description: Setup python, install the pip version of scons.
inputs:
python-version:
description: The python version to use.
default: "3.x"
python-arch:
description: The python architecture.
default: "x64"
runs:
using: "composite"
steps:
# Use python 3.x release (works cross platform)
- name: Set up Python 3.x
uses: actions/setup-python@v2
with:
# Semantic version range syntax or exact version of a Python version
python-version: ${{ inputs.python-version }}
# Optional - x64 or x86 architecture, defaults to x64
architecture: ${{ inputs.python-arch }}
- name: Setup scons
shell: bash
run: |
python -c "import sys; print(sys.version)"
python -m pip install scons
scons --version

View File

@@ -1,19 +0,0 @@
name: Upload Godot artifact
description: Upload the Godot artifact.
inputs:
name:
description: The artifact name.
default: "${{ github.job }}"
path:
description: The path to upload.
required: true
default: "bin/*"
runs:
using: "composite"
steps:
- name: Upload Godot Artifact
uses: actions/upload-artifact@v2
with:
name: ${{ inputs.name }}
path: ${{ inputs.path }}
retention-days: 14

View File

@@ -1,65 +0,0 @@
name: 🤖 Android Builds
on: [push, pull_request]
# Global Settings
env:
GODOT_BASE_BRANCH: 3.4
SCONSFLAGS: verbose=yes warnings=all werror=yes debug_symbols=no
concurrency:
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-android
cancel-in-progress: true
jobs:
android-template:
runs-on: "ubuntu-20.04"
name: Template (target=release, tools=no)
steps:
- uses: actions/checkout@v2
# Azure repositories are not reliable, we need to prevent azure giving us packages.
- name: Make apt sources.list use the default Ubuntu repositories
run: |
sudo rm -f /etc/apt/sources.list.d/*
sudo cp -f misc/ci/sources.list /etc/apt/sources.list
sudo apt-get update
- name: Set up Java 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Setup Godot build cache
uses: ./.github/actions/godot-cache
continue-on-error: true
- name: Setup python and scons
uses: ./.github/actions/godot-deps
- name: Compilation (armv7)
uses: ./.github/actions/godot-build
with:
sconsflags: ${{ env.SCONSFLAGS }} android_arch=armv7
platform: android
target: release
tools: false
- name: Compilation (arm64v8)
uses: ./.github/actions/godot-build
with:
sconsflags: ${{ env.SCONSFLAGS }} android_arch=arm64v8
platform: android
target: release
tools: false
- name: Generate Godot templates
run: |
cd platform/android/java
./gradlew generateGodotTemplates
cd ../../..
ls -l bin/
- name: Upload artifact
uses: ./.github/actions/upload-artifact

View File

@@ -1,37 +0,0 @@
name: 🍏 iOS Builds
on: [push, pull_request]
# Global Settings
env:
GODOT_BASE_BRANCH: 3.4
SCONSFLAGS: verbose=yes warnings=all werror=yes debug_symbols=no
concurrency:
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-ios
cancel-in-progress: true
jobs:
ios-template:
runs-on: "macos-latest"
name: Template (target=release, tools=no)
steps:
- uses: actions/checkout@v2
- name: Setup Godot build cache
uses: ./.github/actions/godot-cache
continue-on-error: true
- name: Setup python and scons
uses: ./.github/actions/godot-deps
- name: Compilation (armv7)
uses: ./.github/actions/godot-build
with:
sconsflags: ${{ env.SCONSFLAGS }}
platform: iphone
target: release
tools: false
- name: Upload artifact
uses: ./.github/actions/upload-artifact

View File

@@ -1,57 +0,0 @@
name: 🌐 JavaScript Builds
on: [push, pull_request]
# Global Settings
env:
GODOT_BASE_BRANCH: 3.4
SCONSFLAGS: verbose=yes warnings=all werror=yes debug_symbols=no
EM_VERSION: 2.0.25
EM_CACHE_FOLDER: "emsdk-cache"
concurrency:
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-javascript
cancel-in-progress: true
jobs:
javascript-template:
runs-on: "ubuntu-20.04"
name: Template (target=release, tools=no)
steps:
- uses: actions/checkout@v2
# Additional cache for Emscripten generated system libraries
- name: Load Emscripten cache
id: javascript-template-emscripten-cache
uses: actions/cache@v2
with:
path: ${{env.EM_CACHE_FOLDER}}
key: ${{env.EM_VERSION}}-${{github.job}}
- name: Set up Emscripten latest
uses: mymindstorm/setup-emsdk@v10
with:
version: ${{env.EM_VERSION}}
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
- name: Verify Emscripten setup
run: |
emcc -v
- name: Setup Godot build cache
uses: ./.github/actions/godot-cache
continue-on-error: true
- name: Setup python and scons
uses: ./.github/actions/godot-deps
- name: Compilation
uses: ./.github/actions/godot-build
with:
sconsflags: ${{ env.SCONSFLAGS }}
platform: javascript
target: release
tools: false
- name: Upload artifact
uses: ./.github/actions/upload-artifact

View File

@@ -1,137 +0,0 @@
name: 🐧 Linux Builds
on: [push, pull_request]
# Global Settings
env:
GODOT_BASE_BRANCH: 3.4
SCONSFLAGS: verbose=yes warnings=all werror=yes
concurrency:
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-linux
cancel-in-progress: true
jobs:
build-linux:
runs-on: "ubuntu-20.04"
name: ${{ matrix.name }}
strategy:
fail-fast: false
matrix:
include:
- name: Editor w/ Mono (target=release_debug, tools=yes)
cache-name: linux-editor-mono
target: release_debug
tools: true
sconsflags: module_mono_enabled=yes mono_static=yes mono_glue=no
bin: "./bin/godot.x11.opt.tools.64.mono"
build-mono: true
artifact: true
- name: Editor and sanitizers (target=debug, tools=yes, use_asan=yes, use_ubsan=yes)
cache-name: linux-editor-sanitizers
target: debug
tools: true
sconsflags: use_asan=yes use_ubsan=yes
test: true
bin: "./bin/godot.x11.tools.64s"
build-mono: false
# Skip 2GiB artifact speeding up action.
artifact: false
- name: Template w/ Mono (target=release, tools=no)
cache-name: linux-template-mono
target: release
tools: false
sconsflags: module_mono_enabled=yes mono_static=yes mono_glue=no debug_symbols=no
build-mono: false
artifact: true
steps:
- uses: actions/checkout@v2
- name: Linux dependencies
shell: bash
run: |
# Azure repositories are not reliable, we need to prevent azure giving us packages.
sudo rm -f /etc/apt/sources.list.d/*
sudo cp -f misc/ci/sources.list /etc/apt/sources.list
sudo apt-get update
# The actual dependencies
sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \
libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev \
libdbus-1-dev libudev-dev libxi-dev libxrandr-dev yasm xvfb wget unzip
- name: Setup Godot build cache
uses: ./.github/actions/godot-cache
with:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- name: Setup python and scons
uses: ./.github/actions/godot-deps
- name: Compilation
uses: ./.github/actions/godot-build
with:
sconsflags: ${{ env.SCONSFLAGS }} ${{ matrix.sconsflags }}
platform: linuxbsd
target: ${{ matrix.target }}
tools: ${{ matrix.tools }}
# Generate mono glue
- name: Generate Mono glue code
if: ${{ matrix.build-mono }}
run: |
DRI_PRIME=0 xvfb-run ${{ matrix.bin }} --generate-mono-glue modules/mono/glue || true
# Rebuild with mono
- name: Compilation (mono_glue=yes)
uses: ./.github/actions/godot-build
if: ${{ matrix.build-mono }}
with:
sconsflags: ${{ env.SCONSFLAGS }} ${{ matrix.sconsflags }} mono_glue=yes
platform: linuxbsd
target: ${{ matrix.target }}
tools: ${{ matrix.tools }}
# Download and extract zip archive with project, folder is renamed to be able to easy change used project
- name: Download test project
if: ${{ matrix.test }}
run: |
wget https://github.com/godotengine/regression-test-project/archive/3.4.zip
unzip 3.4.zip
mv "regression-test-project-3.4" "test_project"
# Editor is quite complicated piece of software, so it is easy to introduce bug here
- name: Open and close editor
if: ${{ matrix.test }}
run: |
DRI_PRIME=0 xvfb-run ${{ matrix.bin }} --audio-driver Dummy -e -q --path test_project 2>&1 | tee sanitizers_log.txt || true
misc/scripts/check_ci_log.py sanitizers_log.txt
# Run test project
- name: Run project
if: ${{ matrix.test }}
run: |
DRI_PRIME=0 xvfb-run ${{ matrix.bin }} 30 --video-driver GLES3 --audio-driver Dummy --path test_project 2>&1 | tee sanitizers_log.txt || true
misc/scripts/check_ci_log.py sanitizers_log.txt
# Check class reference
- name: Check for class reference updates
if: ${{ matrix.test }}
run: |
echo "Running --doctool to see if this changes the public API without updating the documentation."
echo -e "If a diff is shown, it means that your code/doc changes are incomplete and you should update the class reference with --doctool.\n\n"
DRI_PRIME=0 xvfb-run ${{ matrix.bin }} --doctool . 2>&1 > /dev/null || true
git diff --color --exit-code && ! git ls-files --others --exclude-standard | sed -e 's/^/New doc file missing in PR: /' | grep 'xml$'
- name: Prepare artifact
if: ${{ matrix.artifact }}
run: |
strip bin/godot.*
- name: Upload artifact
uses: ./.github/actions/upload-artifact
if: ${{ matrix.artifact }}
with:
name: ${{ matrix.cache-name }}

View File

@@ -1,55 +0,0 @@
name: 🍎 macOS Builds
on: [push, pull_request]
# Global Settings
env:
GODOT_BASE_BRANCH: 3.4
SCONSFLAGS: verbose=yes warnings=all werror=yes debug_symbols=no
concurrency:
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-macos
cancel-in-progress: true
jobs:
build-macos:
runs-on: "macos-latest"
name: ${{ matrix.name }}
strategy:
fail-fast: false
matrix:
include:
- name: Editor (target=release_debug, tools=yes)
cache-name: macos-editor
target: release_debug
tools: true
bin: "./bin/godot.osx.opt.tools.64"
- name: Template (target=release, tools=no)
cache-name: macos-template
target: release
tools: false
steps:
- uses: actions/checkout@v2
- name: Setup Godot build cache
uses: ./.github/actions/godot-cache
with:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- name: Setup python and scons
uses: ./.github/actions/godot-deps
- name: Compilation
uses: ./.github/actions/godot-build
with:
sconsflags: ${{ env.SCONSFLAGS }}
platform: osx
target: ${{ matrix.target }}
tools: ${{ matrix.tools }}
- name: Upload artifact
uses: ./.github/actions/upload-artifact
with:
name: ${{ matrix.cache-name }}

View File

@@ -1,61 +0,0 @@
name: ☁ Server Builds
on: [push, pull_request]
# Global Settings
env:
GODOT_BASE_BRANCH: 3.4
SCONSFLAGS: verbose=yes warnings=all werror=yes debug_symbols=no module_mono_enabled=yes mono_static=yes mono_glue=no
concurrency:
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-server
cancel-in-progress: true
jobs:
build-server:
runs-on: "ubuntu-20.04"
name: ${{ matrix.name }}
strategy:
fail-fast: false
matrix:
include:
- name: Linux Headless w/ Mono (target=release_debug, tools=yes)
cache-name: server-editor-mono
target: release_debug
tools: true
- name: Linux Server w/ Mono (target=release, tools=no)
cache-name: server-template-mono
target: release
tools: false
steps:
- uses: actions/checkout@v2
- name: Linux dependencies
shell: bash
run: |
# Azure repositories are not reliable, we need to prevent azure giving us packages.
sudo rm -f /etc/apt/sources.list.d/*
sudo cp -f misc/ci/sources.list /etc/apt/sources.list
sudo apt-get update
# The actual dependencies
sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \
libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev \
libdbus-1-dev libudev-dev libxi-dev libxrandr-dev yasm xvfb wget unzip
- name: Setup Godot build cache
uses: ./.github/actions/godot-cache
with:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- name: Setup python and scons
uses: ./.github/actions/godot-deps
- name: Compilation
uses: ./.github/actions/godot-build
with:
sconsflags: ${{ env.SCONSFLAGS }} ${{ matrix.sconsflags }}
platform: server
target: ${{ matrix.target }}
tools: ${{ matrix.tools }}

View File

@@ -1,49 +0,0 @@
name: 📊 Static Checks
on: [push, pull_request]
jobs:
static-checks:
name: Static Checks (clang-format, black format, file format, documentation checks)
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v2
# Azure repositories are not reliable, we need to prevent Azure giving us packages.
- name: Make apt sources.list use the default Ubuntu repositories
run: |
sudo rm -f /etc/apt/sources.list.d/*
sudo cp -f misc/ci/sources.list /etc/apt/sources.list
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt-add-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-13 main"
sudo apt-get update
- name: Install dependencies
run: |
sudo apt-get install -qq dos2unix recode clang-format-13
sudo update-alternatives --remove-all clang-format
sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-13 100
sudo pip3 install black==21.10b0 pygments
- name: File formatting checks (file_format.sh)
run: |
bash ./misc/scripts/file_format.sh
- name: Style checks via clang-format (clang_format.sh)
run: |
bash ./misc/scripts/clang_format.sh
- name: Python style checks via black (black_format.sh)
run: |
bash ./misc/scripts/black_format.sh
- name: JavaScript style and documentation checks via ESLint and JSDoc
run: |
cd platform/javascript
npm ci
npm run lint
npm run docs -- -d dry-run
- name: Documentation checks
run: |
doc/tools/make_rst.py --dry-run doc/classes modules

View File

@@ -1,59 +0,0 @@
name: 🏁 Windows Builds
on: [push, pull_request]
# Global Settings
# SCONS_CACHE for windows must be set in the build environment
env:
GODOT_BASE_BRANCH: 3.4
SCONSFLAGS: verbose=yes warnings=all werror=yes debug_symbols=no
SCONS_CACHE_MSVC_CONFIG: true
concurrency:
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-windows
cancel-in-progress: true
jobs:
build-windows:
# Windows 10 with latest image
runs-on: "windows-latest"
name: ${{ matrix.name }}
strategy:
fail-fast: false
matrix:
include:
- name: Editor (target=release_debug, tools=yes)
cache-name: windows-editor
target: release_debug
tools: true
bin: "./bin/godot.windows.opt.tools.64.exe"
- name: Template (target=release, tools=no)
cache-name: windows-template
target: release
tools: false
steps:
- uses: actions/checkout@v2
- name: Setup Godot build cache
uses: ./.github/actions/godot-cache
with:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- name: Setup python and scons
uses: ./.github/actions/godot-deps
- name: Compilation
uses: ./.github/actions/godot-build
with:
sconsflags: ${{ env.SCONSFLAGS }}
platform: windows
target: ${{ matrix.target }}
tools: ${{ matrix.tools }}
scons-cache-limit: 3072
- name: Upload artifact
uses: ./.github/actions/upload-artifact
with:
name: ${{ matrix.cache-name }}

147
.gitignore vendored
View File

@@ -1,6 +1,29 @@
# Godot auto generated files
*.gen.*
.import/
platform/server/logo.h
platform/android/logo.h
platform/bb10/logo.h
platform/iphone/logo.h
platform/javascript/logo.h
platform/osx/logo.h
platform/windows/logo.h
platform/x11/logo.h
drivers/gles2/shaders/*.h
modules/register_module_types.cpp
core/version.h
core/method_bind.inc
core/method_bind_ext.inc
core/script_encryption_key.cpp
core/global_defaults.cpp
drivers/unix/os_unix_global_settings_path.cpp
tools/editor/register_exporters.cpp
tools/editor/doc_data_compressed.h
tools/editor/certs_compressed.h
tools/editor/editor_icons.cpp
tools/editor/translations.h
tools/editor/builtin_fonts.h
.fscache
make.bat
log.txt
# Documentation generated by doxygen or from classes.xml
doc/_build/
@@ -8,20 +31,16 @@ doc/_build/
# Javascript specific
*.bc
# CLion
cmake-build-debug
# Android specific
.gradle
local.properties
*.iml
.idea
.gradletasknamecache
project.properties
platform/android/java/app/libs/*
platform/android/java/build.gradle
platform/android/java/.gradle
platform/android/java/.gradletasknamecache
platform/android/java/local.properties
platform/android/java/project.properties
platform/android/java/build.gradle
platform/android/java/AndroidManifest.xml
platform/android/java/libs/*
platform/android/java/lib/.cxx/
platform/android/java/nativeSrcsConfigs/.cxx/
platform/android/java/assets
# General c++ generated files
*.lib
@@ -34,57 +53,29 @@ platform/android/java/nativeSrcsConfigs/.cxx/
*.os
*.Plo
*.lo
# Binutils tmp linker output of the form "stXXXXXX" where "X" is alphanumeric
st[A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9]
# Libs generated files
.deps/*
.dirstamp
# Gprof output
gmon.out
# Vim temp files
*.swo
*.swp
# Qt project files
# QT project files
*.config
*.creator
*.creator.*
*.files
*.includes
*.cflags
*.cxxflags
# Code::Blocks files
*.cbp
*.layout
*.depend
# Eclipse CDT files
.cproject
.settings/
*.pydevproject
*.launch
# Geany/geany-plugins files
*.geany
.geanyprj
# Jetbrains IDEs
.idea/
# Misc
.DS_Store
__MACOSX
logs/
# for projects that use SCons for building: http://http://www.scons.org/
.sconf_temp
.sconsign*.dblite
.sconsign.dblite
*.pyc
# https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
@@ -96,9 +87,6 @@ logs/
*.sln
*.vcxproj*
# Custom SCons configuration override
/custom.py
# Build results
[Dd]ebug/
[Dd]ebugPublic/
@@ -108,19 +96,11 @@ build/
bld/
[Bb]in/
[Oo]bj/
*.debug
*.dSYM
# Visual Studio cache/options directory
.vs/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# Hints for improving IntelliSense, created together with VS project
cpp.hint
#NUNIT
*.VisualState.xml
TestResult.xml
@@ -144,7 +124,6 @@ TestResult.xml
*.tlh
*.tmp
*.tmp_proj
*.bak
*.log
*.vspscc
*.vssscc
@@ -152,7 +131,6 @@ TestResult.xml
*.pidb
*.svclog
*.scc
*.nib
# Chutzpah Test files
_Chutzpah*
@@ -165,9 +143,7 @@ ipch/
*.sdf
*.cachefile
*.VC.db
*.VC.opendb
*.VC.VC.opendb
enc_temp_folder/
# Visual Studio profiler
*.psess
@@ -260,23 +236,13 @@ ClientBin/
*.pfx
*.publishsettings
node_modules/
__pycache__/
# KDE
.directory
# Kdevelop project files
#Kdevelop project files
*.kdev4
# Kate swap files
*.kate-swp
# Xcode
xcuserdata/
*.xcscmblueprint
*.xccheckout
*.xcodeproj/*
# RIA/Silverlight projects
Generated_Code/
@@ -304,19 +270,11 @@ FakesAssemblies/
# =========================
# Windows image file caches
[Tt]humbs.db
[Tt]humbs.db:encryptable
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Windows stackdumps
*.stackdump
# Windows shortcuts
*.lnk
# Folder config file
[Dd]esktop.ini
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
@@ -328,7 +286,6 @@ logo.h
TAGS
!TAGS/
tags
*.tags
!tags/
gtags.files
GTAGS
@@ -343,28 +300,6 @@ godot.creator.*
projects/
platform/windows/godot_res.res
# Visual Studio 2017 and Visual Studio Code workspace folder
/.vs
# Visual Studio Code folder (and files) that are created
# when the C/C++ extension (https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) is used
/.vscode
# Visual Studio Code workspace file
*.code-workspace
# Scons construction environment dump
.scons_env.json
# 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
# Cppcheck
*.cppcheck
# https://clangd.llvm.org/ cache folder
.clangd/
.cache/

148
.mailmap
View File

@@ -1,148 +0,0 @@
Aaron Record <aaronjrecord@gmail.com>
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>
Anish Bhobe <anishbhobe@hotmail.com>
Anutrix <numaanzaheerahmed@yahoo.com>
Aren Villanueva <arenvillanueva@yomogi-soft.com> <aren@displaysweet.com>
Ariel Manzur <ariel@godotengine.org>
Ariel Manzur <ariel@godotengine.org> <puntob@gmail.com>
Ariel Manzur <ariel@godotengine.org> <punto@godotengine.org>
Ariel Manzur <ariel@godotengine.org> <ariel@okamstudio.com>
Ariel Manzur <ariel@godotengine.org> <punto@Ariels-Mac-mini.local>
Ariel Manzur <ariel@godotengine.org> <punto@Ariels-Mac-mini-2.local>
Bastiaan Olij <mux213@gmail.com>
Benjamin <mafortion.benjamin@gmail.com>
Bernhard Liebl <Bernhard.Liebl@gmx.org> <poke1024@gmx.de>
Bernhard Liebl <Bernhard.Liebl@gmx.org> <poke1024@gmx.org>
Bruno Lourenço <madequa@users.noreply.github.com> <bmlourenco@gmail.com>
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>
dankan1890 <mewuidev2@gmail.com>
Daniel J. Ramirez <djrmuv@gmail.com>
David Cambré <david.cambre@gmail.com> <David.Cambre@gmail.com>
Dominik 'dreamsComeTrue' Jasiński <dominikjasinski@o2.pl>
Emmanuel Barroga <emmanuelbarroga@gmail.com>
Eric M <itsjusteza@gmail.com>
Eric Rybicki <info@ericrybicki.com> <stratos695@googlemail.com>
Erik Selecký <35656626+rxlecky@users.noreply.github.com>
Erik Selecký <35656626+rxlecky@users.noreply.github.com> <35656626+SeleckyErik@users.noreply.github.com>
Eveline Jarosz <marqin.pl@gmail.com>
Eveline Jarosz <marqin.pl@gmail.com> <marqin.pl+git@gmail.com>
Fabian <supagu@gmail.com>
Ferenc Arn <tagcup@yahoo.com>
Ferenc Arn <tagcup@yahoo.com> <tagcup@users.noreply.github.com>
foxydevloper <12120644+foxydevloper@users.noreply.github.com>
Fredia Huya-Kouadio <fhuyakou@gmail.com>
Fredia Huya-Kouadio <fhuyakou@gmail.com> <fhuya@google.com>
Geequlim <geequlim@gmail.com>
Gilles Roudiere <gilles.roudiere@gmail.com>
Gilles Roudiere <gilles.roudiere@gmail.com> <gilles.roudiere@laas.fr>
Gordon MacPherson <gordon@gordonite.tech>
Guilherme Felipe <guilhermefelipecgs@gmail.com>
Hanif Bin Ariffin <hanif.ariffin.4326@gmail.com>
HaSa1002 <johawitt@outlook.de>
Hein-Pieter van Braam-Stewart <hp@tmm.cx>
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>
Jake Young <young9003@gmail.com>
Jakub Grzesik <kubecz3k@gmail.com>
janglee <merupatel123@gmail.com>
Jean-Michel Bernard <jmb462@gmail.com>
Jérôme Gully <jerome.gully0@gmail.com>
JFonS <joan.fonssanchez@gmail.com>
Juan Linietsky <reduzio@gmail.com>
Juan Linietsky <reduzio@gmail.com> <juan@godotengine.org>
Juan Linietsky <reduzio@gmail.com> <juan@okamstudio.com>
Juan Linietsky <reduzio@gmail.com> <reduz@Juans-MBP.fibertel.com.ar>
Juan Linietsky <reduzio@gmail.com> <red@kyoko>
Julian Murgia <the.straton@gmail.com>
Kanabenki <lucien.menassol@gmail.com> <18357657+Kanabenki@users.noreply.github.com>
karroffel <therzog@mail.de>
karroffel <therzog@mail.de> <thomas.herzog@mail.com>
karroffel <therzog@mail.de> <thomas.herzog@simedis.com>
Kelly Thomas <kelly.thomas@hotmail.com.au>
Kongfa Waroros <gongpha@hotmail.com>
K. S. Ernest (iFire) Lee <ernest.lee@chibifire.com>
kleonc <9283098+kleonc@users.noreply.github.com> <kleonc@users.noreply.github.com>
Leon Krause <lk@leonkrause.com> <eska@eska.me>
Leon Krause <lk@leonkrause.com> <eska014@users.noreply.github.com>
Liz Haas <27thLiz@gmail.com>
Liz Haas <27thLiz@gmail.com> <liu.gam3@gmail.com>
Liz Haas <27thLiz@gmail.com> <hinsbart@gmail.com>
Liz Haas <27thLiz@gmail.com> <hinsbart@users.noreply.github.com>
Liz Haas <27thLiz@gmail.com> <entenflugstuhl@gmail.com>
Manuele Finocchiaro <m4nu3lf@gmail.com>
Manuel Strey <manuel.strey@gmx.de>
Marcel Admiraal <madmiraal@users.noreply.github.com>
Marcelo Fernandez <marcelofg55@gmail.com>
Marcin Zawiejski <dragmz@gmail.com>
Marcus Elg <marcusaccounts@yahoo.se>
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>
Mateo Kuruk Miccino <mateomiccino@gmail.com>
Max Hilbrunner <m.hilbrunner@gmail.com>
Max Hilbrunner <m.hilbrunner@gmail.com> <mhilbrunner@users.noreply.github.com>
Michael Alexsander <michaelalexsander@protonmail.com>
Nathan Franke <natfra@pm.me> <nathanwfranke@gmail.com>
Nathan Lovato <nathan@gdquest.com>
Nathan Warden <nathan@nathanwarden.com> <nathanwardenlee@icloud.com>
Nicholas Huelin <62965063+SirQuartz@users.noreply.github.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>
Pawel Kowal <pkowal1982@gmail.com>
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>
Rafał Mikrut <mikrutrafal@protonmail.com>
Rafał Mikrut <mikrutrafal@protonmail.com> <mikrutrafal54@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>
Ricardo Subtil <ricasubtil@gmail.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>
Silc 'Tokage' Renew <tokage.it.lab@gmail.com>
Silc 'Tokage' Renew <tokage.it.lab@gmail.com> <61938263+TokageItLab@users.noreply.github.com>
Swarnim Arun <swarnimarun11@gmail.com>
Theo Hallenius <redsymbzone@hotmail.com>
Tomasz Chabora <kobewi4e@gmail.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>
Yuri Sizov <yuris@humnom.net> <pycbouh@users.noreply.github.com>
Zae <zaevi@live.com>
Zak Stam <zakscomputers@hotmail.com>
Zher Huei Lee <lee.zh.92@gmail.com>

78
.travis.yml Normal file
View File

@@ -0,0 +1,78 @@
language: cpp
sudo: false
compiler:
- gcc
- clang
os:
- linux
- osx
env:
- GODOT_TARGET=iphone
- GODOT_TARGET=osx
- GODOT_TARGET=x11
- GODOT_TARGET=android
- GODOT_TARGET=windows
matrix:
exclude:
- os: linux
env: GODOT_TARGET=iphone
- os: linux
env: GODOT_TARGET=osx
- os: linux
env: GODOT_TARGET=android
- os: osx
env: GODOT_TARGET=x11
- os: osx
env: GODOT_TARGET=windows
- compiler: gcc
env: GODOT_TARGET=iphone
- compiler: gcc
env: GODOT_TARGET=osx
- compiler: clang
env: GODOT_TARGET=android
- compiler: clang
env: GODOT_TARGET=windows
- compiler: clang
env: GODOT_TARGET=x11
addons:
apt:
packages:
- build-essential
- scons
- pkg-config
- libx11-dev
- libxcursor-dev
- libasound2-dev
- libfreetype6-dev
- libgl1-mesa-dev
- libglu1-mesa-dev
- libssl-dev
- libxinerama-dev
- libxrandr-dev
# 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
before_script:
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; brew install scons; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$GODOT_TARGET" = "android" ]; then
brew update; travis_wait 20 brew install -v android-sdk;
travis_wait 20 brew install -v android-ndk | grep -v "inflating:" | grep -v "creating:";
export ANDROID_HOME=/usr/local/opt/android-sdk; export ANDROID_NDK_ROOT=/usr/local/opt/android-ndk;
fi
script:
- scons platform=$GODOT_TARGET CXX=$CXX openssl=builtin

View File

@@ -1,241 +0,0 @@
# Godot Engine authors
Godot Engine is developed by a community of voluntary contributors who
contribute code, bug reports, documentation, artwork, support, etc.
It is impossible to list them all; nevertheless, this file aims at listing
the developers who contributed significant patches to this MIT licensed
source code. "Significant" is arbitrarily decided, but should be fair :)
GitHub usernames are indicated in parentheses, or as sole entry when no other
name is available.
## Project Founders
Juan Linietsky (reduz)
Ariel Manzur (punto-)
## Lead Developer
Juan Linietsky (reduz)
## Project Manager
Rémi Verschelde (akien-mga)
## Developers
(in alphabetical order, with over 10 commits excluding merges)
Aaron Franke (aaronfranke)
Aaron Record (LightningAA)
Alexander Holland (AlexHolly)
Alexey Khoroshavin (allkhor)
Alket Rexhepi (alketii)
Andrea Catania (AndreaCatania)
Andrii Doroshenko (Xrayez)
Andy Moss (MillionOstrich)
Angad Kambli (angad-k)
Anilforextra (AnilBK)
Anish Bhobe (KidRigger)
Anton Yabchinskiy (a12n)
Anutrix
Aren Villanueva (kurikaesu)
Ariel Manzur (punto-)
Bartłomiej T. Listwon (Listwon)
Bastiaan Olij (BastiaanOlij)
Ben Brookshire (sheepandshepherd)
Benjamin Larsson (Nallebeorn)
Bernhard Liebl (poke1024)
Bhuvan Vemula (Bhu1-V)
Błażej Szczygieł (zaps166)
Bojidar Marinov (bojidar-bg)
Brian Semrau (briansemrau)
Bruno Lourenço (MadEqua)
bruvzg
Cameron Reikes (creikey)
Camille Mohr-Daurat (pouleyKetchoupp)
Caner Demirer (cdemirer)
Carl Olsson (not-surt)
Carter Anderson (cart)
Chris Bradfield (cbscribe)
Clay John (clayjohn)
Dana Olson (adolson)
Daniel J. Ramirez (djrm)
Daniel Rakos (aqnuep)
dankan1890
Danil Alexeev (dalexeev)
David Cambré (Gallilus)
David Sichma (DavidSichma)
David Snopek (dsnopek)
Dharkael (lupoDharkael)
Dmitry Koteroff (Krakean)
Dominik Jasiński (dreamsComeTrue)
DualMatrix
Ellen Poe (ellenhp)
Emmanuel Barroga (codecustard)
Emmanuel Leblond (touilleMan)
Eoin O'Neill (Eoin-ONeill-Yokai)
Eric Lasota (elasota)
Eric M (EricEzaM)
Eric Rybicki (ericrybick)
Erik Selecký (rxlecky)
est31
Eveline Jarosz (Marqin)
Fabian Mathews (supagu)
Fabio Alessandrelli (Faless)
fabriceci
Ferenc Arn (tagcup)
follower
foxydevloper
François Belair (Razoric480)
Franklin Sobrinho (TheHX)
Fredia Huya-Kouadio (m4gr3d)
Geequlim
George Marques (vnen)
Gerrit Großkopf (Grosskopf)
Gilles Roudiere (groud)
Gordon MacPherson (RevoluPowered)
Guilherme Felipe de C. G. da Silva (guilhermefelipecgs)
Hanif Bin Ariffin (hbina)
Haoyu Qiu (timothyqiu)
Hein-Pieter van Braam-Stewart (hpvb)
Hendrik Brucker (Geometror)
hilfazer
Hiroshi Ogawa (hi-ogawa)
homer666
hoontee
Hugo Locurcio (Calinou)
Ian Bishop (ianb96)
Ibrahn Sahir (ibrahn)
Ignacio Etcheverry (neikeq)
Ilaria Cislaghi (QbieShay)
Indah Sylvia (ISylvox)
J08nY
Jake Young (Duroxxigar)
Jakub Grzesik (kubecz3k)
James Buck (jbuck3)
Jean-Michel Bernard (jmb462)
Jérôme Gully (Nutriz)
Jia Jun Chai (SkyLucilfer)
Joan Fons Sanchez (JFonS)
Johannes Witt (HaSa1002)
Johan Manuel (29jm)
Jordan Schidlowsky (winterpixelgames)
Joshua Grams (JoshuaGrams)
Juan Linietsky (reduz)
Julian Murgia (StraToN)
Julien Nguyen (Blackiris)
Jummit
Justo Delgado (mrcdk)
karroffel
Kelly Thomas (KellyThomas)
kleonc
Kongfa Waroros (gongpha)
Kostadin Damyanov (Max-Might)
K. S. Ernest (iFire) Lee (fire)
lawnjelly
Leon Krause (leonkrause)
Liz Haas (27thLiz)
Lucien Menassol (Kanabenki)
Lyuma
Maganty Rushyendra (mrushyendra)
Manuele Finocchiaro (m4nu3lf)
Marcel Admiraal (madmiraal)
Marcelo Fernandez (marcelofg55)
Marc Gilleron (Zylann)
Marcin Zawiejski (dragmz)
Marcus Brummer (mbrlabs)
Marcus Elg (MCrafterzz)
Mariano Javier Suligoy (MarianoGnu)
Mario Schlack (hurikhan)
Marios Staikopoulos (marstaik)
Markus Sauermann (Sauermann)
Martin Capitanio (capnm)
Martin Liška (marxin)
Martin Sjursen (binbitten)
marynate
Masoud BH (masoudbh3)
Mateo Kuruk Miccino (kuruk-mm)
Matthew (skyace65)
Matthias Hölzl (hoelzl)
Max Hilbrunner (mhilbrunner)
merumelu
Meru Patel (Janglee123)
Michael Alexsander (YeldhamDev)
MichiRecRoom (LikeLakers2)
Morris "Tabor" Arroad (mortarroad)
mrezai
Muhammad Huri (CakHuri)
muiroc
Nathan Franke (nathanfranke)
Nathan Lovato (NathanLovato)
Nathan Warden (NathanWarden)
Nicholas Huelin (SirQuartz)
Nils André-Chang (NilsIrl)
Noah Beard (TwistedTwigleg)
Nuno Donato (nunodonato)
Omar El Sheikh (The-O-King)
Ovnuniarchos
Pascal Richter (ShyRed)
Patrick (firefly2442)
Paul Batty (Paulb23)
Paul Joannon (paulloz)
Paul Trojahn (ptrojahn)
Pawel Kowal (pkowal1982)
Pawel Lampe (Scony)
Pedro J. Estébanez (RandomShaper)
Pieter-Jan Briers (PJB3005)
Poommetee Ketson (Noshyaar)
Przemysław Gołąb (n-pigeon)
Rafael M. G. (rafallus)
Rafał Mikrut (qarmin)
Ralf Hölzemer (rollenrolm)
Ramesh Ravone (RameshRavone)
Raphael2048
Raul Santos (raulsntos)
Ray Koopa (RayKoopa)
Rémi Verschelde (akien-mga)
Rhody Lugo (rraallvv)
Ricardo Buring (rburing)
Ricardo Subtil (Ev1lbl0w)
Roberto F. Arroyo (robfram)
Robin Hübner (profan)
romulox-x
Ruslan Mustakov (endragor)
Ryan Roden-Corrent (rrcore)
Saniko (sanikoyes)
santouits
SaracenOne
Sergey Minakov (naithar)
sersoong
Shiqing (kawa-yoiko)
Silc 'Tokage' Renew (TokageItLab)
Simon Wenner (swenner)
Stijn Hinlopen (hinlopen)
Swarnim Arun (minraws)
TC (floppyhammer)
Thakee Nathees (ThakeeNathees)
thebestnom
Theo Hallenius (TheoXD)
Timo Schwarzer (timoschwarzer)
Timo (toger5)
Tomasz Chabora (KoBeWi)
trollodel
Twarit Waikar (IronicallySerious)
Umang Kalra (theoway)
Vinzenz Feenstra (vinzenz)
박한얼 (volzhs)
V. Vamsi Krishna (vkbsb)
Wilhem Barbier (nounoursheureux)
William Deurwaarder (williamd67)
Will Nations (willnationsdev)
Wilson E. Alvarez (Rubonnek)
Xavier Cho (mysticfall)
yg2f (SuperUserNameMan)
Yuri Rubinsky (Chaosus)
Yuri Sizov (pycbouh)
Zae Chao (zaevi)
Zak Stam (zaksnet)
Zher Huei Lee (leezh)
ZuBsPaCe

File diff suppressed because it is too large Load Diff

View File

@@ -1,236 +1,59 @@
# How to contribute efficiently
## Table of contents
- [Reporting bugs](#reporting-bugs)
- [Proposing features or improvements](#proposing-features-or-improvements)
- [Contributing pull requests](#contributing-pull-requests)
- [Contributing to Godot's translation](#contributing-to-godots-translation)
- [Communicating with developers](#communicating-with-developers)
**Please read the first section before reporting a bug!**
## Reporting bugs
## Reporting bugs or proposing features
The golden rule is to **always open *one* issue for *one* bug**. If you notice
several bugs and want to report them, make sure to create one new issue for
each of them.
The golden rule is to **always open *one* issue for *one* bug**. If you notice several bugs and want to report them, make sure to create one new issue for each of them.
If you're reporting a new bug, you'll make our life simpler (and the
fix will come sooner) by following these guidelines:
Everything refered to hereafter as "bug" also applies for feature requests.
### Search first in the existing database
If you are reporting a new issue, you will make our life much simpler (and the fix come much sooner) by following those guidelines:
Issues are often reported several times by various users. It's good practice to
**search first in the [issue tracker](https://github.com/godotengine/godot/issues)
before reporting your issue**. If you don't find a relevant match or if you're
unsure, don't hesitate to **open a new issue**. The bugsquad will handle it
from there if it's a duplicate.
#### Search first in the existing database
### Specify the platform
Issues are often reported several times by various users. It's a good practice to **search first** in the issues database before reporting your issue. If you don't find a relevant match or if you are unsure, don't hesitate to **open a new issue**. The bugsquad will handle it from there if it's a duplicate.
Godot runs on a large variety of platforms and operating systems and devices.
**In your bug reports, please always specify:**
#### Specify the platform
Godot runs on a large variety of platforms and operating systems and devices. If you believe your issue is device/platform dependent (for example if it is related to the rendering, crashes or compilation errors), please specify:
* Operating system
* Device (including architecture, e.g. x86, x86_64, arm, etc.)
* GPU model (and driver in use if you know it)
- Operating system and version (e.g. Windows 10, macOS 10.15, Ubuntu 19.10)
- Godot version (e.g. 3.2, 3.1.2, or the Git commit hash if you're using a development branch)
#### Specify steps to reproduce
For bugs that are likely OS-specific and/or graphics-related, please also specify:
Many bugs can't be reproduced unless specific steps are taken. Please **specify the exact steps** that must be taken to reproduce the condition, and try to keep them as minimal as possible.
- Device (CPU model including architecture, e.g. x86, x86_64, ARM, etc.)
- GPU model (and the driver version in use if you know it)
#### Provide a simple, example project
**Bug reports not including the required information may be closed at the
maintainers' discretion.** If in doubt, always include all the requested
information; it's better to include too much information than not enough
information.
Sometimes an unexpected behavior happens in your project. In such case, understand that:
### Specify steps to reproduce
Many bugs can't be reproduced unless specific steps are taken. Please **specify
the exact steps** that must be taken to reproduce the condition, and try to
keep them as minimal as possible. If you're describing a procedure to follow
in the editor, don't hesitate to include screenshots.
Making your bug report easy to reproduce will make it easier for contributors
to fix the bug.
### Provide a simple, example project
Sometimes, unexpected behavior can happen in your project. In such case,
understand that:
- What happens to you may not happen to other users.
- We can't take the time to look at your project, understand how it is set up
and then figure out why it's failing.
To speed up our work, **please upload a minimal project** that isolates
and reproduces the issue. This is always the **best way for us to fix it**.
We recommend attaching a ZIP file with the minimal project directly to the bug report,
by drag and dropping the file in the GitHub edition field. This ensures the file
can remain available for a long period of time. Only use third-party file hosts
if your ZIP file isn't accepted by GitHub because it's too large.
We recommend always attaching a minimal reproduction project, even if the issue
may seem simple to reproduce manually.
**If you've been asked by a maintainer to upload a minimal reproduction project,
you *must* do so within 7 days.** Otherwise, your bug report will be closed as
it'll be considered too difficult to diagnose.
Now that you've read the guidelines, click the link below to create a
bug report:
- **[Report a bug](https://github.com/godotengine/godot/issues/new?assignees=&labels=&template=bug_report.yml)**
## Proposing features or improvements
**Since August 2019, the main issue tracker no longer accepts feature proposals.**
Instead, head to the [Godot Proposals repository](https://github.com/godotengine/godot-proposals)
and follow the instructions in the README file. High-quality feature proposals
are more likely to be well-received by the maintainers and community, so do
your best :)
See [this article](https://godotengine.org/article/introducing-godot-proposals-repository)
for detailed rationale on this change.
* What happens to you may not happen to other users.
* We can't take the time to look at your project, understand how it is set up and then figure out why it's failing.
To speed up our work, please prepare for us **a simple project** that isolates and reproduces the issue. This is always the **the best way for us to fix it**. You can attach a zip file with the minimal project directly to the bug report, by drag and dropping the file in the GitHub edition field.
## Contributing pull requests
If you want to add new engine features, please make sure that:
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.
- You talked to other developers on how to implement it best. See also
[Proposing features or improvements](#proposing-features-or-improvements).
- Even if it doesn't get merged, your PR is useful for future work by another
developer.
* This functionality is desired.
* You talked to other developers on how to implement it best (on either communication channel, and maybe in a GitHub issue first before making your PR).
* Even if it does not get merged, your PR is useful for future work by another developer.
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.
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.
#### Be nice to the git history
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.
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.
The [Contributing docs](https://docs.godotengine.org/en/latest/community/contributing/index.html)
also have important information on the PR workflow and the code style we use.
When updating your fork with upstream changes, please use ``git pull --rebase`` to avoid creating "merge commits". Those commits unnecessarily pollute the git history when coming from PRs.
### Document your changes
Also try to make commits that bring the engine from one stable state to another stable state, i.e. if your first commit has a bug that you fixed in the second commit, try to merge them together before making your pull request (see ``git rebase -i`` and relevant help about rebasing or ammending commits on the Internet).
If your pull request adds methods, properties or signals that are exposed to
scripting APIs, you **must** update the class reference to document those.
This is to ensure the documentation coverage doesn't decrease as contributions
are merged.
This git style guide has some good practices to have in mind: https://github.com/agis-/git-style-guide
[Update the documentation template](https://docs.godotengine.org/en/latest/community/contributing/updating_the_class_reference.html#updating-the-documentation-template)
using your compiled binary, then fill in the descriptions.
Follow the style guide described in the
[Docs writing guidelines](https://docs.godotengine.org/en/latest/community/contributing/docs_writing_guidelines.html).
Thanks!
If your pull request modifies parts of the code in a non-obvious way, make sure
to add comments in the code as well. This helps other people understand the
change without having to look at `git blame`.
### 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.
When updating your fork with upstream changes, please use ``git pull --rebase``
to avoid creating "merge commits". Those commits unnecessarily pollute the git
history when coming from PRs.
Also try to make commits that bring the engine from one stable state to another
stable state, i.e. if your first commit has a bug that you fixed in the second
commit, try to merge them together before making your pull request (see ``git
rebase -i`` and relevant help about rebasing or amending commits on the
Internet).
This [Git style guide](https://github.com/agis-/git-style-guide) has some
good practices to have in mind.
See our [PR workflow](https://docs.godotengine.org/en/latest/community/contributing/pr_workflow.html)
documentation for tips on using Git, amending commits and rebasing branches.
### Format your commit messages with readability in mind
The way you format your commit messages is quite important to ensure that the
commit history and changelog will be easy to read and understand. A Git commit
message is formatted as a short title (first line) and an extended description
(everything after the first line and an empty separation line).
The short title is the most important part, as it is what will appear in the
`shortlog` changelog (one line per commit, so no description shown) or in the
GitHub interface unless you click the "expand" button. As the name says, try to
keep that first line under 72 characters. It should describe what the commit
does globally, while details would go in the description. Typically, if you
can't keep the title short because you have too much stuff to mention, it means
you should probably split your changes in several commits :)
Here's an example of a well-formatted commit message (note how the extended
description is also manually wrapped at 80 chars for readability):
```text
Prevent French fries carbonization by fixing heat regulation
When using the French fries frying module, Godot would not regulate the heat
and thus bring the oil bath to supercritical liquid conditions, thus causing
unwanted side effects in the physics engine.
By fixing the regulation system via an added binding to the internal feature,
this commit now ensures that Godot will not go past the ebullition temperature
of cooking oil under normal atmospheric conditions.
Fixes #1789, long live the Realm!
```
**Note:** When using the GitHub online editor or its drag-and-drop
feature, *please* edit the commit title to something meaningful. Commits named
"Update my_file.cpp" won't be accepted.
## Contributing to Godot's translation
You can contribute to Godot's translation from the [Hosted
Weblate](https://hosted.weblate.org/projects/godot-engine/godot), an open
source and web-based translation platform. Please refer to the [translation
readme](editor/translations/README.md) for more information.
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
channels](https://godotengine.org/community), some used more for user-level
discussions and support, others more for development discussions.
To communicate with developers (e.g. to discuss a feature you want to implement
or a bug you want to fix), the following channels can be used:
- [Godot Contributors Chat](https://chat.godotengine.org): You will
find most core developers there, so it's the go-to platform for direct chat
about Godot Engine development. Feel free to start discussing something there
to get some early feedback before writing up a detailed proposal in a GitHub
issue.
- [Bug tracker](https://github.com/godotengine/godot/issues): If there is an
existing issue about a topic you want to discuss, just add a comment to it -
many developers watch the repository and will get a notification. You can
also create a new issue - please keep in mind to create issues only to
discuss quite specific points about the development, and not general user
feedback or support requests.
- [Feature proposals](https://github.com/godotengine/godot-proposals/issues):
To propose a new feature, we have a dedicated issue tracker for that. Don't
hesitate to start by talking about your idea on the Godot Contributors Chat
to make sure that it makes sense in Godot's context.
Thanks for your interest in contributing!
—The Godot development team
The Godot development team

File diff suppressed because it is too large Load Diff

845
DONORS.md
View File

@@ -1,845 +0,0 @@
# Donors to the Godot Engine project
Godot Engine is a non-profit project developed by a community of voluntary
contributors, as well as occasional paid contributors thanks to the financial
support of generous donors.
The ways to donate to the project, as well as details on how the funds are
used, are described on [Godot's website](https://godotengine.org/donate).
The following is a list of the current monthly donors, who will have their
generous deed immortalized in the next stable release of Godot Engine.
## Platinum sponsors
Gamblify <https://www.gamblify.com>
Spiffcode <http://spiffcode.com>
## Gold sponsors
None currently, become one! <https://godotengine.org/donate>
## Silver sponsors
ASIFA-Hollywood <https://www.asifa-hollywood.org>
ORE System <https://ore-system.com>
## Bronze sponsors
Ben Nolan
Brandon Lamb
Bri
Daniel Kaplan
Garry Newman
Gordon MacPherson
Hunter Dickson
Kitcat490
Kyle Szklenski
Maxim Karsten
Moonwards <https://www.moonwards.com>
TrampolineTales <https://trampolinetales.com>
## Mini sponsors
AD Ford
Andres Hernandez
Andrew Bowen
Andrew Dunai
anti666
Christian Baune
Christopher Montesano
Christopher Shifflett
Daniel Edwards
Darrin Massena
David Mydlarz
Digital Grows
Dov Zimring
Edward Flick
Florian Neumann
Gamechuck
GameDev.net
Hein-Pieter van Braam
Jasper Brooks
Jeffery Chiu
John G Gentzel
Jonah Stich
Justin Arnold
Justo Delgado Baudí
Kossi Selom Banybah
Marcel Kräml
Marek Belski
Markus Ort
Matthieu Huvé
Michael
Mike King
Nassor Paulino da Silva
Nathan Warden
Neal Gompa (Conan Kudo)
Ninja_5tyl3
Patrick Horn
Patrick Schmidt
Rami
Relintai
Ronnie Cheng
ShikadiGum
Slobodan Milnovic
Stephan Lanfermann
Steve
Thomas Krampl
Violin Iliev
Vladimír Chvátil
## Gold donors
Acheron
Adam Brown
albinaask
Arisaka Mayuki
Asher Glick
Barugon
Benito
Carlo Cabanilla
Daniel James
David Gehrig
David Hubber
David Snopek
Ed Morley
First Last
Florian Rämisch
Hunter Jones
Jacobus Dens
Jakub Grzesik
Javier Roman
Joan Fons
Jonathan Wright
Jon Woodward
Karl Werf
Kevin Vu
Klavdij Voncina
Maciej Pendolski
Manuele Finocchiaro
Markus Wiesner
Mateo Navarrete
Mathieu
Matthew Hillier
Officine Pixel S.n.c.
Pedro Silva
Retro Village
Rob Messick
Roland Fredenhagen
Ronan Zeegers
Sarksus
Sean
Sergey
Sofox
Stephan Kessler
Stephen Molyneaux
Taylor Ritenour
Tom Langwaldt
Tricky Fat Cat
tukon
Vagabond Arcade
Victor
Xeno Coliseum
Adam Mill
Adam Nakonieczny
Adam Nelson
Adrian Adamiak
Alexander Erlemann
Alexander J Maynard
Alex Khayrullin
alice gambrell
Amar Šahinović
Andrew Cunningham
Andrew Farr
Andriy
Antanas Paskauskas
Antoni Batchelli
Arch Henderson III
Arthur S. Muszynski
c64cosmin
Cameron Connolly
Charlie Whitfield
Chase Taranto
Chris Petrich
Chris Serino
Craig Ostrin
Craig Scarborough
Craig Smith
Cristopher
CzechBlueBear
D
DagobertDick
dan didenko
Daniel
Daniel Hernández Alcojor
Daniel Tebbutt
Darrian Little
Daylon
Dennis Belfrage
Dev To be curious
Dima Fedotov
Dimitri Nüscheler
Dmitriy Khudorozhkov
Donn Eddy
Douglas Hammond
EerieExpanse
Eric Brand
Eugenio Hugo Salgüero Jáñez
EXUREI
Felix Winterhalter
flesk
foxydevloper
Fransiska
Freeman
Gabrielius Vaiškūnas
Gary Hulst
gavlig
Geoffroy Warin
GGGames.org
gisora
GrayDwarf
Guilherme Felipe de C. G. da Silva
Harry Tumber
Harvey Fong
Heath Hayes
Horváth-Lázár Péter
Hu Hund
Hunter Barabas
HurrieCrane
Jamal Bencharki
James Couzens
Jan Sælid
Jared
Jared White
Jean-Sébastien Ross
Jennifer Wilcox
Jeremi Biernacki
Jesús Chicharro
Joel Fivat
Johnathan Kupferer
Josef Stumpfegger
Jose Malheiro
Jose Manuel Muñoz Perez
Joshie Sparks
Joshua Flores
Joshua Lesperance
Juan Velandia
Judd
Julián Absatz
Julian Todd
Juraj Móza
JUSTIN CARROLL
Kelteseth
kickmaniac
kinfox
Kos
Lakshaya Goel
Laszlo Kiss
leetNightshade
Leo Fidel R Liban
Liam Smyth
LoparPanda
LordZaruflex
Luca Vazzano
Luke
MadScientistCarl
Marcus Dobler
Marcus Richter
Mark Barrett
Martin Eigel
Martin Gulliksson
Martin Kotz
Martin Soucek
matt
Matt Greene
Matthew Hall
Max Kryschi
medecau
Michael Dürwald
Michael Policastro
Miika Moilanen
MikadoSC
Mike Barbee
nate etan
Nick Abousselam
Nicola Cocchiaro
Nicolás Carrasco
Oliver Dick
Oscar Campos
Paul Hocker
Paul Von Zimmerman
Pavel Kotlyar
Pete Goodwin
Peter Richmond
Petr Malac
PhaineOfCatz
Rafał Michno
Raymond Harris
Reilt
Rene Tailleur
Rhodochrone
Rickard Hermanson
Rob
Robert McDermott
Robert Willes
Rob McInroy
Rocknight Studios
RodZilla
Romeo Disca
Ronnie Ashlock
Ronny Mühle
Russ
Ryan Breaker
Ryan Heath
Ryan Scott
Samuel Hummerstone
Samuel Judd
Sean Morgan
Sebastian Hutter
Serban Serafimescu
Sergey Fonaryov
Sergey Minakov
Shishir Tandale
Sing Chun Lee
SKison
Song Junwoo
spacechase0
Stephan Hennion
Stephen Brown
Steven Landow
Stoned Xander
Super Izzo
Sven F.
Thomas Bjarnelöf
Thomas Kurz
Timothy van der Valk
Tobias Bocanegra
Tobias Raggl
Todd Smith
Tom Wor
Torbulous
toto bibi
Troy Kinsella
Turntsnaco
Valryia
Vincent Cloutier
VoidPointer
Winston
Wojciech Chojnacki
xzibiting
Yifan Lai
Yuancheng Zhang
Артём Равбецкий
## Silver donors
1D_Inc
Aaron Oldenburg
A. B.
Adam Brunnmeier
Adam Carr
Adam Long
Adam McCurdy
Adam N Webber
Adam Smeltzer
Adam Szymański
Adisibio
Adrien de Pierres
Agustinus Arya
Aidan O'Flannagain
Aki Mimoto
Alan Beauchamp
Albert Gyulgazyan
Alberto Salazar Muñoz
Alberto Vilches
Alder Stefano
Alejandro Saucedo
AleMax
Ales Jelovcan
Alessandro Senese
Alex Chan
Alex Clavelle
alex raeside
Alex (Well Done Games)
Allan Davis
Allen Schade
Andre Altmueller
Andre Stackhouse
Andrew Groot
andrew james morris
Andrew Thomas
angrykoala
Ano Nim
Anthony Avina
Anton Bouwer
Antti Vesanen
Arch Toasty
Arda Erol
Arseniy M
Arthur Brainville
Arturo Rosales
Ashley Claymore
Aubrey Falconer
Auré Franky
aurelien condomines
AzulCrescent
b110110
Balázs Batári
Beau Seymour
Behzad Ghaffari
Benedikt
Ben Ridley
Ben Vercammen
Bernd Jänichen
Bernhard Werner
Bill Thibault
bitbrain
Bjarne Voigtländer
Black Block
Blair Allen
Blunderjack
Bobby CC Wong
Brad Harms
Bram
Brandon
Brian Klein
Brodie Fairhall
Bronson Zgeb
Burney Waring
Caleb Gartner
Caleb Makela
Caliburn
Cameron Meyer
Carlos Rios
Carl van der Geest
Casey
Cassidy James
Chad Steadman
Checkpoint Charlie
ChrBohm
Chris Jagusch
Chris Langford
Christian Mauduit
Christian Winter
Christoffer Dahlblom
Christophe Gagnier
Christopher Chin
Christoph Woinke
Codecat
Cody Parker
Conall O
Conner Lane
Corchari
Corey W
Craig Post
Dakota Watkins
Daniel Cheney
Daren Scot Wilson
Dave Walker
David Baker
David Bôle
David May
David Maziarka
David Rapisarda
Devin Carraway
Diego Pereira
Dimitri Roche
Dmytro Korchynskyi
Dominik Wetzel
Don B
Douglas Plumley
Dragontrapper
Dr Ewan Murray
Ducky
Duobix
Duodecimal
Eduardo Teixeira
Edward Herbert
Edward Swartz
Egon Elbre
Elgenzay
Elias Nykrem
Emerson MX
Ephemeral
Eric Stokes
Eric Walkingshaw
Eric Williams
Erika Sanders
Erkki Seppälä
Ewan Holmes
Faisal Alkubaisi
Fault Boy
fby
Fekinox
Felix Adam
Felix Bohmann
Fer DC
Filip Lundby
Francisco Garcia Florez
Frank
freakazoid
FrostMarble
Game Endeavor
Garett Bass
Gary Thomas
gebba
George Marques
Green Fox
Greg Lincoln
Greg Olson
Greyson Richey
Grid
Grominet
Guillaume Pham Ngoc
Guldoman
Guo Hongci
gurehamu
Hal A
Haplo
Hayden Foley
Heribert Hirth
Hinken
Ian Richard Kunert
Ian Williams
Idilio Alfaro
IndustrialRobot
Ivan Nikolaev
iveks
izzy neuhaus
Jackson Harmer
Jacob D
Jaguar
Jake D
Jake Huxell
Jako Danar
James
James A F Manley
James Gary
James Guardino
James Quincy
James Thomas
Jamie Massey
Janis Skuja
Jan Vetulani
Japortie
JARKKO PARVIAINEN
Jason Bolton
Jason Evans
Jason Uechi
Jason Yundt
Jeff Hungerford
Jeffrey Berube
Jennifer Graves
Jesse Dubay
Jim Engstrand
Joe Hurdle
Joe Klemmer
Joel Höglund
John Anders Stav
John Bruce
John Gabriel
Jonas
Jonas Arndt
Jonas Bernemann
Jonas Rudlang
Jonas Yamazaki
Jonatan R
Jonathan Bieber
Jonathan Ellis
Jonathan G
Jonathan Turner
Jon Bonazza
Jon Sully
Jordan West
Jordy Goodridge
Jorge Antunes
Jorge Araya Navarro
Jose Francisco 'Yiro' Vera Girona
Joseph Catrambone
Josh P
Josh Taylor
Joshua Heidrich
Joshua Segall
jromkjrom
Juanfran
Juan Maggi
Juan Uys
Jueast
Julian le Roux
Julian Murgia
June Little
Justin Hamilton
Justin Oaksford
Justin Spedding
KaDokta
Karol Wojtasiuk (Drakonter)
Katsuomi Kobayashi
Keedong Park
keeganstoybox
Keinan Powers
Keith Bradner
Kenji Kawabata
Ken Minardo
Kent Jofur
Kerotasma
Ketafuki
Kiri Jolly
Kodera Software
Kolandrious
Kquona
Krishna Nadoor
Kristian Nygaard Jensen
KR McGinley
Kronarq
KsyTek Games
kycho
Kyle Burnett
Kyle Jacobs
Kyuppin
La diagonale du poulpe
Lasse le Dous
Laurent CHEA
Laurent Dethoor
Laxman Pradhan
Leland Vakarian
LEMMiNO
Leonardo Dimano
Linus Lind Lundgren
Logan Apple
Ludovic DELVAL
Luigi Renna
Luis Gaemperle
Luke Kasz
LunaticInAHat
Major Haul
Malcolm
Marco Lardelli
Mark Jad
Mark Malone
Markus Martin
Markus Michael Egger
Markus Strompen
Martin FIbik
Martin Holas
Martin Linklater
Martin Liška
Martin Trbola
Martin Zabinski
Matt Edwards
Matthew Booe
Matt Sylvia
Maverick
Max Fiedler
Maxime Blade
Maxime Santerre
Maxwell
Melissa Mears
Merlyn Morgan-Graham
Metal Demon 2000
mhilbrunner
Michael
Michael Bruce-Lockhart
Michael Haney
Michael Morrison
Michael Toporkov
Michał Skwarek
Mikael Nordenberg
Mikayla
Mike Birkhead
Mike Copley
Mitchell
Mitchell J. Wagner
MJacred
ModularMind
Molinghu
Molly Jameson
MoltenGears
moulefrite
MrAZIE
Mrjemandem
Nathan Fish
Nathaniel
neighty
Neil Blakey-Milner
Neil Wang
Nerdforge
Nerdyninja
Nicholas La Roux
Nicholas Orlowski
Nick Eldrenkamp
Nick Macholl
Niclas Eriksen
Nicolas Goll-Perrier
Nicolas Rosset
Nils Nordmark
Nima Farid
Noel Billig
Noesis
oceoh
Okatima
Oleg Reva
Oliver Ambrose
oscar1000108
Oscar Domingo
Pascal
Patrick Indermühle
Patrickm
Patrick Nafarrete
Patrick Wuttke
Paul E Hansen
Paul Gieske
Paweł Kowal
Paweł Łyczkowski
Peter Höglund
Philip Cohoe
Philip Ludington (MrPhil)
Pierre Caye
pingudroid
pj
Point08
Preethi Vaidyanathan
PsycHead
pwab
RabidTunes
RackBar Dingum
Rafa Laguna
Raffaele Aramo
Ragnar Pettersson
Rainer Amler
Rami Hanano
Rammeow
RAMupgrade
red1939
Remi Rampin
Reneator
René Habermann
Riccardo Marini
Richard Hayes
Richard Ivánek
Richard Néveri
Riley
Robin Ward
RobotCritter
Rob Ruana
Rodrigo Loli
Roger Smith
Roglozor
Roland Rząsa
Roman Papush
Ronald Ho Hip (CrimsonZA)
Ronan
Roy Scayged
Ryan Groom
Rykk
Sam Caulfield
Sam Edson
Sammy Fischer
Sangeeth Pavithran
schroedinger's possum
Scott Longley
Sean Wall
Sebastian Michailidis
SeongWan Kim
Sessamekesh
SeungJong k
Shaidak
Shane
Shane Abraham
Shane Sicienski
Shane Spoor
Silver1063
simdee
Simon Jonas Larsen
Simon Schoenenberger
Simon Wenner
Sina Yeganeh
sirn
Skalli
slavfox
smbe19
smo1704
Snippytorque
Soheib El-Harrache
Solene Waked
Sophie Winter
Squirrel
Stéphane Roussel
Stephen Rice
Steve Cloete
Steven Drovie
summerblind
Sung soo Choi
Svenne Krap
SxP
tadashi endo
Tarch
Terry
The Domis4
Theodore Lindsey
TheVoiceInMyHead
Thibaut DECROMBECQUE
thomas
Thomas Bechtold
Thomas Detoy
Thomas Pickett
thommy
Till1805
Tim Drumheller
Tim Erskine
Tim Gleason
Tim Klein
Timothy B. MacDonald
tinyBigGAMES LLC
Title Plinsut
TMoney
Toadile
Tobias Bradtke
Tom Coxon
Tom Webster
Torgeir Lilleskog
Torsten Crass
TQQQ
Travis O'Brien
Trent Skinner
tril zerobyte
Troy Bonneau
Tryggve Sollid
Turgut Temucin
Tycho
Tyler Stafos
UltyX
Uther
v01tech
Vaida
Vaughan Ling
VikFro
Vincent Foulon
Vitaliy Sapronenko
Vi Watch
Vladimir Savin
Wapiti .
Watchinofoye
Wiley Thompson
William Bodin
William Edwards
William F Siqueira
William Hogben
Woonki Moon
Wyatt Goodin
xenomat
yakcyll
Yan Shi
Yegor Smirnov
Zach H.
Zak Stephens
Zher Huei Lee
蕭惟允
貴宏 小松
郝晨煜
## Bronze donors
There are even more donors that support the project with a small monthly donation.
Every bit counts and we thank every one of them for their amazing support!

10
ISSUE_TEMPLATE Normal file
View File

@@ -0,0 +1,10 @@
**Operating system or device - Godot version:**
**Issue description** (what happened, and what was expected):
**Steps to reproduce:**
**Link to minimal example project** (optional but very welcome):

27
LICENSE.md Normal file
View File

@@ -0,0 +1,27 @@
GODOT ENGINE
http://www.godotengine.org
************************************************************************
Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
************************************************************************

View File

@@ -1,20 +0,0 @@
Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.
Copyright (c) 2014-2022 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.

View File

@@ -1,5 +1,2 @@
Godot Engine Logo
Copyright (c) 2017 Andrea Calabró
This work is licensed under a Creative Commons Attribution 4.0 International
License (CC-BY-4.0 International) <https://creativecommons.org/licenses/by/4.0/>.
Godot Logo (c) Andrea Calabró, distributed under the terms of the CC By License:
https://creativecommons.org/licenses/by/3.0/legalcode

View File

@@ -1,78 +1,66 @@
# Godot Engine
[![GODOT](/logo.png)](https://godotengine.org)
<p align="center">
<a href="https://godotengine.org">
<img src="logo_outlined.svg" width="400" alt="Godot Engine logo">
</a>
</p>
## Godot Engine
## 2D and 3D cross-platform game engine
Homepage: https://godotengine.org
**[Godot Engine](https://godotengine.org) is a feature-packed, cross-platform
game engine to create 2D and 3D games from a unified interface.** It provides a
comprehensive set of common tools, so that users can focus on making games
without having to reinvent the wheel. Games can be exported in one click to a
number of platforms, including the major desktop platforms (Linux, macOS,
Windows), mobile platforms (Android, iOS), as well as Web-based platforms
(HTML5) and
[consoles](https://docs.godotengine.org/en/latest/tutorials/platform/consoles.html).
#### 2D and 3D cross-platform game engine
## Free, open source and community-driven
Godot Engine is a feature-packed, cross-platform game engine to create 2D and
3D games from a unified interface. It provides a comprehensive set of common
tools, so that users can focus on making games without having to reinvent the
wheel. Games can be exported in one click to a number of platforms, including
the major desktop platforms (Linux, Mac OSX, Windows) as well as mobile
(Android, iOS) and web-based (HTML5) platforms.
#### Free, open source and community-driven
Godot is completely free and open source under the very permissive MIT license.
No strings attached, no royalties, nothing. The users' games are theirs, down
to the last line of engine code. Godot's development is fully independent and
community-driven, empowering users to help shape their engine to match their
expectations. It is supported by the [Software Freedom Conservancy](https://sfconservancy.org/)
expectations. It is supported by the Software Freedom Conservancy
not-for-profit.
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://raw.githubusercontent.com/godotengine/godot-design/master/screenshots/editor_tps_demo_1920x1080.jpg)
### Getting the engine
## Getting the engine
### Binary downloads
#### Binary downloads
Official binaries for the Godot editor and the export templates can be found
[on the homepage](https://godotengine.org/download).
### Compiling from source
#### 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/reference/_compiling.html)
for compilation instructions for every supported platform.
## Community and contributing
### Community
Godot is not only an engine but an ever-growing community of users and engine
developers. The main community channels are listed [on the homepage](https://godotengine.org/community).
To get in touch with the engine developers, the best way is to join the
[Godot Contributors Chat](https://chat.godotengine.org).
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
## 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/)
is also accessible from the Godot editor.
The [class reference](http://docs.godotengine.org/en/latest/classes/_classes.html)
is also accessible from within the engine.
The official demos are maintained in their own [GitHub repository](https://github.com/godotengine/godot-demo-projects)
as well.
There are also a number of other
[learning resources](https://docs.godotengine.org/en/latest/community/tutorials.html)
provided by the community, such as text and video tutorials, demos, etc.
Consult the [community channels](https://godotengine.org/community)
for more information.
There are also a number of other learning resources provided by the community,
such as text and video tutorials, demos, etc. Consult the [community channels](https://godotengine.org/community)
for more info.
[![Actions Build Status](https://github.com/godotengine/godot/workflows/Godot/badge.svg?branch=master)](https://github.com/godotengine/godot/actions)
[![Code Triagers Badge](https://www.codetriage.com/godotengine/godot/badges/users.svg)](https://www.codetriage.com/godotengine/godot)
[![Translate on Weblate](https://hosted.weblate.org/widgets/godot-engine/-/godot/svg-badge.svg)](https://hosted.weblate.org/engage/godot-engine/?utm_source=widget)
[![Total alerts on LGTM](https://img.shields.io/lgtm/alerts/g/godotengine/godot.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/godotengine/godot/alerts)
[![TODOs](https://badgen.net/https/api.tickgit.com/badgen/github.com/godotengine/godot)](https://www.tickgit.com/browse?repo=github.com/godotengine/godot)
[![Build Status](https://travis-ci.org/godotengine/godot.svg?branch=master)](https://travis-ci.org/godotengine/godot)
[![Code Triagers Badge](http://www.codetriage.com/godotengine/godot/badges/users.svg)](http://www.codetriage.com/godotengine/godot)

View File

@@ -1,20 +1,17 @@
#!/usr/bin/env python
EnsureSConsVersion(0, 98, 1)
EnsureSConsVersion(0, 14)
# System
import atexit
import glob
import string
import os
import pickle
import os.path
import glob
import sys
import time
from collections import OrderedDict
# Local
import methods
import gles_builders
from platform_methods import run_in_subprocess
methods.update_version()
# scan possible build platforms
@@ -22,89 +19,100 @@ platform_list = [] # list of platforms
platform_opts = {} # options for each platform
platform_flags = {} # flags for each platform
active_platforms = []
active_platform_ids = []
platform_exporters = []
platform_apis = []
global_defaults = []
time_at_start = time.time()
for x in sorted(glob.glob("platform/*")):
if not os.path.isdir(x) or not os.path.exists(x + "/detect.py"):
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"):
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 detect.is_active():
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)
if detect.can_build():
if (detect.can_build()):
x = x.replace("platform/", "") # rest of world
x = x.replace("platform\\", "") # win32
platform_list += [x]
platform_opts[x] = detect.get_opts()
platform_flags[x] = detect.get_flags()
sys.path.remove(tmppath)
sys.modules.pop("detect")
sys.modules.pop('detect')
module_list = methods.detect_modules()
# print "Detected Platforms: "+str(platform_list)
methods.save_active_platforms(active_platforms, active_platform_ids)
custom_tools = ["default"]
custom_tools = ['default']
platform_arg = ARGUMENTS.get("platform", ARGUMENTS.get("p", False))
if os.name == "nt" and (platform_arg == "android" or methods.get_cmdline_bool("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("VSINSTALLDIR") == None or platform_arg == "android"):
custom_tools = ['mingw']
# We let SCons build its default ENV as it includes OS-specific things which we don't
# want to have to pull in manually.
# Then we prepend PATH to make it take precedence, while preserving SCons' own entries.
env_base = Environment(tools=custom_tools)
env_base.PrependENVPath("PATH", os.getenv("PATH"))
env_base.PrependENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH"))
if "TERM" in os.environ: # Used for colored output.
env_base["ENV"]["TERM"] = os.environ["TERM"]
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_dependencies = []
env_base.android_java_dirs = []
env_base.android_res_dirs = []
env_base.android_aidl_dirs = []
env_base.android_jni_dirs = []
env_base.android_default_config = []
env_base.android_manifest_chunk = ""
env_base.android_permission_chunk = ""
env_base.android_appattributes_chunk = ""
env_base.disabled_modules = []
env_base.use_ptrcall = False
env_base.module_version_string = ""
env_base.msvc = False
env_base.split_drivers = False
env_base.__class__.android_add_maven_repository = methods.android_add_maven_repository
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_aidl_dir = methods.android_add_aidl_dir
env_base.__class__.android_add_jni_dir = methods.android_add_jni_dir
env_base.__class__.android_add_default_config = methods.android_add_default_config
env_base.__class__.android_add_to_manifest = methods.android_add_to_manifest
env_base.__class__.android_add_to_permissions = methods.android_add_to_permissions
env_base.__class__.android_add_to_attributes = methods.android_add_to_attributes
env_base.__class__.disable_module = methods.disable_module
env_base.__class__.add_module_version_string = methods.add_module_version_string
env_base.__class__.add_source_files = methods.add_source_files
env_base.__class__.use_windows_spawn_fix = methods.use_windows_spawn_fix
env_base.__class__.split_lib = methods.split_lib
env_base.__class__.add_shared_library = methods.add_shared_library
env_base.__class__.add_library = methods.add_library
env_base.__class__.add_program = methods.add_program
env_base.__class__.CommandNoCache = methods.CommandNoCache
env_base.__class__.disable_warnings = methods.disable_warnings
env_base["x86_libtheora_opt_gcc"] = False
env_base["x86_libtheora_opt_vc"] = False
# avoid issues when building with different versions of python out of the same directory
env_base.SConsignFile(".sconsign{0}.dblite".format(pickle.HIGHEST_PROTOCOL))
# Build options
customs = ["custom.py"]
customs = ['custom.py']
profile = ARGUMENTS.get("profile", "")
profile = ARGUMENTS.get("profile", False)
if profile:
import os.path
if os.path.isfile(profile):
customs.append(profile)
elif os.path.isfile(profile + ".py"):
@@ -113,599 +121,297 @@ if profile:
opts = Variables(customs, ARGUMENTS)
# Target build options
opts.Add("p", "Platform (alias for 'platform')", "")
opts.Add("platform", "Target platform (%s)" % ("|".join(platform_list),), "")
opts.Add(BoolVariable("tools", "Build the tools (a.k.a. the Godot editor)", True))
opts.Add(EnumVariable("target", "Compilation target", "debug", ("debug", "release_debug", "release")))
opts.Add("arch", "Platform-dependent architecture (arm/arm64/x86/x64/mips/...)", "")
opts.Add(EnumVariable("bits", "Target platform bits", "default", ("default", "32", "64")))
opts.Add(EnumVariable("optimize", "Optimization type", "speed", ("speed", "size", "none")))
opts.Add(BoolVariable("production", "Set defaults to build Godot for use in production", False))
opts.Add(BoolVariable("use_lto", "Use link-time optimization", False))
opts.Add('arch', "Platform-dependent architecture (arm/arm64/x86/x64/mips/etc)", '')
opts.Add('bits', "Target platform bits (default/32/64/fat)", 'default')
opts.Add('p', "Platform (alias for 'platform')", '')
opts.Add('platform', "Target platform: any in " + str(platform_list), '')
opts.Add('target', "Compilation target (debug/release_debug/release)", 'debug')
opts.Add('tools', "Build the tools a.k.a. the Godot editor (yes/no)", 'yes')
# Components
opts.Add(BoolVariable("deprecated", "Enable deprecated features", True))
opts.Add(BoolVariable("minizip", "Enable ZIP archive support using minizip", True))
opts.Add(BoolVariable("xaudio2", "Enable the XAudio2 audio driver", False))
opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
opts.Add('deprecated', "Enable deprecated features (yes/no)", 'yes')
opts.Add('gdscript', "Build GDSCript support (yes/no)", 'yes')
opts.Add('minizip', "Build minizip archive support (yes/no)", 'yes')
opts.Add('xml', "XML format support for resources (yes/no)", 'yes')
# Advanced options
opts.Add(BoolVariable("dev", "If yes, alias for verbose=yes warnings=extra werror=yes", False))
opts.Add(BoolVariable("fast_unsafe", "Enable unsafe options for faster rebuilds", False))
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", "Level of compilation warnings", "all", ("extra", "all", "moderate", "no")))
opts.Add(BoolVariable("werror", "Treat compiler warnings as errors", 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(
BoolVariable(
"split_libmodules",
"Split intermediate libmodules.a in smaller chunks to prevent exceeding linker command line size (forced to True when using MinGW)",
False,
)
)
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", True))
opts.Add("system_certs_path", "Use this path as SSL certificates default for editor (for package maintainers)", "")
opts.Add(BoolVariable("use_precise_math_checks", "Math checks use very precise epsilon (debug option)", False))
opts.Add('disable_3d', "Disable 3D nodes for smaller executable (yes/no)", 'no')
opts.Add('disable_advanced_gui', "Disable advance 3D gui nodes and behaviors (yes/no)", 'no')
opts.Add('extra_suffix', "Custom extra suffix added to the base filename of all generated binary files", '')
opts.Add('unix_global_settings_path', "UNIX-specific path to system-wide settings. Currently only used for templates", '')
opts.Add('verbose', "Enable verbose output for the compilation (yes/no)", 'yes')
opts.Add('vsproj', "Generate Visual Studio Project. (yes/no)", 'no')
# Thirdparty libraries
opts.Add(BoolVariable("builtin_bullet", "Use the built-in Bullet library", True))
opts.Add(BoolVariable("builtin_certs", "Use the built-in SSL certificates bundles", True))
opts.Add(BoolVariable("builtin_embree", "Use the built-in Embree library", 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_wslay", "Use the built-in wslay 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_pcre2_with_jit", "Use JIT compiler for 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('builtin_freetype', "Use the builtin freetype library (yes/no)", 'yes')
opts.Add('builtin_glew', "Use the builtin glew library (yes/no)", 'yes')
opts.Add('builtin_libmpcdec', "Use the builtin libmpcdec library (yes/no)", 'yes')
opts.Add('builtin_libogg', "Use the builtin libogg library (yes/no)", 'yes')
opts.Add('builtin_libpng', "Use the builtin libpng library (yes/no)", 'yes')
opts.Add('builtin_libtheora', "Use the builtin libtheora library (yes/no)", 'yes')
opts.Add('builtin_libvorbis', "Use the builtin libvorbis library (yes/no)", 'yes')
opts.Add('builtin_libwebp', "Use the builtin libwebp library (yes/no)", 'yes')
opts.Add('builtin_openssl', "Use the builtin openssl library (yes/no)", 'yes')
opts.Add('builtin_opus', "Use the builtin opus library (yes/no)", 'yes')
# (akien) Unbundling would require work in audio_stream_speex.{cpp,h}, but since speex was
# removed in 3.0+ and this is only to preserve compatibility in 2.1, I haven't worked on it.
# Patches welcome if anyone cares :)
opts.Add('builtin_speex', "Use the builtin speex library (yes/no)", 'yes')
opts.Add('builtin_squish', "Use the builtin squish library (yes/no)", 'yes')
opts.Add('builtin_zlib', "Use the builtin zlib library (yes/no)", 'yes')
# Compilation environment setup
# Environment setup
opts.Add("CXX", "C++ compiler")
opts.Add("CC", "C compiler")
opts.Add("LINK", "Linker")
opts.Add("CCFLAGS", "Custom flags for both the C and C++ compilers")
opts.Add("CCFLAGS", "Custom flags for the C and C++ compilers")
opts.Add("CFLAGS", "Custom flags for the C compiler")
opts.Add("CXXFLAGS", "Custom flags for the C++ compiler")
opts.Add("LINKFLAGS", "Custom flags for the linker")
# Update the environment to have all above options defined
# in following code (especially platform and custom_modules).
opts.Update(env_base)
# Platform selection: validate input, and add options.
# add platform specific options
selected_platform = ""
for k in platform_opts.keys():
opt_list = platform_opts[k]
for o in opt_list:
opts.Add(o[0], o[1], o[2])
if env_base["platform"] != "":
selected_platform = env_base["platform"]
elif env_base["p"] != "":
selected_platform = env_base["p"]
else:
# Missing `platform` argument, try to detect platform automatically
if (
sys.platform.startswith("linux")
or sys.platform.startswith("dragonfly")
or sys.platform.startswith("freebsd")
or sys.platform.startswith("netbsd")
or sys.platform.startswith("openbsd")
):
selected_platform = "x11"
elif sys.platform == "darwin":
selected_platform = "osx"
elif sys.platform == "win32":
selected_platform = "windows"
else:
print("Could not detect platform automatically. Supported platforms:")
for x in platform_list:
print("\t" + x)
print("\nPlease run SCons again and select a valid platform: platform=<string>")
for x in module_list:
opts.Add('module_' + x + '_enabled', "Enable module '" + x + "' (yes/no)", "yes")
if selected_platform != "":
print("Automatically detected platform: " + selected_platform)
if selected_platform in ["linux", "bsd", "linuxbsd"]:
if selected_platform == "linuxbsd":
# Alias for forward compatibility.
print('Platform "linuxbsd" is still called "x11" in Godot 3.x. Building for platform "x11".')
# Alias for convenience.
selected_platform = "x11"
# Make sure to update this to the found, valid platform as it's used through the buildsystem as the reference.
# It should always be re-set after calling `opts.Update()` otherwise it uses the original input value.
env_base["platform"] = selected_platform
# Add platform-specific options.
if selected_platform in platform_opts:
for opt in platform_opts[selected_platform]:
opts.Add(opt)
# Update the environment to take platform-specific options into account.
opts.Update(env_base)
env_base["platform"] = selected_platform # Must always be re-set after calling opts.Update().
# Detect modules.
modules_detected = OrderedDict()
module_search_paths = ["modules"] # Built-in path.
if env_base["custom_modules"]:
paths = env_base["custom_modules"].split(",")
for p in paths:
try:
module_search_paths.append(methods.convert_custom_modules_path(p))
except ValueError as e:
print(e)
sys.exit(255)
for path in module_search_paths:
if path == "modules":
# Built-in modules don't have nested modules,
# so save the time it takes to parse directories.
modules = methods.detect_modules(path, recursive=False)
else: # Custom.
modules = methods.detect_modules(path, env_base["custom_modules_recursive"])
# Provide default include path for both the custom module search `path`
# and the base directory containing custom modules, as it may be different
# from the built-in "modules" name (e.g. "custom_modules/summator/summator.h"),
# so it can be referenced simply as `#include "summator/summator.h"`
# independently of where a module is located on user's filesystem.
env_base.Prepend(CPPPATH=[path, os.path.dirname(path)])
# Note: custom modules can override built-in ones.
modules_detected.update(modules)
# Add module options
for name, path in modules_detected.items():
enabled = True
sys.path.insert(0, path)
import config
try:
enabled = config.is_enabled()
except AttributeError:
pass
sys.path.remove(path)
sys.modules.pop("config")
opts.Add(BoolVariable("module_" + name + "_enabled", "Enable module '%s'" % (name,), enabled))
methods.write_modules(modules_detected)
# Update the environment again after all the module options are added.
opts.Update(env_base)
env_base["platform"] = selected_platform # Must always be re-set after calling opts.Update().
Help(opts.GenerateHelpText(env_base))
opts.Update(env_base) # update environment
Help(opts.GenerateHelpText(env_base)) # generate help
# add default include paths
env_base.Prepend(CPPPATH=["#"])
env_base.Append(CPPPATH=['#core', '#core/math', '#tools', '#drivers', '#'])
# configure ENV for platform
env_base.platform_exporters = platform_exporters
env_base.platform_apis = platform_apis
# Build type defines - more platform-specific ones can be in detect.py.
if env_base["target"] == "release_debug" or env_base["target"] == "debug":
# DEBUG_ENABLED enables debugging *features* and debug-only code, which is intended
# to give *users* extra debugging information for their game development.
env_base.Append(CPPDEFINES=["DEBUG_ENABLED"])
"""
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":
# DEV_ENABLED enables *engine developer* code which should only be compiled for those
# working on the engine itself.
env_base.Append(CPPDEFINES=["DEV_ENABLED"])
if (env_base['target'] == 'debug'):
env_base.Append(CPPFLAGS=['-DDEBUG_MEMORY_ALLOC'])
env_base.Append(CPPFLAGS=['-DSCI_NAMESPACE'])
# SCons speed optimization controlled by the `fast_unsafe` option, which provide
# more than 10 s speed up for incremental rebuilds.
# Unsafe as they reduce the certainty of rebuilding all changed files, so it's
# enabled by default for `debug` builds, and can be overridden from command line.
# Ref: https://github.com/SCons/scons/wiki/GoFastButton
if methods.get_cmdline_bool("fast_unsafe", env_base["target"] == "debug"):
# Renamed to `content-timestamp` in SCons >= 4.2, keeping MD5 for compat.
env_base.Decider("MD5-timestamp")
env_base.SetOption("implicit_cache", 1)
env_base.SetOption("max_drift", 60)
if (env_base['deprecated'] != 'no'):
env_base.Append(CPPFLAGS=['-DENABLE_DEPRECATED'])
if env_base["use_precise_math_checks"]:
env_base.Append(CPPDEFINES=["PRECISE_MATH_CHECKS"])
env_base.platforms = {}
if not env_base.File("#main/splash_editor.png").exists():
# Force disabling editor splash if missing.
env_base["no_editor_splash"] = True
if env_base["no_editor_splash"]:
env_base.Append(CPPDEFINES=["NO_EDITOR_SPLASH"])
if not env_base["deprecated"]:
env_base.Append(CPPDEFINES=["DISABLE_DEPRECATED"])
selected_platform = ""
if env_base['platform'] != "":
selected_platform = env_base['platform']
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)
import detect
sys.path.append("./platform/" + selected_platform)
import detect
if "create" in dir(detect):
env = detect.create(env_base)
else:
env = env_base.Clone()
# Generating the compilation DB (`compile_commands.json`) requires SCons 4.0.0 or later.
from SCons import __version__ as scons_raw_version
if env['vsproj'] == "yes":
env.vs_incs = []
env.vs_srcs = []
scons_ver = env._get_major_minor_revision(scons_raw_version)
if scons_ver >= (4, 0, 0):
env.Tool("compilation_db")
env.Alias("compiledb", env.CompilationDatabase())
# 'dev' and 'production' are aliases to set default options if they haven't been set
# manually by the user.
if env["dev"]:
env["verbose"] = methods.get_cmdline_bool("verbose", True)
env["warnings"] = ARGUMENTS.get("warnings", "extra")
env["werror"] = methods.get_cmdline_bool("werror", True)
if env["production"]:
env["use_static_cpp"] = methods.get_cmdline_bool("use_static_cpp", True)
env["use_lto"] = methods.get_cmdline_bool("use_lto", True)
print("use_lto is: " + str(env["use_lto"]))
env["debug_symbols"] = methods.get_cmdline_bool("debug_symbols", False)
if not env["tools"] and env["target"] == "debug":
print(
"WARNING: Requested `production` build with `tools=no target=debug`, "
"this will give you a full debug template (use `target=release_debug` "
"for an optimized template with debug features)."
)
if env.msvc:
print(
"WARNING: For `production` Windows builds, you should use MinGW with GCC "
"or Clang instead of Visual Studio, as they can better optimize the "
"GDScript VM in a very significant way. MSVC LTO also doesn't work "
"reliably for our use case."
"If you want to use MSVC nevertheless for production builds, set "
"`debug_symbols=no use_lto=no` instead of the `production=yes` option."
)
Exit(255)
def AddToVSProject(sources):
for x in sources:
if type(x) == type(""):
fname = env.File(x).path
else:
fname = env.File(x)[0].path
pieces = fname.split(".")
if len(pieces) > 0:
basename = pieces[0]
basename = basename.replace('\\\\', '/')
env.vs_srcs = env.vs_srcs + [basename + ".cpp"]
env.vs_incs = env.vs_incs + [basename + ".h"]
# print basename
env.AddToVSProject = AddToVSProject
env.extra_suffix = ""
if env["extra_suffix"] != "":
env.extra_suffix += "." + env["extra_suffix"]
if env["extra_suffix"] != '':
env.extra_suffix += '.' + env["extra_suffix"]
# Environment flags
CCFLAGS = env.get("CCFLAGS", "")
env["CCFLAGS"] = ""
env.Append(CCFLAGS=str(CCFLAGS).split())
CCFLAGS = env.get('CCFLAGS', '')
env['CCFLAGS'] = ''
CFLAGS = env.get("CFLAGS", "")
env["CFLAGS"] = ""
env.Append(CFLAGS=str(CFLAGS).split())
env.Append(CCFLAGS=string.split(str(CCFLAGS)))
CXXFLAGS = env.get("CXXFLAGS", "")
env["CXXFLAGS"] = ""
env.Append(CXXFLAGS=str(CXXFLAGS).split())
CFLAGS = env.get('CFLAGS', '')
env['CFLAGS'] = ''
LINKFLAGS = env.get("LINKFLAGS", "")
env["LINKFLAGS"] = ""
env.Append(LINKFLAGS=str(LINKFLAGS).split())
env.Append(CFLAGS=string.split(str(CFLAGS)))
LINKFLAGS = env.get('LINKFLAGS', '')
env['LINKFLAGS'] = ''
env.Append(LINKFLAGS=string.split(str(LINKFLAGS)))
# Platform specific flags
flag_list = platform_flags[selected_platform]
for f in flag_list:
if not (f[0] in ARGUMENTS): # allow command line to override platform flags
env[f[0]] = f[1]
# Must happen after the flags definition, so that they can be used by platform detect
# must happen after the flags, so when flags are used by configure, stuff happens (ie, ssl on x11)
detect.configure(env)
# Set our C and C++ standard requirements.
# Prepending to make it possible to override
# This needs to come after `configure`, otherwise we don't have env.msvc.
if not env.msvc:
# Specifying GNU extensions support explicitly, which are supported by
# both GCC and Clang. This mirrors GCC and Clang's current default
# compile flags if no -std is specified.
env.Prepend(CFLAGS=["-std=gnu11"])
env.Prepend(CXXFLAGS=["-std=gnu++14"])
else:
# MSVC doesn't have clear C standard support, /std only covers C++.
# We apply it to CCFLAGS (both C and C++ code) in case it impacts C features.
env.Prepend(CCFLAGS=["/std:c++14"])
#env['platform_libsuffix'] = env['LIBSUFFIX']
# Configure compiler warnings
if env.msvc: # MSVC
# Truncations, narrowing conversions, signed/unsigned comparisons...
disable_nonessential_warnings = ["/wd4267", "/wd4244", "/wd4305", "/wd4018", "/wd4800"]
if env["warnings"] == "extra":
env.Append(CCFLAGS=["/Wall"]) # Implies /W4
elif env["warnings"] == "all":
env.Append(CCFLAGS=["/W3"] + disable_nonessential_warnings)
elif env["warnings"] == "moderate":
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"])
suffix = "." + selected_platform
if env["werror"]:
env.Append(CCFLAGS=["/WX"])
else: # GCC, Clang
version = methods.get_compiler_version(env) or [-1, -1]
common_warnings = []
if methods.using_gcc(env):
common_warnings += ["-Wno-misleading-indentation"]
if version[0] >= 7:
common_warnings += ["-Wshadow-local"]
elif methods.using_clang(env) or methods.using_emcc(env):
# We often implement `operator<` for structs of pointers as a requirement
# for putting them in `Set` or `Map`. We don't mind about unreliable ordering.
common_warnings += ["-Wno-ordered-compare-function-pointers"]
if env["warnings"] == "extra":
# 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", "-Wwrite-strings", "-Wno-unused-parameter"] + common_warnings)
env.Append(CXXFLAGS=["-Wctor-dtor-privacy", "-Wnon-virtual-dtor"])
if methods.using_gcc(env):
env.Append(
CCFLAGS=[
"-Walloc-zero",
"-Wduplicated-branches",
"-Wduplicated-cond",
"-Wstringop-overflow=4",
"-Wlogical-op",
]
)
env.Append(CXXFLAGS=["-Wnoexcept", "-Wplacement-new=1"])
if version[0] >= 9:
env.Append(CCFLAGS=["-Wattribute-alias=2"])
elif env["warnings"] == "all":
env.Append(CCFLAGS=["-Wall"] + common_warnings)
elif env["warnings"] == "moderate":
env.Append(CCFLAGS=["-Wall", "-Wno-unused"] + common_warnings)
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
if env["target"] == "release":
if env["tools"]:
if (env["target"] == "release"):
if (env["tools"] == "yes"):
print("Tools can only be built with targets 'debug' and 'release_debug'.")
sys.exit(255)
suffix += ".opt"
env.Append(CPPDEFINES=["NDEBUG"])
elif env["target"] == "release_debug":
if env["tools"]:
env.Append(CCFLAGS=['-DNDEBUG'])
elif (env["target"] == "release_debug"):
if (env["tools"] == "yes"):
suffix += ".opt.tools"
else:
suffix += ".opt.debug"
else:
if env["tools"]:
if (env["tools"] == "yes"):
suffix += ".tools"
else:
suffix += ".debug"
if env["arch"] != "":
suffix += "." + env["arch"]
elif env["bits"] == "32":
elif (env["bits"] == "32"):
suffix += ".32"
elif env["bits"] == "64":
elif (env["bits"] == "64"):
suffix += ".64"
elif (env["bits"] == "fat"):
suffix += ".fat"
suffix += env.extra_suffix
sys.path.remove(tmppath)
sys.modules.pop("detect")
modules_enabled = OrderedDict()
env.module_icons_paths = []
env.doc_class_path = {}
for name, path in modules_detected.items():
if not env["module_" + name + "_enabled"]:
continue
sys.path.insert(0, path)
env.current_module = name
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:
config.configure(env)
# Get doc classes paths (if present)
try:
doc_classes = config.get_doc_classes()
doc_path = config.get_doc_path()
for c in doc_classes:
env.doc_class_path[c] = path + "/" + doc_path
except Exception:
pass
# Get icon paths (if present)
try:
icons_path = config.get_icons_path()
env.module_icons_paths.append(path + "/" + icons_path)
except Exception:
# Default path for module icons
env.module_icons_paths.append(path + "/" + "icons")
modules_enabled[name] = path
sys.path.remove(path)
sys.modules.pop("config")
env.module_list = modules_enabled
methods.update_version(env.module_version_string)
env["PROGSUFFIX"] = suffix + env.module_version_string + env["PROGSUFFIX"]
env["PROGSUFFIX"] = suffix + 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"])
if env["tools"]:
env.Append(CPPDEFINES=["TOOLS_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"])
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"])
if env["minizip"]:
env.Append(CPPDEFINES=["MINIZIP_ENABLED"])
sys.path.remove("./platform/" + selected_platform)
sys.modules.pop('detect')
editor_module_list = ["freetype"]
for x in editor_module_list:
if not env["module_" + x + "_enabled"]:
if env["tools"]:
print(
"Build option 'module_" + x + "_enabled=no' cannot be used with 'tools=yes' (editor), "
"only with 'tools=no' (export template)."
)
sys.exit(255)
env.module_list = []
if not env["verbose"]:
for x in module_list:
if env['module_' + x + '_enabled'] != "yes":
continue
tmppath = "./modules/" + x
sys.path.append(tmppath)
env.current_module = x
import config
if (config.can_build(selected_platform)):
config.configure(env)
env.module_list.append(x)
sys.path.remove(tmppath)
sys.modules.pop('config')
if (env.use_ptrcall):
env.Append(CPPFLAGS=['-DPTRCALL_ENABLED'])
# to test 64 bits compiltion
# env.Append(CPPFLAGS=['-m64'])
if (env['tools'] == 'yes'):
env.Append(CPPFLAGS=['-DTOOLS_ENABLED'])
if (env['disable_3d'] == 'yes'):
env.Append(CPPFLAGS=['-D_3D_DISABLED'])
if (env['gdscript'] == 'yes'):
env.Append(CPPFLAGS=['-DGDSCRIPT_ENABLED'])
if (env['disable_advanced_gui'] == 'yes'):
env.Append(CPPFLAGS=['-DADVANCED_GUI_DISABLED'])
if (env['minizip'] == 'yes'):
env.Append(CPPFLAGS=['-DMINIZIP_ENABLED'])
if (env['xml'] == 'yes'):
env.Append(CPPFLAGS=['-DXML_ENABLED'])
if (env['verbose'] == 'no'):
methods.no_verbose(sys, env)
if not env["platform"] == "server": # FIXME: detect GLES3
env.Append(
BUILDERS={
"GLES3_GLSL": env.Builder(
action=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"
)
}
)
scons_cache_path = os.environ.get("SCONS_CACHE")
if scons_cache_path != None:
CacheDir(scons_cache_path)
print("Scons cache enabled... (path: '" + scons_cache_path + "')")
if env["vsproj"]:
env.vs_incs = []
env.vs_srcs = []
Export("env")
Export('env')
# build subdirs, the build order is dependent on link order.
SConscript("core/SCsub")
SConscript("servers/SCsub")
SConscript("scene/SCsub")
SConscript("editor/SCsub")
SConscript("tools/SCsub")
SConscript("drivers/SCsub")
SConscript("platform/SCsub")
SConscript("modules/SCsub")
SConscript("main/SCsub")
SConscript("platform/" + selected_platform + "/SCsub") # build selected platform
# Microsoft Visual Studio Project Generation
if env["vsproj"]:
env["CPPPATH"] = [Dir(path) for path in env["CPPPATH"]]
methods.generate_vs_project(env, GetOption("num_jobs"))
methods.generate_cpp_hint_file("cpp.hint")
if (env['vsproj']) == "yes":
# Check for the existence of headers
conf = Configure(env)
if "check_c_headers" in env:
for header in env["check_c_headers"]:
if conf.CheckCHeader(header[0]):
env.AppendUnique(CPPDEFINES=[header[1]])
AddToVSProject(env.core_sources)
AddToVSProject(env.main_sources)
AddToVSProject(env.modules_sources)
AddToVSProject(env.scene_sources)
AddToVSProject(env.servers_sources)
AddToVSProject(env.tool_sources)
elif selected_platform != "":
if selected_platform == "list":
print("The following platforms are available:\n")
else:
print('Invalid target platform "' + selected_platform + '".')
print("The following platforms were detected:\n")
# this env flag won't work, it needs to be set in env_base=Environment(MSVC_VERSION='9.0')
# Even then, SCons still seems to ignore it and builds with the latest MSVC...
# That said, it's not needed to be set so far but I'm leaving it here so that this comment
# has a purpose.
# env['MSVS_VERSION']='9.0'
# Calls a CMD with /C(lose) and /V(delayed environment variable expansion) options.
# And runs vcvarsall bat for the propper arhitecture and scons for propper configuration
env['MSVSBUILDCOM'] = 'cmd /V /C set "plat=$(PlatformTarget)" ^& (if "$(PlatformTarget)"=="x64" (set "plat=x86_amd64")) ^& set "tools=yes" ^& (if "$(Configuration)"=="release" (set "tools=no")) ^& call "$(VCInstallDir)vcvarsall.bat" !plat! ^& scons platform=windows target=$(Configuration) tools=!tools! -j2'
env['MSVSREBUILDCOM'] = 'cmd /V /C set "plat=$(PlatformTarget)" ^& (if "$(PlatformTarget)"=="x64" (set "plat=x86_amd64")) ^& set "tools=yes" ^& (if "$(Configuration)"=="release" (set "tools=no")) & call "$(VCInstallDir)vcvarsall.bat" !plat! ^& scons platform=windows target=$(Configuration) tools=!tools! vsproj=yes -j2'
env['MSVSCLEANCOM'] = 'cmd /V /C set "plat=$(PlatformTarget)" ^& (if "$(PlatformTarget)"=="x64" (set "plat=x86_amd64")) ^& set "tools=yes" ^& (if "$(Configuration)"=="release" (set "tools=no")) ^& call "$(VCInstallDir)vcvarsall.bat" !plat! ^& scons --clean platform=windows target=$(Configuration) tools=!tools! -j2'
# This version information (Win32, x64, Debug, Release, Release_Debug seems to be
# required for Visual Studio to understand that it needs to generate an NMAKE
# project. Do not modify without knowing what you are doing.
debug_variants = ['debug|Win32'] + ['debug|x64']
release_variants = ['release|Win32'] + ['release|x64']
release_debug_variants = ['release_debug|Win32'] + ['release_debug|x64']
variants = debug_variants + release_variants + release_debug_variants
debug_targets = ['bin\\godot.windows.tools.32.exe'] + ['bin\\godot.windows.tools.64.exe']
release_targets = ['bin\\godot.windows.opt.32.exe'] + ['bin\\godot.windows.opt.64.exe']
release_debug_targets = ['bin\\godot.windows.opt.tools.32.exe'] + ['bin\\godot.windows.opt.tools.64.exe']
targets = debug_targets + release_targets + release_debug_targets
msvproj = env.MSVSProject(target=['#godot' + env['MSVSPROJECTSUFFIX']],
incs=env.vs_incs,
srcs=env.vs_srcs,
runfile=targets,
buildtarget=targets,
auto_build_solution=1,
variant=variants)
else:
print("No valid target platform selected.")
print("The following were detected:")
for x in platform_list:
print("\t" + x)
print("\nPlease run SCons again and select a valid platform: platform=<string>")
if selected_platform == "list":
# Exit early to suppress the rest of the built-in SCons messages
sys.exit(0)
else:
sys.exit(255)
# The following only makes sense when the 'env' is defined, and assumes it is.
if "env" in locals():
methods.show_progress(env)
# TODO: replace this with `env.Dump(format="json")`
# once we start requiring SCons 4.0 as min version.
methods.dump(env)
def print_elapsed_time():
elapsed_time_sec = round(time.time() - time_at_start, 3)
time_ms = round((elapsed_time_sec % 1) * 1000)
print("[Time elapsed: {}.{:03}]".format(time.strftime("%H:%M:%S", time.gmtime(elapsed_time_sec)), time_ms))
atexit.register(print_elapsed_time)
print("\nPlease run scons again with argument: platform=<string>")

View File

@@ -1,97 +0,0 @@
import sys
if sys.version_info < (3,):
def isbasestring(s):
return isinstance(s, basestring)
def open_utf8(filename, mode):
return open(filename, mode)
def byte_to_str(x):
return str(ord(x))
import cStringIO
def StringIO():
return cStringIO.StringIO()
def encode_utf8(x):
return x
def decode_utf8(x):
return x
def iteritems(d):
return d.iteritems()
def itervalues(d):
return d.itervalues()
def escape_string(s):
if isinstance(s, unicode):
s = s.encode("ascii")
result = ""
for c in s:
if not (32 <= ord(c) < 127) or c in ("\\", '"'):
result += "\\%03o" % ord(c)
else:
result += c
return result
def qualname(obj):
# Not properly equivalent to __qualname__ in py3, but it doesn't matter.
return obj.__name__
else:
def isbasestring(s):
return isinstance(s, (str, bytes))
def open_utf8(filename, mode):
return open(filename, mode, encoding="utf-8")
def byte_to_str(x):
return str(x)
import io
def StringIO():
return io.StringIO()
import codecs
def encode_utf8(x):
return codecs.utf_8_encode(x)[0]
def decode_utf8(x):
return codecs.utf_8_decode(x)[0]
def iteritems(d):
return iter(d.items())
def itervalues(d):
return iter(d.values())
def charcode_to_c_escapes(c):
rev_result = []
while c >= 256:
c, low = (c // 256, c % 256)
rev_result.append("\\%03o" % low)
rev_result.append("\\%03o" % c)
return "".join(reversed(rev_result))
def escape_string(s):
result = ""
if isinstance(s, str):
s = s.encode("utf-8")
for c in s:
if not (32 <= c < 127) or c in (ord("\\"), ord('"')):
result += charcode_to_c_escapes(c)
else:
result += chr(c)
return result
def qualname(obj):
return obj.__qualname__

View File

@@ -1,201 +1,67 @@
#!/usr/bin/env python
Import("env")
import core_builders
import make_binders
from platform_methods import run_in_subprocess
Import('env')
env.core_sources = []
# Generate AES256 script encryption key
import os
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 "globals.h"\n'
gd_cpp += gd_inc
gd_cpp += "void Globals::register_global_defaults() {\n" + gd_call + "\n}\n"
f = open("global_defaults.cpp", "wb")
f.write(gd_cpp)
f.close()
import os
txt = "0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0"
if "SCRIPT_AES256_ENCRYPTION_KEY" in os.environ:
key = os.environ["SCRIPT_AES256_ENCRYPTION_KEY"]
if ("SCRIPT_AES256_ENCRYPTION_KEY" in os.environ):
e = os.environ["SCRIPT_AES256_ENCRYPTION_KEY"]
txt = ""
ec_valid = True
if len(key) != 64:
if (len(e) != 64):
ec_valid = False
else:
txt = ""
for i in range(len(key) >> 1):
if i > 0:
for i in range(len(e) >> 1):
if (i > 0):
txt += ","
txts = "0x" + key[i * 2 : i * 2 + 2]
txts = "0x" + e[i * 2:i * 2 + 2]
try:
int(txts, 16)
except Exception:
except:
ec_valid = False
txt += txts
if not ec_valid:
print("Error: Invalid AES256 encryption key, not 64 hexadecimal characters: '" + key + "'.")
print(
"Unset 'SCRIPT_AES256_ENCRYPTION_KEY' in your environment "
"or make sure that it contains exactly 64 hexadecimal characters."
)
Exit(255)
if (not ec_valid):
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.cpp", "wb")
f.write("#include \"globals.h\"\nuint8_t script_encryption_key[32]={" + txt + "};\n")
f.close()
# Add required thirdparty code.
thirdparty_obj = []
env_thirdparty = env.Clone()
env_thirdparty.disable_warnings()
# Misc 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
"fastlz.c",
"smaz.c",
# C++ sources
"hq2x.cpp",
"pcg.cpp",
"triangulator.cpp",
"clipper.cpp",
]
thirdparty_misc_sources = [thirdparty_misc_dir + file for file in thirdparty_misc_sources]
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_misc_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.Prepend(CPPPATH=[thirdparty_zlib_dir])
# Needs to be available in main env too
env.Prepend(CPPPATH=[thirdparty_zlib_dir])
if env["target"] == "debug":
env_thirdparty.Append(CPPDEFINES=["ZLIB_DEBUG"])
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_zlib_sources)
# Minizip library, could be unbundled in theory
# However, our version has some custom modifications, so it won't compile with the system one
thirdparty_minizip_dir = "#thirdparty/minizip/"
thirdparty_minizip_sources = [
"ioapi.c",
"unzip.c",
"zip.c",
]
thirdparty_minizip_sources = [thirdparty_minizip_dir + file for file in thirdparty_minizip_sources]
env_thirdparty.add_source_files(thirdparty_obj, 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",
"compress/zstd_compress_superblock.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.Prepend(CPPPATH=[thirdparty_zstd_dir, thirdparty_zstd_dir + "common"])
env_thirdparty.Append(CPPDEFINES=["ZSTD_STATIC_LINKING_ONLY"])
env.Prepend(CPPPATH=thirdparty_zstd_dir)
# Also needed in main env includes will trigger warnings
env.Append(CPPDEFINES=["ZSTD_STATIC_LINKING_ONLY"])
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_zstd_sources)
env.core_sources += thirdparty_obj
# Godot source files
env.add_source_files(env.core_sources, "*.cpp")
env.add_source_files(env.core_sources, "script_encryption_key.gen.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", "method_bind_free_func.gen.inc"],
"make_binders.py",
run_in_subprocess(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("crypto/SCsub")
SConscript("io/SCsub")
SConscript("bind/SCsub")
# Build it all as a library
lib = env.add_library("core", env.core_sources)
Export('env')
import make_binders
env.Command(['method_bind.inc', 'method_bind_ext.inc'], 'make_binders.py', make_binders.run)
SConscript('os/SCsub')
SConscript('math/SCsub')
SConscript('io/SCsub')
SConscript('bind/SCsub')
lib = env.Library("core", env.core_sources)
env.Prepend(LIBS=[lib])
# Needed to force rebuilding the core files when the thirdparty code is updated.
env.Depends(lib, thirdparty_obj)

198
core/allocators.h Normal file
View File

@@ -0,0 +1,198 @@
/*************************************************************************/
/* allocators.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef 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

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,120 +26,149 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "array.h"
#include "vector.h"
#include "hashfuncs.h"
#include "variant.h"
#include "object.h"
#include "core/hashfuncs.h"
#include "core/object.h"
#include "core/variant.h"
#include "core/vector.h"
struct ArrayPrivate {
class ArrayPrivate {
public:
SafeRefCount refcount;
Vector<Variant> array;
bool shared;
};
void Array::_ref(const Array &p_from) const {
void Array::_ref(const Array& p_from) const {
ArrayPrivate *_fp = p_from._p;
ERR_FAIL_COND(!_fp); // should NOT happen.
if (_fp == _p) {
return; // whatever it is, nothing to do here move along
}
if (_fp == _p)
return; //wathever it is, nothing to do here move along
bool success = _fp->refcount.ref();
ERR_FAIL_COND(!success); // should really not happen either
ERR_FAIL_COND(!success); //should really not happen either
_unref();
_p = p_from._p;
if (_fp->shared) {
_p = p_from._p;
} else {
_p = memnew( ArrayPrivate );
_p->shared=false;
_p->refcount.init();
_p->array=_fp->array;
if (_fp->refcount.unref())
memdelete(_fp);
}
}
void Array::_unref() const {
if (!_p) {
if (!_p)
return;
}
if (_p->refcount.unref()) {
memdelete(_p);
}
_p = nullptr;
_p=NULL;
}
Variant &Array::operator[](int p_idx) {
return _p->array.write[p_idx];
}
const Variant &Array::operator[](int p_idx) const {
Variant& Array::operator[](int p_idx) {
return _p->array[p_idx];
}
const Variant& Array::operator[](int p_idx) const {
return _p->array[p_idx];
}
int Array::size() const {
return _p->array.size();
}
bool Array::empty() const {
return _p->array.empty();
}
void Array::clear() {
_p->array.clear();
}
bool Array::operator==(const Array &p_array) const {
return _p == p_array._p;
bool Array::is_shared() const {
return _p->shared;
}
bool Array::operator==(const Array& p_array) const {
return _p==p_array._p;
}
uint32_t Array::hash() const {
uint32_t h = hash_djb2_one_32(0);
for (int i = 0; i < _p->array.size(); i++) {
h = hash_djb2_one_32(_p->array[i].hash(), h);
uint32_t h=hash_djb2_one_32(0);
for (int i=0;i<_p->array.size();i++) {
h = hash_djb2_one_32( _p->array[i].hash(), h);
}
return h;
}
void Array::operator=(const Array &p_array) {
void Array::operator=(const Array& p_array) {
_ref(p_array);
}
void Array::push_back(const Variant &p_value) {
void Array::push_back(const Variant& p_value) {
_p->array.push_back(p_value);
}
void Array::append_array(const Array &p_array) {
_p->array.append_array(p_array._p->array);
}
Error Array::resize(int p_new_size) {
return _p->array.resize(p_new_size);
}
void Array::insert(int p_pos, const Variant &p_value) {
_p->array.insert(p_pos, p_value);
void Array::insert(int p_pos, const Variant& p_value) {
_p->array.insert(p_pos,p_value);
}
void Array::erase(const Variant &p_value) {
void Array::erase(const Variant& p_value) {
_p->array.erase(p_value);
}
Variant Array::front() const {
ERR_FAIL_COND_V_MSG(_p->array.size() == 0, Variant(), "Can't take value from empty array.");
ERR_FAIL_COND_V(_p->array.size() == 0, Variant());
return operator[](0);
}
Variant Array::back() const {
ERR_FAIL_COND_V_MSG(_p->array.size() == 0, Variant(), "Can't take value from empty array.");
ERR_FAIL_COND_V(_p->array.size() == 0, Variant());
return operator[](_p->array.size() - 1);
}
int Array::find(const Variant &p_value, int p_from) const {
int Array::find(const Variant& p_value, int p_from) const {
return _p->array.find(p_value, p_from);
}
int Array::rfind(const Variant &p_value, int p_from) const {
if (_p->array.size() == 0) {
int Array::rfind(const Variant& p_value, int p_from) const {
if (_p->array.size() == 0)
return -1;
}
if (p_from < 0) {
// Relative offset from the end
@@ -151,317 +179,140 @@ int Array::rfind(const Variant &p_value, int p_from) const {
p_from = _p->array.size() - 1;
}
for (int i = p_from; i >= 0; i--) {
if (_p->array[i] == p_value) {
for (int i=p_from; i>=0; i--) {
if(_p->array[i] == p_value){
return i;
}
}
};
};
return -1;
}
int Array::find_last(const Variant &p_value) const {
int Array::find_last(const Variant& p_value) const {
return rfind(p_value);
}
int Array::count(const Variant &p_value) const {
if (_p->array.size() == 0) {
return 0;
}
int Array::count(const Variant& p_value) const {
int amount = 0;
for (int i = 0; i < _p->array.size(); i++) {
if (_p->array[i] == p_value) {
if(_p->array.size() == 0)
return 0;
int amount=0;
for (int i=0; i<_p->array.size(); i++) {
if(_p->array[i] == p_value){
amount++;
}
}
};
};
return amount;
}
bool Array::has(const Variant &p_value) const {
bool Array::has(const Variant& p_value) const {
return _p->array.find(p_value, 0) != -1;
}
void Array::remove(int p_pos) {
_p->array.remove(p_pos);
}
void Array::set(int p_idx, const Variant &p_value) {
operator[](p_idx) = p_value;
void Array::set(int p_idx,const Variant& p_value) {
operator[](p_idx)=p_value;
}
const Variant &Array::get(int p_idx) const {
const Variant& Array::get(int p_idx) const {
return operator[](p_idx);
}
Array Array::duplicate(bool p_deep) 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);
}
return new_arr;
}
int Array::_clamp_slice_index(int p_index) const {
int arr_size = size();
int fixed_index = CLAMP(p_index, -arr_size, arr_size - 1);
if (fixed_index < 0) {
fixed_index = arr_size + fixed_index;
}
return fixed_index;
}
Array Array::slice(int p_begin, int p_end, int p_step, bool p_deep) const { // like python, but inclusive on upper bound
Array new_arr;
ERR_FAIL_COND_V_MSG(p_step == 0, new_arr, "Array slice step size cannot be zero.");
if (empty()) { // Don't try to slice empty arrays.
return new_arr;
}
if (p_step > 0) {
if (p_begin >= size() || p_end < -size()) {
return new_arr;
}
} else { // p_step < 0
if (p_begin < -size() || p_end >= size()) {
return new_arr;
}
}
int begin = _clamp_slice_index(p_begin);
int end = _clamp_slice_index(p_end);
int new_arr_size = MAX(((end - begin + p_step) / p_step), 0);
new_arr.resize(new_arr_size);
if (p_step > 0) {
int dest_idx = 0;
for (int idx = begin; idx <= end; idx += p_step) {
ERR_FAIL_COND_V_MSG(dest_idx < 0 || dest_idx >= new_arr_size, Array(), "Bug in Array slice()");
new_arr[dest_idx++] = p_deep ? get(idx).duplicate(p_deep) : get(idx);
}
} else { // p_step < 0
int dest_idx = 0;
for (int idx = begin; idx >= end; idx += p_step) {
ERR_FAIL_COND_V_MSG(dest_idx < 0 || dest_idx >= new_arr_size, Array(), "Bug in Array slice()");
new_arr[dest_idx++] = p_deep ? get(idx).duplicate(p_deep) : get(idx);
}
}
return new_arr;
}
struct _ArrayVariantSort {
_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
bool valid = false;
_FORCE_INLINE_ bool operator()(const Variant& p_l, const Variant& p_r) const {
bool valid=false;
Variant res;
Variant::evaluate(Variant::OP_LESS, p_l, p_r, res, valid);
if (!valid) {
res = false;
}
Variant::evaluate(Variant::OP_LESS,p_l,p_r,res,valid);
if (!valid)
res=false;
return res;
}
};
Array &Array::sort() {
void Array::sort() {
_p->array.sort_custom<_ArrayVariantSort>();
return *this;
}
struct _ArrayVariantSortCustom {
Object *obj;
StringName func;
_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
const Variant *args[2] = { &p_l, &p_r };
_FORCE_INLINE_ bool operator()(const Variant& p_l, const Variant& p_r) const {
const Variant*args[2]={&p_l,&p_r};
Variant::CallError err;
bool res = obj->call(func, args, 2, err);
if (err.error != Variant::CallError::CALL_OK) {
res = false;
}
bool res = obj->call(func,args,2,err);
if (err.error!=Variant::CallError::CALL_OK)
res=false;
return res;
}
};
Array &Array::sort_custom(Object *p_obj, const StringName &p_function) {
ERR_FAIL_NULL_V(p_obj, *this);
void Array::sort_custom(Object *p_obj,const StringName& p_function){
ERR_FAIL_NULL(p_obj);
SortArray<Variant,_ArrayVariantSortCustom> avs;
avs.compare.obj=p_obj;
avs.compare.func=p_function;
avs.sort(_p->array.ptr(),_p->array.size());
SortArray<Variant, _ArrayVariantSortCustom, true> 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;
}
}
void Array::invert(){
template <typename Less>
_FORCE_INLINE_ int bisect(const Vector<Variant> &p_array, const Variant &p_value, bool p_before, const Less &p_less) {
int lo = 0;
int hi = p_array.size();
if (p_before) {
while (lo < hi) {
const int mid = (lo + hi) / 2;
if (p_less(p_array.get(mid), p_value)) {
lo = mid + 1;
} else {
hi = mid;
}
}
} else {
while (lo < hi) {
const int mid = (lo + hi) / 2;
if (p_less(p_value, p_array.get(mid))) {
hi = mid;
} else {
lo = mid + 1;
}
}
}
return lo;
}
int Array::bsearch(const Variant &p_value, bool p_before) {
return bisect(_p->array, p_value, p_before, _ArrayVariantSort());
}
int Array::bsearch_custom(const Variant &p_value, Object *p_obj, const StringName &p_function, bool p_before) {
ERR_FAIL_NULL_V(p_obj, 0);
_ArrayVariantSortCustom less;
less.obj = p_obj;
less.func = p_function;
return bisect(_p->array, p_value, p_before, less);
}
Array &Array::invert() {
_p->array.invert();
return *this;
}
void Array::push_front(const Variant &p_value) {
_p->array.insert(0, p_value);
void Array::push_front(const Variant& p_value) {
_p->array.insert(0,p_value);
}
Variant Array::pop_back() {
if (!_p->array.empty()) {
const int n = _p->array.size() - 1;
const Variant ret = _p->array.get(n);
_p->array.resize(n);
return ret;
}
return Variant();
}
void Array::pop_back(){
Variant Array::pop_front() {
if (!_p->array.empty()) {
const Variant ret = _p->array.get(0);
if (!_p->array.empty())
_p->array.resize( _p->array.size() -1 );
}
void Array::pop_front(){
if (!_p->array.empty())
_p->array.remove(0);
return ret;
}
return Variant();
}
Variant Array::pop_at(int p_pos) {
if (_p->array.empty()) {
// Return `null` without printing an error to mimic `pop_back()` and `pop_front()` behavior.
return Variant();
}
if (p_pos < 0) {
// Relative offset from the end
p_pos = _p->array.size() + p_pos;
}
Array::Array(const Array& p_from) {
ERR_FAIL_INDEX_V_MSG(
p_pos,
_p->array.size(),
Variant(),
vformat(
"The calculated index %s is out of bounds (the array has %s elements). Leaving the array untouched and returning `null`.",
p_pos,
_p->array.size()));
const Variant ret = _p->array.get(p_pos);
_p->array.remove(p_pos);
return ret;
}
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;
}
const void *Array::id() const {
return _p->array.ptr();
}
Array::Array(const Array &p_from) {
_p = nullptr;
_p=NULL;
_ref(p_from);
}
Array::Array() {
_p = memnew(ArrayPrivate);
}
Array::Array(bool p_shared) {
_p = memnew( ArrayPrivate );
_p->refcount.init();
_p->shared=p_shared;
}
Array::~Array() {
_unref();
}

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,83 +26,70 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef ARRAY_H
#define ARRAY_H
#include "core/typedefs.h"
#include "typedefs.h"
class Variant;
class ArrayPrivate;
class Object;
class StringName;
class Array {
mutable ArrayPrivate *_p;
void _ref(const Array &p_from) const;
void _ref(const Array& p_from) const;
void _unref() const;
inline int _clamp_slice_index(int p_index) const;
public:
Variant &operator[](int p_idx);
const Variant &operator[](int p_idx) const;
void set(int p_idx, const Variant &p_value);
const Variant &get(int p_idx) const;
Variant& operator[](int p_idx);
const Variant& operator[](int p_idx) const;
void set(int p_idx,const Variant& p_value);
const Variant& get(int p_idx) const;
int size() const;
bool empty() const;
void clear();
bool operator==(const Array &p_array) const;
bool is_shared() const;
bool operator==(const Array& p_array) const;
uint32_t hash() const;
void operator=(const Array &p_array);
void operator=(const Array& p_array);
void push_back(const Variant &p_value);
_FORCE_INLINE_ void append(const Variant &p_value) { push_back(p_value); } //for python compatibility
void append_array(const Array &p_array);
void push_back(const Variant& p_value);
_FORCE_INLINE_ void append(const Variant& p_value) { push_back(p_value); } //for python compatibility
Error resize(int p_new_size);
void insert(int p_pos, const Variant &p_value);
void insert(int p_pos, const Variant& p_value);
void remove(int p_pos);
Variant front() const;
Variant back() const;
Array &sort();
Array &sort_custom(Object *p_obj, const StringName &p_function);
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();
void sort();
void sort_custom(Object *p_obj,const StringName& p_function);
void invert();
int find(const Variant &p_value, int p_from = 0) const;
int rfind(const Variant &p_value, int p_from = -1) const;
int find_last(const Variant &p_value) const;
int count(const Variant &p_value) const;
bool has(const Variant &p_value) const;
int find(const Variant& p_value, int p_from=0) const;
int rfind(const Variant& p_value, int p_from=-1) const;
int find_last(const Variant& p_value) const;
int count(const Variant& p_value) const;
bool has(const Variant& p_value) const;
void erase(const Variant &p_value);
void erase(const Variant& p_value);
void push_front(const Variant &p_value);
Variant pop_back();
Variant pop_front();
Variant pop_at(int p_pos);
void push_front(const Variant& p_value);
void pop_back();
void pop_front();
Array duplicate(bool p_deep = false) const;
Array slice(int p_begin, int p_end, int p_step = 1, bool p_deep = false) const;
Variant min() const;
Variant max() const;
const void *id() const;
Array(const Array &p_from);
Array();
Array(const Array& p_from);
Array(bool p_shared=false);
~Array();
};
#endif // ARRAY_H

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,79 +0,0 @@
/*************************************************************************/
/* bitfield_dynamic.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 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 "bitfield_dynamic.h"
#include "core/os/memory.h"
#include <string.h>
void BitFieldDynamic::copy_from(const BitFieldDynamic &p_source) {
create(p_source.get_num_bits(), false);
memcpy(_data, p_source.get_data(), p_source.get_num_bytes());
}
void BitFieldDynamic::create(uint32_t p_num_bits, bool p_blank) {
// first delete any initial
destroy();
_num_bits = p_num_bits;
if (p_num_bits) {
_num_bytes = (p_num_bits / 8) + 1;
_data = (uint8_t *)memalloc(_num_bytes);
if (p_blank) {
blank(false);
}
}
}
void BitFieldDynamic::destroy() {
if (_data) {
memfree(_data);
_data = nullptr;
}
_num_bytes = 0;
_num_bits = 0;
}
void BitFieldDynamic::blank(bool p_set_or_zero) {
if (p_set_or_zero) {
memset(_data, 255, _num_bytes);
} else {
memset(_data, 0, _num_bytes);
}
}
void BitFieldDynamic::invert() {
for (uint32_t n = 0; n < _num_bytes; n++) {
_data[n] = ~_data[n];
}
}

View File

@@ -1,111 +0,0 @@
/*************************************************************************/
/* bitfield_dynamic.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 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 BITFIELD_DYNAMIC_H
#define BITFIELD_DYNAMIC_H
#include "core/error_macros.h"
class BitFieldDynamic {
public:
~BitFieldDynamic() { destroy(); }
private:
// prevent copying (see effective C++ scott meyers)
// there is no implementation for copy constructor, hence compiler will complain if you try to copy
// feel free to add one if needed...
BitFieldDynamic &operator=(const BitFieldDynamic &);
public:
// create automatically blanks
void create(uint32_t p_num_bits, bool p_blank = true);
void destroy();
// public funcs
uint32_t get_num_bits() const { return _num_bits; }
uint32_t get_bit(uint32_t p_bit) const;
void set_bit(uint32_t p_bit, uint32_t p_set);
bool check_and_set(uint32_t p_bit);
void blank(bool p_set_or_zero = false);
void invert();
void copy_from(const BitFieldDynamic &p_source);
// loading / saving
uint8_t *get_data() { return _data; }
const uint8_t *get_data() const { return _data; }
uint32_t get_num_bytes() const { return _num_bytes; }
protected:
// member vars
uint8_t *_data = nullptr;
uint32_t _num_bytes = 0;
uint32_t _num_bits = 0;
};
inline uint32_t BitFieldDynamic::get_bit(uint32_t p_bit) const {
DEV_ASSERT(_data);
uint32_t byte_number = p_bit >> 3; // divide by 8
DEV_ASSERT(byte_number < _num_bytes);
uint8_t uc = _data[byte_number];
uint32_t bit_set = uc & (1 << (p_bit & 7));
return bit_set;
}
inline bool BitFieldDynamic::check_and_set(uint32_t p_bit) {
DEV_ASSERT(_data);
uint32_t byte_number = p_bit >> 3; // divide by 8
DEV_ASSERT(byte_number < _num_bytes);
uint8_t &uc = _data[byte_number];
uint32_t mask = (1 << (p_bit & 7));
uint32_t bit_set = uc & mask;
if (bit_set) {
return false;
}
// set
uc = uc | mask;
return true;
}
inline void BitFieldDynamic::set_bit(uint32_t p_bit, uint32_t p_set) {
DEV_ASSERT(_data);
uint32_t byte_number = p_bit >> 3; // divide by 8
DEV_ASSERT(byte_number < _num_bytes);
uint8_t uc = _data[byte_number];
uint32_t mask = 1 << (p_bit & 7);
if (p_set) {
uc = uc | mask;
} else {
uc &= ~mask;
}
_data[byte_number] = uc;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,415 +0,0 @@
/*************************************************************************/
/* class_db.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef CLASS_DB_H
#define CLASS_DB_H
#include "core/method_bind.h"
#include "core/object.h"
#include "core/print_string.h"
/** To bind more then 6 parameters include this:
* #include "core/method_bind_ext.gen.inc"
*/
#define DEFVAL(m_defval) (m_defval)
//#define SIMPLE_METHODDEF
#ifdef DEBUG_METHODS_ENABLED
struct MethodDefinition {
StringName name;
Vector<StringName> args;
MethodDefinition() {}
MethodDefinition(const char *p_name) :
name(p_name) {}
MethodDefinition(const StringName &p_name) :
name(p_name) {}
};
MethodDefinition D_METHOD(const char *p_name);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11, const char *p_arg12);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11, const char *p_arg12, const char *p_arg13);
#else
//#define NO_VARIADIC_MACROS
#ifdef NO_VARIADIC_MACROS
static _FORCE_INLINE_ const char *D_METHOD(const char *m_name, ...) {
return m_name;
}
#else
// When DEBUG_METHODS_ENABLED is set this will let the engine know
// the argument names for easier debugging.
#define D_METHOD(m_c, ...) m_c
#endif
#endif
class ClassDB {
public:
enum APIType {
API_CORE,
API_EDITOR,
API_NONE
};
public:
struct PropertySetGet {
int index;
StringName setter;
StringName getter;
MethodBind *_setptr;
MethodBind *_getptr;
Variant::Type type;
};
struct ClassInfo {
APIType api;
ClassInfo *inherits_ptr;
void *class_ptr;
HashMap<StringName, MethodBind *> method_map;
HashMap<StringName, int> constant_map;
HashMap<StringName, List<StringName>> enum_map;
HashMap<StringName, MethodInfo> signal_map;
List<PropertyInfo> property_list;
#ifdef DEBUG_METHODS_ENABLED
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;
StringName inherits;
StringName name;
bool disabled;
bool exposed;
Object *(*creation_func)();
ClassInfo();
~ClassInfo();
};
template <class T>
static Object *creator() {
return memnew(T);
}
static RWLock lock;
static HashMap<StringName, ClassInfo> classes;
static HashMap<StringName, StringName> resource_base_extensions;
static HashMap<StringName, StringName> compat_classes;
#ifdef DEBUG_METHODS_ENABLED
static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount);
#else
static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const char *method_name, const Variant **p_defs, int p_defcount);
#endif
static APIType current_api;
static void _add_class2(const StringName &p_class, const StringName &p_inherits);
static HashMap<StringName, HashMap<StringName, Variant>> default_values;
static Set<StringName> default_values_cached;
private:
// Non-locking variants of get_parent_class and is_parent_class.
static StringName _get_parent_class(const StringName &p_class);
static bool _is_parent_class(const StringName &p_class, const StringName &p_inherits);
public:
// DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!!
template <class T>
static void _add_class() {
_add_class2(T::get_class_static(), T::get_parent_class_static());
}
template <class T>
static void register_class() {
GLOBAL_LOCK_FUNCTION;
T::initialize_class();
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t);
t->creation_func = &creator<T>;
t->exposed = true;
t->class_ptr = T::get_class_ptr_static();
T::register_custom_data_to_otdb();
}
template <class T>
static void register_virtual_class() {
GLOBAL_LOCK_FUNCTION;
T::initialize_class();
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t);
t->exposed = true;
t->class_ptr = T::get_class_ptr_static();
//nothing
}
template <class T>
static Object *_create_ptr_func() {
return T::create();
}
template <class T>
static void register_custom_instance_class() {
GLOBAL_LOCK_FUNCTION;
T::initialize_class();
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t);
t->creation_func = &_create_ptr_func<T>;
t->exposed = true;
t->class_ptr = T::get_class_ptr_static();
T::register_custom_data_to_otdb();
}
static void get_class_list(List<StringName> *p_classes);
static void get_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes);
static void get_direct_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes);
static StringName get_parent_class_nocheck(const StringName &p_class);
static StringName get_parent_class(const StringName &p_class);
static bool class_exists(const StringName &p_class);
static bool is_parent_class(const StringName &p_class, const StringName &p_inherits);
static bool can_instance(const StringName &p_class);
static Object *instance(const StringName &p_class);
static APIType get_api_type(const StringName &p_class);
static uint64_t get_api_hash(APIType p_api);
template <class N, class M>
static MethodBind *bind_method(N p_method_name, M p_method) {
MethodBind *bind = create_method_bind(p_method);
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, nullptr, 0); //use static function, much smaller binary usage
}
template <class N, class M>
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1) {
MethodBind *bind = create_method_bind(p_method);
const Variant *ptr[1] = { &p_def1 };
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 1);
}
template <class N, class M>
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2) {
MethodBind *bind = create_method_bind(p_method);
const Variant *ptr[2] = { &p_def1, &p_def2 };
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 2);
}
template <class N, class M>
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3) {
MethodBind *bind = create_method_bind(p_method);
const Variant *ptr[3] = { &p_def1, &p_def2, &p_def3 };
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 3);
}
template <class N, class M>
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4) {
MethodBind *bind = create_method_bind(p_method);
const Variant *ptr[4] = { &p_def1, &p_def2, &p_def3, &p_def4 };
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 4);
}
template <class N, class M>
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5) {
MethodBind *bind = create_method_bind(p_method);
const Variant *ptr[5] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5 };
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 5);
}
template <class N, class M>
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6) {
MethodBind *bind = create_method_bind(p_method);
const Variant *ptr[6] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6 };
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 6);
}
template <class N, class M>
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6, const Variant &p_def7) {
MethodBind *bind = create_method_bind(p_method);
const Variant *ptr[7] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6, &p_def7 };
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 7);
}
template <class N, class M>
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6, const Variant &p_def7, const Variant &p_def8) {
MethodBind *bind = create_method_bind(p_method);
const Variant *ptr[8] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6, &p_def7, &p_def8 };
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 8);
}
template <class M>
static MethodBind *bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const Vector<Variant> &p_default_args = Vector<Variant>(), bool p_return_nil_is_variant = true) {
GLOBAL_LOCK_FUNCTION;
MethodBind *bind = create_vararg_method_bind(p_method, p_info, p_return_nil_is_variant);
ERR_FAIL_COND_V(!bind, nullptr);
bind->set_name(p_name);
bind->set_default_arguments(p_default_args);
String instance_type = bind->get_instance_class();
ClassInfo *type = classes.getptr(instance_type);
if (!type) {
memdelete(bind);
ERR_FAIL_COND_V(!type, nullptr);
}
if (type->method_map.has(p_name)) {
memdelete(bind);
// overloading not supported
ERR_FAIL_V_MSG(nullptr, "Method already bound: " + instance_type + "::" + p_name + ".");
}
type->method_map[p_name] = bind;
#ifdef DEBUG_METHODS_ENABLED
// FIXME: <reduz> set_return_type is no longer in MethodBind, so I guess it should be moved to vararg method bind
//bind->set_return_type("Variant");
type->method_order.push_back(p_name);
#endif
return bind;
}
static void add_signal(StringName p_class, const MethodInfo &p_signal);
static bool has_signal(StringName p_class, StringName p_signal);
static bool get_signal(StringName p_class, StringName p_signal, MethodInfo *r_signal);
static void get_signal_list(StringName p_class, List<MethodInfo> *p_signals, bool p_no_inheritance = false);
static void add_property_group(StringName p_class, const String &p_name, const String &p_prefix = "");
static void add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
static void set_property_default_value(StringName p_class, const StringName &p_name, const Variant &p_default);
static void get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance = false, const Object *p_validator = nullptr);
static bool set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid = nullptr);
static bool get_property(Object *p_object, const StringName &p_property, Variant &r_value);
static bool has_property(const StringName &p_class, const StringName &p_property, bool p_no_inheritance = false);
static int get_property_index(const StringName &p_class, const StringName &p_property, bool *r_is_valid = nullptr);
static Variant::Type get_property_type(const StringName &p_class, const StringName &p_property, bool *r_is_valid = nullptr);
static StringName get_property_setter(StringName p_class, const StringName &p_property);
static StringName get_property_getter(StringName p_class, const StringName &p_property);
static bool has_method(StringName p_class, StringName p_method, bool p_no_inheritance = false);
static void set_method_flags(StringName p_class, StringName p_method, int p_flags);
static void get_method_list(StringName p_class, List<MethodInfo> *p_methods, bool p_no_inheritance = false, bool p_exclude_from_properties = false);
static MethodBind *get_method(StringName p_class, StringName p_name);
static void add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual = true);
static void get_virtual_methods(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance = false);
static void bind_integer_constant(const StringName &p_class, const StringName &p_enum, const StringName &p_name, int p_constant);
static void get_integer_constant_list(const StringName &p_class, List<String> *p_constants, bool p_no_inheritance = false);
static int get_integer_constant(const StringName &p_class, const StringName &p_name, bool *p_success = nullptr);
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 bool has_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false);
static Variant class_get_default_property_value(const StringName &p_class, const StringName &p_property, bool *r_valid = nullptr);
static StringName get_category(const StringName &p_node);
static void set_class_enabled(StringName p_class, bool p_enable);
static bool is_class_enabled(StringName p_class);
static bool is_class_exposed(StringName p_class);
static void add_resource_base_extension(const StringName &p_extension, const StringName &p_class);
static void get_resource_base_extensions(List<String> *p_extensions);
static void get_extensions_for_type(const StringName &p_class, List<String> *p_extensions);
static void add_compatibility_class(const StringName &p_class, const StringName &p_fallback);
static void set_current_api(APIType p_api);
static APIType get_current_api();
static void cleanup_defaults();
static void cleanup();
};
#ifdef DEBUG_METHODS_ENABLED
#define BIND_CONSTANT(m_constant) \
ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
#define BIND_ENUM_CONSTANT(m_constant) \
ClassDB::bind_integer_constant(get_class_static(), __constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant);
#else
#define BIND_CONSTANT(m_constant) \
ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
#define BIND_ENUM_CONSTANT(m_constant) \
ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
#endif
#ifdef TOOLS_ENABLED
#define BIND_VMETHOD(m_method) \
ClassDB::add_virtual_method(get_class_static(), m_method);
#else
#define BIND_VMETHOD(m_method)
#endif
#endif // CLASS_DB_H

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,153 +26,108 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "color.h"
#include "math_funcs.h"
#include "print_string.h"
#include "map.h"
#include "color_names.inc"
#include "core/color_names.inc"
#include "core/map.h"
#include "core/math/math_funcs.h"
#include "core/print_string.h"
uint32_t Color::to_ARGB32() const {
uint32_t Color::to_argb32() const {
uint32_t c = (uint8_t)Math::round(a * 255);
c <<= 8;
c |= (uint8_t)Math::round(r * 255);
c <<= 8;
c |= (uint8_t)Math::round(g * 255);
c <<= 8;
c |= (uint8_t)Math::round(b * 255);
uint32_t c=(uint8_t)(a*255);
c<<=8;
c|=(uint8_t)(r*255);
c<<=8;
c|=(uint8_t)(g*255);
c<<=8;
c|=(uint8_t)(b*255);
return c;
}
uint32_t Color::to_abgr32() const {
uint32_t c = (uint8_t)Math::round(a * 255);
c <<= 8;
c |= (uint8_t)Math::round(b * 255);
c <<= 8;
c |= (uint8_t)Math::round(g * 255);
c <<= 8;
c |= (uint8_t)Math::round(r * 255);
uint32_t Color::to_32() const {
return c;
}
uint32_t Color::to_rgba32() const {
uint32_t c = (uint8_t)Math::round(r * 255);
c <<= 8;
c |= (uint8_t)Math::round(g * 255);
c <<= 8;
c |= (uint8_t)Math::round(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);
uint32_t c=(uint8_t)(a*255);
c<<=8;
c|=(uint8_t)(r*255);
c<<=8;
c|=(uint8_t)(g*255);
c<<=8;
c|=(uint8_t)(b*255);
return c;
}
float Color::get_h() const {
float min = MIN(r, g);
min = MIN(min, b);
float max = MAX(r, g);
max = MAX(max, b);
float min = MIN( r, g );
min = MIN( min, b );
float max = MAX( r, g );
max = MAX( max, b );
float delta = max - min;
if (delta == 0) {
if( delta == 0 )
return 0;
}
float h;
if (r == max) {
h = (g - b) / delta; // between yellow & magenta
} else if (g == max) {
h = 2 + (b - r) / delta; // between cyan & yellow
} else {
h = 4 + (r - g) / delta; // between magenta & cyan
}
if( r == max )
h = ( g - b ) / delta; // between yellow & magenta
else if( g == max )
h = 2 + ( b - r ) / delta; // between cyan & yellow
else
h = 4 + ( r - g ) / delta; // between magenta & cyan
h /= 6.0;
if (h < 0) {
h += 1.0;
}
h/=6.0;
if (h<0)
h+=1.0;
return h;
}
float Color::get_s() const {
float min = MIN(r, g);
min = MIN(min, b);
float max = MAX(r, g);
max = MAX(max, b);
float min = MIN( r, g );
min = MIN( min, b );
float max = MAX( r, g );
max = MAX( max, b );
float delta = max - min;
return (max != 0) ? (delta / max) : 0;
return (max!=0) ? (delta / max) : 0;
}
float Color::get_v() const {
float max = MAX(r, g);
max = MAX(max, b);
float max = MAX( r, g );
max = MAX( max, b );
return max;
}
void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
int i;
float f, p, q, t;
a = p_alpha;
a=p_alpha;
if (p_s == 0) {
if( p_s == 0 ) {
// acp_hromatic (grey)
r = g = b = p_v;
return;
}
p_h *= 6.0;
p_h = Math::fmod(p_h, 6);
i = Math::floor(p_h);
p_h *=6.0;
p_h = Math::fmod(p_h,6);
i = Math::floor( p_h );
f = p_h - i;
p = p_v * (1 - p_s);
q = p_v * (1 - p_s * f);
t = p_v * (1 - p_s * (1 - f));
p = p_v * ( 1 - p_s );
q = p_v * ( 1 - p_s * f );
t = p_v * ( 1 - p_s * ( 1 - f ) );
switch (i) {
switch( i ) {
case 0: // Red is the dominant color
r = p_v;
g = t;
@@ -207,194 +161,176 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
}
}
bool Color::is_equal_approx(const Color &p_color) const {
return Math::is_equal_approx(r, p_color.r) && Math::is_equal_approx(g, p_color.g) && Math::is_equal_approx(b, p_color.b) && Math::is_equal_approx(a, p_color.a);
}
void Color::invert() {
r = 1.0 - r;
g = 1.0 - g;
b = 1.0 - b;
r=1.0-r;
g=1.0-g;
b=1.0-b;
}
void Color::contrast() {
r = Math::fmod(r + 0.5, 1.0);
g = Math::fmod(g + 0.5, 1.0);
b = Math::fmod(b + 0.5, 1.0);
r=Math::fmod(r+0.5,1.0);
g=Math::fmod(g+0.5,1.0);
b=Math::fmod(b+0.5,1.0);
}
Color Color::hex(uint32_t p_hex) {
float a = (p_hex & 0xFF) / 255.0;
p_hex >>= 8;
float b = (p_hex & 0xFF) / 255.0;
p_hex >>= 8;
float g = (p_hex & 0xFF) / 255.0;
p_hex >>= 8;
float r = (p_hex & 0xFF) / 255.0;
return Color(r, g, b, a);
float a = (p_hex&0xFF)/255.0;
p_hex>>=8;
float b = (p_hex&0xFF)/255.0;
p_hex>>=8;
float g = (p_hex&0xFF)/255.0;
p_hex>>=8;
float r = (p_hex&0xFF)/255.0;
return Color(r,g,b,a);
}
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;
static float _parse_col(const String& p_str, int p_ofs) {
return Color(r, g, b, a);
}
int ig=0;
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);
for(int i=0;i<2;i++) {
float rd = r * m;
float gd = g * m;
float bd = b * m;
int c=p_str[i+p_ofs];
int v=0;
return Color(rd, gd, bd, 1.0f);
}
static float _parse_col(const String &p_str, int p_ofs) {
int ig = 0;
for (int i = 0; i < 2; i++) {
int c = p_str[i + p_ofs];
int v = 0;
if (c >= '0' && c <= '9') {
v = c - '0';
} else if (c >= 'a' && c <= 'f') {
v = c - 'a';
v += 10;
} else if (c >= 'A' && c <= 'F') {
v = c - 'A';
v += 10;
if (c>='0' && c<='9') {
v=c-'0';
} else if (c>='a' && c<='f') {
v=c-'a';
v+=10;
} else if (c>='A' && c<='F') {
v=c-'A';
v+=10;
} else {
return -1;
}
if (i == 0) {
ig += v * 16;
} else {
ig += v;
}
if (i==0)
ig+=v*16;
else
ig+=v;
}
return ig;
}
Color Color::inverted() const {
Color c = *this;
Color c=*this;
c.invert();
return c;
}
Color Color::contrasted() const {
Color c = *this;
Color c=*this;
c.contrast();
return c;
}
Color Color::html(const String &p_color) {
Color Color::html(const String& p_color) {
String color = p_color;
if (color.length() == 0) {
if (color.length()==0)
return Color();
}
if (color[0] == '#') {
color = color.substr(1, color.length() - 1);
}
if (color.length() == 3 || color.length() == 4) {
String exp_color;
for (int i = 0; i < color.length(); i++) {
exp_color += color[i];
exp_color += color[i];
}
color = exp_color;
}
if (color[0]=='#')
color=color.substr(1,color.length()-1);
bool alpha = false;
bool alpha=false;
if (color.length() == 8) {
alpha = true;
} else if (color.length() == 6) {
alpha = false;
if (color.length()==8) {
alpha=true;
} else if (color.length()==6) {
alpha=false;
} else {
ERR_FAIL_V_MSG(Color(), "Invalid color code: " + p_color + ".");
ERR_EXPLAIN("Invalid Color Code: "+p_color);
ERR_FAIL_V(Color());
}
int a = 255;
int a=255;
if (alpha) {
a = _parse_col(color, 0);
ERR_FAIL_COND_V_MSG(a < 0, Color(), "Invalid color code: " + p_color + ".");
a=_parse_col(color,0);
if (a<0) {
ERR_EXPLAIN("Invalid Color Code: "+p_color);
ERR_FAIL_V(Color());
}
}
int from = alpha ? 2 : 0;
int from=alpha?2:0;
int r = _parse_col(color, from + 0);
ERR_FAIL_COND_V_MSG(r < 0, Color(), "Invalid color code: " + p_color + ".");
int g = _parse_col(color, from + 2);
ERR_FAIL_COND_V_MSG(g < 0, Color(), "Invalid color code: " + p_color + ".");
int b = _parse_col(color, from + 4);
ERR_FAIL_COND_V_MSG(b < 0, Color(), "Invalid color code: " + p_color + ".");
int r=_parse_col(color,from+0);
if (r<0) {
ERR_EXPLAIN("Invalid Color Code: "+p_color);
ERR_FAIL_V(Color());
}
int g=_parse_col(color,from+2);
if (g<0) {
ERR_EXPLAIN("Invalid Color Code: "+p_color);
ERR_FAIL_V(Color());
}
int b=_parse_col(color,from+4);
if (b<0) {
ERR_EXPLAIN("Invalid Color Code: "+p_color);
ERR_FAIL_V(Color());
}
return Color(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
return Color(r/255.0,g/255.0,b/255.0,a/255.0);
}
bool Color::html_is_valid(const String &p_color) {
bool Color::html_is_valid(const String& p_color) {
String color = p_color;
if (color.length() == 0) {
if (color.length()==0)
return false;
}
if (color[0] == '#') {
color = color.substr(1, color.length() - 1);
}
if (color[0]=='#')
color=color.substr(1,color.length()-1);
bool alpha = false;
bool alpha=false;
if (color.length() == 8) {
alpha = true;
} else if (color.length() == 6) {
alpha = false;
if (color.length()==8) {
alpha=true;
} else if (color.length()==6) {
alpha=false;
} else {
return false;
}
int a=255;
if (alpha) {
int a = _parse_col(color, 0);
if (a < 0) {
a=_parse_col(color,0);
if (a<0) {
return false;
}
}
int from = alpha ? 2 : 0;
int from=alpha?2:0;
int r = _parse_col(color, from + 0);
if (r < 0) {
int r=_parse_col(color,from+0);
if (r<0) {
return false;
}
int g = _parse_col(color, from + 2);
if (g < 0) {
int g=_parse_col(color,from+2);
if (g<0) {
return false;
}
int b = _parse_col(color, from + 4);
if (b < 0) {
int b=_parse_col(color,from+4);
if (b<0) {
return false;
}
return true;
}
Color Color::named(const String &p_name) {
if (_named_colors.empty()) {
_populate_named_colors(); // from color_names.inc
}
if (_named_colors.empty()) _populate_named_colors(); // from color_names.inc
String name = p_name;
// Normalize name
name = name.replace(" ", "");
@@ -403,162 +339,61 @@ Color Color::named(const String &p_name) {
name = name.replace("'", "");
name = name.replace(".", "");
name = name.to_lower();
const Map<String, Color>::Element *color = _named_colors.find(name);
ERR_FAIL_NULL_V_MSG(color, Color(), "Invalid color name: " + p_name + ".");
return color->value();
const Map<String, Color>::Element* color = _named_colors.find(name);
if(color) {
return color->value();
} else {
ERR_EXPLAIN("Invalid Color Name: "+p_name);
ERR_FAIL_V(Color());
}
}
String _to_hex(float p_val) {
int v = Math::round(p_val * 255);
v = CLAMP(v, 0, 255);
int v = p_val * 255;
v = CLAMP(v,0,255);
String ret;
for (int i = 0; i < 2; i++) {
CharType c[2] = { 0, 0 };
int lv = v & 0xF;
if (lv < 10) {
c[0] = '0' + lv;
} else {
c[0] = 'a' + lv - 10;
}
for(int i=0;i<2;i++) {
v >>= 4;
String cs = (const CharType *)c;
CharType c[2]={0,0};
int lv = v&0xF;
if (lv<10)
c[0]='0'+lv;
else
c[0]='a'+lv-10;
v>>=4;
String cs=(const CharType*)c;
ret = cs + ret;
}
return ret;
}
String Color::to_html(bool p_alpha) const {
String txt;
txt += _to_hex(r);
txt += _to_hex(g);
txt += _to_hex(b);
if (p_alpha) {
txt = _to_hex(a) + txt;
}
txt+=_to_hex(r);
txt+=_to_hex(g);
txt+=_to_hex(b);
if (p_alpha)
txt=_to_hex(a)+txt;
return txt;
}
Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const {
Color c;
c.set_hsv(p_h, p_s, p_v, p_a);
return c;
}
// FIXME: Remove once Godot 3.1 has been released
float Color::gray() const {
WARN_DEPRECATED_MSG("'Color.gray()' is deprecated and will be removed in a future version. Use 'Color.v' for a better grayscale approximation.");
return (r + g + b) / 3.0;
return (r+g+b)/3.0;
}
Color::operator String() const {
return rtos(r) + ", " + rtos(g) + ", " + rtos(b) + ", " + rtos(a);
return rtos(r)+", "+rtos(g)+", "+rtos(b)+", "+rtos(a);
}
Color Color::operator+(const Color &p_color) const {
return Color(
r + p_color.r,
g + p_color.g,
b + p_color.b,
a + p_color.a);
}
void Color::operator+=(const Color &p_color) {
r = r + p_color.r;
g = g + p_color.g;
b = b + p_color.b;
a = a + p_color.a;
}
Color Color::operator-(const Color &p_color) const {
return Color(
r - p_color.r,
g - p_color.g,
b - p_color.b,
a - p_color.a);
}
void Color::operator-=(const Color &p_color) {
r = r - p_color.r;
g = g - p_color.g;
b = b - p_color.b;
a = a - p_color.a;
}
Color Color::operator*(const Color &p_color) const {
return Color(
r * p_color.r,
g * p_color.g,
b * p_color.b,
a * p_color.a);
}
Color Color::operator*(const real_t &rvalue) const {
return Color(
r * rvalue,
g * rvalue,
b * rvalue,
a * rvalue);
}
void Color::operator*=(const Color &p_color) {
r = r * p_color.r;
g = g * p_color.g;
b = b * p_color.b;
a = a * p_color.a;
}
void Color::operator*=(const real_t &rvalue) {
r = r * rvalue;
g = g * rvalue;
b = b * rvalue;
a = a * rvalue;
}
Color Color::operator/(const Color &p_color) const {
return Color(
r / p_color.r,
g / p_color.g,
b / p_color.b,
a / p_color.a);
}
Color Color::operator/(const real_t &rvalue) const {
return Color(
r / rvalue,
g / rvalue,
b / rvalue,
a / rvalue);
}
void Color::operator/=(const Color &p_color) {
r = r / p_color.r;
g = g / p_color.g;
b = b / p_color.b;
a = a / p_color.a;
}
void Color::operator/=(const real_t &rvalue) {
if (rvalue == 0) {
r = 1.0;
g = 1.0;
b = 1.0;
a = 1.0;
} else {
r = r / rvalue;
g = g / rvalue;
b = b / rvalue;
a = a / rvalue;
}
};
Color Color::operator-() const {
return Color(
1.0 - r,
1.0 - g,
1.0 - b,
1.0 - a);
}

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,15 +26,18 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef COLOR_H
#define COLOR_H
#include "core/math/math_funcs.h"
#include "core/ustring.h"
#include "ustring.h"
#include "math_funcs.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
struct Color {
union {
struct {
float r;
float g;
@@ -45,187 +47,102 @@ struct Color {
float components[4];
};
bool operator==(const Color &p_color) const { return (r == p_color.r && g == p_color.g && b == p_color.b && a == p_color.a); }
bool operator!=(const Color &p_color) const { return (r != p_color.r || g != p_color.g || b != p_color.b || a != p_color.a); }
bool operator==(const Color &p_color) const { return (r==p_color.r && g==p_color.g && b==p_color.b && a==p_color.a ); }
bool operator!=(const Color &p_color) const { return (r!=p_color.r || g!=p_color.g || b!=p_color.b || a!=p_color.a ); }
uint32_t to_rgba32() const;
uint32_t to_argb32() const;
uint32_t to_abgr32() const;
uint64_t to_rgba64() const;
uint64_t to_argb64() const;
uint64_t to_abgr64() const;
uint32_t to_32() const;
uint32_t to_ARGB32() const;
float gray() const;
float get_h() const;
float get_s() const;
float get_v() const;
void set_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0);
void set_hsv(float p_h, float p_s, float p_v, float p_alpha=1.0);
_FORCE_INLINE_ float &operator[](int idx) {
_FORCE_INLINE_ float& operator[](int idx) {
return components[idx];
}
_FORCE_INLINE_ const float &operator[](int idx) const {
_FORCE_INLINE_ const float& operator[](int idx) const {
return components[idx];
}
Color operator+(const Color &p_color) const;
void operator+=(const Color &p_color);
Color operator-() const;
Color operator-(const Color &p_color) const;
void operator-=(const Color &p_color);
Color operator*(const Color &p_color) const;
Color operator*(const real_t &rvalue) const;
void operator*=(const Color &p_color);
void operator*=(const real_t &rvalue);
Color operator/(const Color &p_color) const;
Color operator/(const real_t &rvalue) const;
void operator/=(const Color &p_color);
void operator/=(const real_t &rvalue);
bool is_equal_approx(const Color &p_color) const;
void invert();
void contrast();
Color inverted() const;
Color contrasted() const;
_FORCE_INLINE_ Color linear_interpolate(const Color &p_to, float p_weight) const {
Color res = *this;
_FORCE_INLINE_ Color linear_interpolate(const Color& p_b, float p_t) const {
res.r += (p_weight * (p_to.r - r));
res.g += (p_weight * (p_to.g - g));
res.b += (p_weight * (p_to.b - b));
res.a += (p_weight * (p_to.a - a));
Color res=*this;
res.r+= (p_t * (p_b.r-r));
res.g+= (p_t * (p_b.g-g));
res.b+= (p_t * (p_b.b-b));
res.a+= (p_t * (p_b.a-a));
return res;
}
_FORCE_INLINE_ Color darkened(float p_amount) const {
Color res = *this;
res.r = res.r * (1.0f - p_amount);
res.g = res.g * (1.0f - p_amount);
res.b = res.b * (1.0f - p_amount);
return res;
}
_FORCE_INLINE_ Color blend(const Color& p_over) const {
_FORCE_INLINE_ Color lightened(float p_amount) const {
Color res = *this;
res.r = res.r + (1.0f - res.r) * p_amount;
res.g = res.g + (1.0f - res.g) * p_amount;
res.b = res.b + (1.0f - res.b) * p_amount;
return res;
}
_FORCE_INLINE_ uint32_t to_rgbe9995() const {
const float pow2to9 = 512.0f;
const float B = 15.0f;
//const float Emax = 31.0f;
const float N = 9.0f;
float sharedexp = 65408.000f; //(( pow2to9 - 1.0f)/ pow2to9)*powf( 2.0f, 31.0f - 15.0f);
float cRed = MAX(0.0f, MIN(sharedexp, r));
float cGreen = MAX(0.0f, MIN(sharedexp, g));
float cBlue = MAX(0.0f, MIN(sharedexp, b));
float cMax = MAX(cRed, MAX(cGreen, cBlue));
// expp = MAX(-B - 1, log2(maxc)) + 1 + B
float expp = MAX(-B - 1.0f, floor(Math::log(cMax) / Math_LN2)) + 1.0f + B;
float sMax = (float)floor((cMax / Math::pow(2.0f, expp - B - N)) + 0.5f);
float exps = expp + 1.0f;
if (0.0 <= sMax && sMax < pow2to9) {
exps = expp;
}
float sRed = Math::floor((cRed / pow(2.0f, exps - B - N)) + 0.5f);
float sGreen = Math::floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
float sBlue = Math::floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
return (uint32_t(Math::fast_ftoi(sRed)) & 0x1FF) | ((uint32_t(Math::fast_ftoi(sGreen)) & 0x1FF) << 9) | ((uint32_t(Math::fast_ftoi(sBlue)) & 0x1FF) << 18) | ((uint32_t(Math::fast_ftoi(exps)) & 0x1F) << 27);
}
_FORCE_INLINE_ Color blend(const Color &p_over) const {
Color res;
float sa = 1.0 - p_over.a;
res.a = a * sa + p_over.a;
if (res.a == 0) {
return Color(0, 0, 0, 0);
res.a = a*sa+p_over.a;
if (res.a==0) {
return Color(0,0,0,0);
} else {
res.r = (r * a * sa + p_over.r * p_over.a) / res.a;
res.g = (g * a * sa + p_over.g * p_over.a) / res.a;
res.b = (b * a * sa + p_over.b * p_over.a) / res.a;
res.r = (r*a*sa + p_over.r * p_over.a)/res.a;
res.g = (g*a*sa + p_over.g * p_over.a)/res.a;
res.b = (b*a*sa + p_over.b * p_over.a)/res.a;
}
return res;
}
_FORCE_INLINE_ Color to_linear() const {
return Color(
r < 0.04045 ? r * (1.0 / 12.92) : Math::pow((r + 0.055) * (1.0 / (1 + 0.055)), 2.4),
g < 0.04045 ? g * (1.0 / 12.92) : Math::pow((g + 0.055) * (1.0 / (1 + 0.055)), 2.4),
b < 0.04045 ? b * (1.0 / 12.92) : Math::pow((b + 0.055) * (1.0 / (1 + 0.055)), 2.4),
a);
}
_FORCE_INLINE_ Color to_srgb() const {
return Color(
r < 0.0031308 ? 12.92 * r : (1.0 + 0.055) * Math::pow(r, 1.0f / 2.4f) - 0.055,
g < 0.0031308 ? 12.92 * g : (1.0 + 0.055) * Math::pow(g, 1.0f / 2.4f) - 0.055,
b < 0.0031308 ? 12.92 * b : (1.0 + 0.055) * Math::pow(b, 1.0f / 2.4f) - 0.055, a);
r<0.04045 ? r * (1.0 / 12.92) : Math::pow((r + 0.055) * (1.0 / (1 + 0.055)), 2.4),
g<0.04045 ? g * (1.0 / 12.92) : Math::pow((g + 0.055) * (1.0 / (1 + 0.055)), 2.4),
b<0.04045 ? b * (1.0 / 12.92) : Math::pow((b + 0.055) * (1.0 / (1 + 0.055)), 2.4),
a
);
}
static Color hex(uint32_t p_hex);
static Color 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_rgbe);
static Color html(const String& p_color);
static bool html_is_valid(const String& p_color);
static Color named(const String& p_name);
String to_html(bool p_alpha=true) const;
_FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys
_FORCE_INLINE_ bool operator<(const Color& p_color) const; //used in set keys
operator String() const;
/**
* No construct parameters, r=0, g=0, b=0. a=255
*/
_FORCE_INLINE_ Color() {
r = 0;
g = 0;
b = 0;
a = 1.0;
r=0; g=0; b=0; a=1.0;
}
/**
* RGB / RGBA construct parameters. Alpha is optional, but defaults to 1.0
*/
_FORCE_INLINE_ Color(float p_r, float p_g, float p_b, float p_a = 1.0) {
r = p_r;
g = p_g;
b = p_b;
a = p_a;
}
_FORCE_INLINE_ Color(float p_r,float p_g,float p_b,float p_a=1.0) { r=p_r; g=p_g; b=p_b; a=p_a; }
};
bool Color::operator<(const Color &p_color) const {
if (r == p_color.r) {
if (g == p_color.g) {
if (b == p_color.b) {
return (a < p_color.a);
} else {
return (b < p_color.b);
}
} else {
return g < p_color.g;
}
} else {
return r < p_color.r;
}
bool Color::operator<(const Color& p_color) const {
if (r==p_color.r) {
if (g==p_color.g) {
if(b==p_color.b) {
return (a<p_color.a);
} else
return (b<p_color.b);
} else
return g<p_color.g;
} else
return r<p_color.r;
}
#endif

View File

@@ -1,11 +1,7 @@
// Names from https://en.wikipedia.org/wiki/X11_color_names
#include "core/map.h"
// 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
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));
@@ -145,7 +141,6 @@ static void _populate_named_colors() {
_named_colors.insert("thistle", Color(0.85, 0.75, 0.85));
_named_colors.insert("tomato", Color(1.00, 0.39, 0.28));
_named_colors.insert("turquoise", Color(0.25, 0.88, 0.82));
_named_colors.insert("transparent", Color(1.00, 1.00, 1.00, 0.00));
_named_colors.insert("violet", Color(0.93, 0.51, 0.93));
_named_colors.insert("wheat", Color(0.96, 0.87, 0.70));
_named_colors.insert("white", Color(1.00, 1.00, 1.00));

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,40 +26,43 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "command_queue_mt.h"
#include "core/os/os.h"
#include "core/project_settings.h"
#include "os/os.h"
void CommandQueueMT::lock() {
mutex.lock();
if (mutex)
mutex->lock();
}
void CommandQueueMT::unlock() {
mutex.unlock();
if (mutex)
mutex->unlock();
}
void CommandQueueMT::wait_for_flush() {
// wait one millisecond for a flush to happen
OS::get_singleton()->delay_usec(1000);
}
CommandQueueMT::SyncSemaphore *CommandQueueMT::_alloc_sync_sem() {
int idx = -1;
CommandQueueMT::SyncSemaphore* CommandQueueMT::_alloc_sync_sem() {
int idx=-1;
while(true) {
for(int i=0;i<SYNC_SEMAPHORES;i++) {
while (true) {
lock();
for (int i = 0; i < SYNC_SEMAPHORES; i++) {
if (!sync_sems[i].in_use) {
sync_sems[i].in_use = true;
idx = i;
sync_sems[i].in_use=true;
idx=i;
break;
}
}
unlock();
if (idx == -1) {
if (idx==-1) {
wait_for_flush();
} else {
break;
@@ -70,53 +72,36 @@ CommandQueueMT::SyncSemaphore *CommandQueueMT::_alloc_sync_sem() {
return &sync_sems[idx];
}
bool CommandQueueMT::dealloc_one() {
tryagain:
if (dealloc_ptr == (write_ptr_and_epoch >> 1)) {
// The queue is empty
return false;
CommandQueueMT::CommandQueueMT(bool p_sync){
read_ptr=0;
write_ptr=0;
mutex = Mutex::create();
for(int i=0;i<SYNC_SEMAPHORES;i++) {
sync_sems[i].sem=Semaphore::create();
sync_sems[i].in_use=false;
}
uint32_t size = *(uint32_t *)&command_mem[dealloc_ptr];
if (size == 0) {
// End of command buffer wrap down
dealloc_ptr = 0;
goto tryagain;
}
if (size & 1) {
// Still used, nothing can be deallocated
return false;
}
dealloc_ptr += (size >> 1) + 8;
return true;
if (p_sync)
sync = Semaphore::create();
else
sync=NULL;
}
CommandQueueMT::CommandQueueMT(bool p_sync) {
read_ptr_and_epoch = 0;
write_ptr_and_epoch = 0;
dealloc_ptr = 0;
command_mem_size = GLOBAL_DEF_RST("memory/limits/command_queue/multithreading_queue_size_kb", DEFAULT_COMMAND_MEM_SIZE_KB);
ProjectSettings::get_singleton()->set_custom_property_info("memory/limits/command_queue/multithreading_queue_size_kb", PropertyInfo(Variant::INT, "memory/limits/command_queue/multithreading_queue_size_kb", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"));
command_mem_size *= 1024;
command_mem = (uint8_t *)memalloc(command_mem_size);
for (int i = 0; i < SYNC_SEMAPHORES; i++) {
sync_sems[i].in_use = false;
}
if (p_sync) {
sync = memnew(Semaphore);
} else {
sync = nullptr;
}
}
CommandQueueMT::~CommandQueueMT() {
if (sync) {
if (sync)
memdelete(sync);
memdelete(mutex);
for(int i=0;i<SYNC_SEMAPHORES;i++) {
memdelete(sync_sems[i].sem);
}
memfree(command_mem);
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,16 +26,224 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "compressed_translation.h"
#include "pair.h"
#include <string.h>
#include "core/pair.h"
/////////// SMAZ /////////////
extern "C" {
#include "thirdparty/misc/smaz.h"
/*
Copyright (c) 2006-2009, Salvatore Sanfilippo
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of Smaz nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Our compression codebook, used for compression */
static const char *Smaz_cb[241] = {
"\002s,\266", "\003had\232\002leW", "\003on \216", "", "\001yS",
"\002ma\255\002li\227", "\003or \260", "", "\002ll\230\003s t\277",
"\004fromg\002mel", "", "\003its\332", "\001z\333", "\003ingF", "\001>\336",
"\001 \000\003 (\002nc\344", "\002nd=\003 on\312",
"\002ne\213\003hat\276\003re q", "", "\002ngT\003herz\004have\306\003s o\225",
"", "\003ionk\003s a\254\002ly\352", "\003hisL\003 inN\003 be\252", "",
"\003 fo\325\003 of \003 ha\311", "", "\002of\005",
"\003 co\241\002no\267\003 ma\370", "", "", "\003 cl\356\003enta\003 an7",
"\002ns\300\001\"e", "\003n t\217\002ntP\003s, \205",
"\002pe\320\003 we\351\002om\223", "\002on\037", "", "\002y G", "\003 wa\271",
"\003 re\321\002or*", "", "\002=\"\251\002ot\337", "\003forD\002ou[",
"\003 toR", "\003 th\r", "\003 it\366",
"\003but\261\002ra\202\003 wi\363\002</\361", "\003 wh\237", "\002 4",
"\003nd ?", "\002re!", "", "\003ng c", "",
"\003ly \307\003ass\323\001a\004\002rir", "", "", "", "\002se_", "\003of \"",
"\003div\364\002ros\003ere\240", "", "\002ta\310\001bZ\002si\324", "",
"\003and\a\002rs\335", "\002rt\362", "\002teE", "\003ati\316", "\002so\263",
"\002th\021", "\002tiJ\001c\034\003allp", "\003ate\345", "\002ss\246",
"\002stM", "", "\002><\346", "\002to\024", "\003arew", "\001d\030",
"\002tr\303", "", "\001\n1\003 a \222", "\003f tv\002veo", "\002un\340", "",
"\003e o\242", "\002a \243\002wa\326\001e\002", "\002ur\226\003e a\274",
"\002us\244\003\n\r\n\247", "\002ut\304\003e c\373", "\002we\221", "", "",
"\002wh\302", "\001f,", "", "", "", "\003d t\206", "", "", "\003th \343",
"\001g;", "", "", "\001\r9\003e s\265", "\003e t\234", "", "\003to Y",
"\003e\r\n\236", "\002d \036\001h\022", "", "\001,Q", "\002 a\031", "\002 b^",
"\002\r\n\025\002 cI", "\002 d\245", "\002 e\253", "\002 fh\001i\b\002e \v",
"", "\002 hU\001-\314", "\002 i8", "", "", "\002 l\315", "\002 m{",
"\002f :\002 n\354", "\002 o\035", "\002 p}\001.n\003\r\n\r\250", "",
"\002 r\275", "\002 s>", "\002 t\016", "", "\002g \235\005which+\003whi\367",
"\002 w5", "\001/\305", "\003as \214", "\003at \207", "", "\003who\331", "",
"\001l\026\002h \212", "", "\002, $", "", "\004withV", "", "", "", "\001m-", "",
"", "\002ac\357", "\002ad\350", "\003TheH", "", "", "\004this\233\001n\t",
"", "\002. y", "", "\002alX\003e, \365", "\003tio\215\002be\\",
"\002an\032\003ver\347", "", "\004that0\003tha\313\001o\006", "\003was2",
"\002arO", "\002as.", "\002at'\003the\001\004they\200\005there\322\005theird",
"\002ce\210", "\004were]", "", "\002ch\231\002l \264\001p<", "", "",
"\003one\256", "", "\003he \023\002dej", "\003ter\270", "\002cou", "",
"\002by\177\002di\201\002eax", "", "\002ec\327", "\002edB", "\002ee\353", "",
"", "\001r\f\002n )", "", "", "", "\002el\262", "", "\003in i\002en3", "",
"\002o `\001s\n", "", "\002er\033", "\003is t\002es6", "", "\002ge\371",
"\004.com\375", "\002fo\334\003our\330", "\003ch \301\001t\003", "\002hab", "",
"\003men\374", "", "\002he\020", "", "", "\001u&", "\002hif", "",
"\003not\204\002ic\203", "\003ed @\002id\355", "", "", "\002ho\273",
"\002r K\001vm", "", "", "", "\003t t\257\002il\360", "\002im\342",
"\003en \317\002in\017", "\002io\220", "\002s \027\001wA", "", "\003er |",
"\003es ~\002is%", "\002it/", "", "\002iv\272", "",
"\002t #\ahttp://C\001x\372", "\002la\211", "\001<\341", "\003, a\224"
};
/* Reverse compression codebook, used for decompression */
static const char *Smaz_rcb[254] = {
" ", "the", "e", "t", "a", "of", "o", "and", "i", "n", "s", "e ", "r", " th",
" t", "in", "he", "th", "h", "he ", "to", "\r\n", "l", "s ", "d", " a", "an",
"er", "c", " o", "d ", "on", " of", "re", "of ", "t ", ", ", "is", "u", "at",
" ", "n ", "or", "which", "f", "m", "as", "it", "that", "\n", "was", "en",
" ", " w", "es", " an", " i", "\r", "f ", "g", "p", "nd", " s", "nd ", "ed ",
"w", "ed", "http://", "for", "te", "ing", "y ", "The", " c", "ti", "r ", "his",
"st", " in", "ar", "nt", ",", " to", "y", "ng", " h", "with", "le", "al", "to ",
"b", "ou", "be", "were", " b", "se", "o ", "ent", "ha", "ng ", "their", "\"",
"hi", "from", " f", "in ", "de", "ion", "me", "v", ".", "ve", "all", "re ",
"ri", "ro", "is ", "co", "f t", "are", "ea", ". ", "her", " m", "er ", " p",
"es ", "by", "they", "di", "ra", "ic", "not", "s, ", "d t", "at ", "ce", "la",
"h ", "ne", "as ", "tio", "on ", "n t", "io", "we", " a ", "om", ", a", "s o",
"ur", "li", "ll", "ch", "had", "this", "e t", "g ", "e\r\n", " wh", "ere",
" co", "e o", "a ", "us", " d", "ss", "\n\r\n", "\r\n\r", "=\"", " be", " e",
"s a", "ma", "one", "t t", "or ", "but", "el", "so", "l ", "e s", "s,", "no",
"ter", " wa", "iv", "ho", "e a", " r", "hat", "s t", "ns", "ch ", "wh", "tr",
"ut", "/", "have", "ly ", "ta", " ha", " on", "tha", "-", " l", "ati", "en ",
"pe", " re", "there", "ass", "si", " fo", "wa", "ec", "our", "who", "its", "z",
"fo", "rs", ">", "ot", "un", "<", "im", "th ", "nc", "ate", "><", "ver", "ad",
" we", "ly", "ee", " n", "id", " cl", "ac", "il", "</", "rt", " wi", "div",
"e, ", " it", "whi", " ma", "ge", "x", "e c", "men", ".com"
};
static int smaz_compress(const char *in, int inlen, char *out, int outlen) {
unsigned int h1,h2,h3=0;
int verblen = 0, _outlen = outlen;
char verb[256], *_out = out;
while(inlen) {
int j = 7, needed;
char *flush = NULL;
const char *slot;
h1 = h2 = in[0]<<3;
if (inlen > 1) h2 += in[1];
if (inlen > 2) h3 = h2^in[2];
if (j > inlen) j = inlen;
/* Try to lookup substrings into the hash table, starting from the
* longer to the shorter substrings */
for (; j > 0; j--) {
switch(j) {
case 1: slot = Smaz_cb[h1%241]; break;
case 2: slot = Smaz_cb[h2%241]; break;
default: slot = Smaz_cb[h3%241]; break;
}
while(slot[0]) {
if (slot[0] == j && memcmp(slot+1,in,j) == 0) {
/* Match found in the hash table,
* prepare a verbatim bytes flush if needed */
if (verblen) {
needed = (verblen == 1) ? 2 : 2+verblen;
flush = out;
out += needed;
outlen -= needed;
}
/* Emit the byte */
if (outlen <= 0) return _outlen+1;
out[0] = slot[slot[0]+1];
out++;
outlen--;
inlen -= j;
in += j;
goto out;
} else {
slot += slot[0]+2;
}
}
}
/* Match not found - add the byte to the verbatim buffer */
verb[verblen] = in[0];
verblen++;
inlen--;
in++;
out:
/* Prepare a flush if we reached the flush length limit, and there
* is not already a pending flush operation. */
if (!flush && (verblen == 256 || (verblen > 0 && inlen == 0))) {
needed = (verblen == 1) ? 2 : 2+verblen;
flush = out;
out += needed;
outlen -= needed;
if (outlen < 0) return _outlen+1;
}
/* Perform a verbatim flush if needed */
if (flush) {
if (verblen == 1) {
flush[0] = (signed char)254;
flush[1] = verb[0];
} else {
flush[0] = (signed char)255;
flush[1] = (signed char)(verblen-1);
memcpy(flush+2,verb,verblen);
}
flush = NULL;
verblen = 0;
}
}
return out-_out;
}
static int smaz_decompress(const char *in, int inlen, char *out, int outlen) {
unsigned char *c = (unsigned char*) in;
char *_out = out;
int _outlen = outlen;
while(inlen) {
if (*c == 254) {
/* Verbatim byte */
if (outlen < 1) return _outlen+1;
*out = *(c+1);
out++;
outlen--;
c += 2;
inlen -= 2;
} else if (*c == 255) {
/* Verbatim string */
int len = (*(c+1))+1;
if (outlen < len) return _outlen+1;
memcpy(out,c+2,len);
out += len;
outlen -= len;
c += 2+len;
inlen -= 2+len;
} else {
/* Codebook entry */
const char *s = Smaz_rcb[*c];
int len = strlen(s);
if (outlen < len) return _outlen+1;
memcpy(out,s,len);
out += len;
outlen -= len;
c++;
inlen--;
}
}
return out-_out;
}
/////////// END OF SMAZ /////////////
struct _PHashTranslationCmp {
int orig_len;
CharString compressed;
int offset;
@@ -44,234 +251,284 @@ struct _PHashTranslationCmp {
void PHashTranslation::generate(const Ref<Translation> &p_from) {
#ifdef TOOLS_ENABLED
ERR_FAIL_COND(p_from.is_null());
List<StringName> keys;
p_from->get_message_list(&keys);
int size = Math::larger_prime(keys.size());
int size=Math::larger_prime(keys.size());
Vector<Vector<Pair<int, CharString>>> buckets;
Vector<Map<uint32_t, int>> table;
Vector<uint32_t> hfunc_table;
Vector<_PHashTranslationCmp> compressed;
print_line("compressing keys: "+itos(keys.size()));
Vector< Vector< Pair<int,CharString> > > buckets;
Vector< Map< uint32_t, int > > table;
Vector< uint32_t > hfunc_table;
Vector< _PHashTranslationCmp > compressed;
table.resize(size);
hfunc_table.resize(size);
buckets.resize(size);
compressed.resize(keys.size());
int idx = 0;
int total_compression_size = 0;
int idx=0;
int total_compression_size=0;
int total_string_size=0;
for(List<StringName>::Element *E=keys.front();E;E=E->next()) {
for (List<StringName>::Element *E = keys.front(); E; E = E->next()) {
//hash string
CharString cs = E->get().operator String().utf8();
uint32_t h = hash(0, cs.get_data());
Pair<int, CharString> p;
p.first = idx;
p.second = cs;
buckets.write[h % size].push_back(p);
uint32_t h = hash(0,cs.get_data());
Pair<int,CharString> p;
p.first=idx;
p.second=cs;
buckets[h % size].push_back(p);
//compress string
CharString src_s = p_from->get_message(E->get()).operator String().utf8();
_PHashTranslationCmp ps;
ps.orig_len = src_s.size();
ps.offset = total_compression_size;
ps.orig_len=src_s.size();
ps.offset=total_compression_size;
if (ps.orig_len != 0) {
if (ps.orig_len!=0) {
CharString dst_s;
dst_s.resize(src_s.size());
int ret = smaz_compress(src_s.get_data(), src_s.size(), dst_s.ptrw(), src_s.size());
if (ret >= src_s.size()) {
int ret = smaz_compress(src_s.get_data(),src_s.size(),&dst_s[0],src_s.size());
if (ret>=src_s.size()) {
//if compressed is larger than original, just use original
ps.orig_len = src_s.size();
ps.compressed = src_s;
ps.orig_len=src_s.size();
ps.compressed=src_s;
} else {
dst_s.resize(ret);
//ps.orig_len=;
ps.compressed = dst_s;
ps.compressed=dst_s;
}
} else {
ps.orig_len = 1;
ps.orig_len=1;
ps.compressed.resize(1);
ps.compressed[0] = 0;
ps.compressed[0]=0;
}
compressed.write[idx] = ps;
total_compression_size += ps.compressed.size();
compressed[idx]=ps;
total_compression_size+=ps.compressed.size();
total_string_size+=src_s.size();
idx++;
}
int bucket_table_size = 0;
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];
for(int i=0;i<size;i++) {
if (b.size() == 0) {
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;
int item =0;
while (item < b.size()) {
uint32_t slot = hash(d, b[item].second.get_data());
while(item < b.size()) {
uint32_t slot = hash(d,b[item].second.get_data());
if (t.has(slot)) {
item = 0;
item=0;
d++;
t.clear();
} else {
t[slot] = b[item].first;
t[slot]=b[item].first;
item++;
}
}
hfunc_table.write[i] = d;
bucket_table_size += 2 + b.size() * 4;
hfunc_table[i]=d;
bucket_table_size+=2+b.size()*4;
}
ERR_FAIL_COND(bucket_table_size == 0);
print_line("bucket table size: "+itos(bucket_table_size*4));
print_line("hash table size: "+itos(size*4));
hash_table.resize(size);
bucket_table.resize(bucket_table_size);
PoolVector<int>::Write htwb = hash_table.write();
PoolVector<int>::Write btwb = bucket_table.write();
DVector<int>::Write htwb = hash_table.write();
DVector<int>::Write btwb = bucket_table.write();
uint32_t *htw = (uint32_t *)&htwb[0];
uint32_t *btw = (uint32_t *)&btwb[0];
uint32_t *htw = (uint32_t*)&htwb[0];
uint32_t *btw = (uint32_t*)&btwb[0];
int btindex = 0;
int btindex=0;
int collisions=0;
for (int i = 0; i < size; i++) {
const Map<uint32_t, int> &t = table[i];
if (t.size() == 0) {
htw[i] = 0xFFFFFFFF; //nothing
for(int i=0;i<size;i++) {
Map< uint32_t, int > &t=table[i];
if (t.size()==0) {
htw[i]=0xFFFFFFFF; //nothing
continue;
} else if (t.size()>1) {
collisions+=t.size()-1;
}
htw[i] = btindex;
btw[btindex++] = t.size();
btw[btindex++] = hfunc_table[i];
htw[i]=btindex;
btw[btindex++]=t.size();
btw[btindex++]=hfunc_table[i];
for (Map<uint32_t, int>::Element *E = t.front(); E; E = E->next()) {
btw[btindex++] = E->key();
btw[btindex++] = compressed[E->get()].offset;
btw[btindex++] = compressed[E->get()].compressed.size();
btw[btindex++] = compressed[E->get()].orig_len;
for( Map< uint32_t, int >::Element *E=t.front();E;E=E->next()) {
btw[btindex++]=E->key();
btw[btindex++]=compressed[E->get()].offset;
btw[btindex++]=compressed[E->get()].compressed.size();
btw[btindex++]=compressed[E->get()].orig_len;
}
}
print_line("total collisions: "+itos(collisions));
strings.resize(total_compression_size);
PoolVector<uint8_t>::Write cw = strings.write();
DVector<uint8_t>::Write cw = strings.write();
for (int i = 0; i < compressed.size(); i++) {
memcpy(&cw[compressed[i].offset], compressed[i].compressed.get_data(), compressed[i].compressed.size());
for(int i=0;i<compressed.size();i++) {
memcpy(&cw[compressed[i].offset],compressed[i].compressed.get_data(),compressed[i].compressed.size());
}
ERR_FAIL_COND(btindex != bucket_table_size);
ERR_FAIL_COND(btindex!=bucket_table_size);
set_locale(p_from->get_locale());
#endif
}
bool PHashTranslation::_set(const StringName &p_name, const Variant &p_value) {
bool PHashTranslation::_set(const StringName& p_name, const Variant& p_value) {
String name = p_name.operator String();
if (name == "hash_table") {
hash_table = p_value;
} else if (name == "bucket_table") {
bucket_table = p_value;
} else if (name == "strings") {
strings = p_value;
} else if (name == "load_from") {
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 {
} else
return false;
}
return true;
}
bool PHashTranslation::_get(const StringName &p_name, Variant &r_ret) const {
bool PHashTranslation::_get(const StringName& p_name,Variant &r_ret) const{
String name = p_name.operator String();
if (name == "hash_table") {
r_ret = hash_table;
} else if (name == "bucket_table") {
r_ret = bucket_table;
} else if (name == "strings") {
r_ret = strings;
} else {
if (name=="hash_table")
r_ret=hash_table;
else if (name=="bucket_table")
r_ret=bucket_table;
else if (name=="strings")
r_ret=strings;
else
return false;
}
return true;
}
StringName PHashTranslation::get_message(const StringName &p_src_text) const {
StringName PHashTranslation::get_message(const StringName& p_src_text) const {
int htsize = hash_table.size();
if (htsize == 0) {
if (htsize==0)
return StringName();
}
CharString str = p_src_text.operator String().utf8();
uint32_t h = hash(0, str.get_data());
uint32_t h = hash(0,str.get_data());
PoolVector<int>::Read htr = hash_table.read();
const uint32_t *htptr = (const uint32_t *)&htr[0];
PoolVector<int>::Read btr = bucket_table.read();
const uint32_t *btptr = (const uint32_t *)&btr[0];
PoolVector<uint8_t>::Read sr = strings.read();
const char *sptr = (const char *)&sr[0];
uint32_t p = htptr[h % htsize];
DVector<int>::Read htr = hash_table.read();
const uint32_t *htptr = (const uint32_t*)&htr[0];
DVector<int>::Read btr = bucket_table.read();
const uint32_t *btptr = (const uint32_t*)&btr[0];
DVector<uint8_t>::Read sr = strings.read();
const char *sptr= (const char*)&sr[0];
if (p == 0xFFFFFFFF) {
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
}
const Bucket &bucket = *(const Bucket *)&btptr[p];
const Bucket &bucket = *(const Bucket*)&btptr[p];
h = hash(bucket.func, str.get_data());
h = hash(bucket.func,str.get_data());
int idx = -1;
int idx=-1;
for (int i = 0; i < bucket.size; i++) {
if (bucket.elem[i].key == h) {
idx = i;
for(int i=0;i<bucket.size;i++) {
if (bucket.elem[i].key==h) {
idx=i;
break;
}
}
if (idx == -1) {
//print_line("bucket pos: "+itos(idx));
if (idx==-1) {
// print_line("GETMSG: Not in Bucket!");
return StringName();
}
if (bucket.elem[idx].comp_size == bucket.elem[idx].uncomp_size) {
String rstr;
rstr.parse_utf8(&sptr[bucket.elem[idx].str_offset], bucket.elem[idx].uncomp_size);
rstr.parse_utf8(&sptr[ bucket.elem[idx].str_offset ], bucket.elem[idx].uncomp_size );
// print_line("Uncompressed, size: "+itos(bucket.elem[idx].comp_size));
// print_line("Return: "+rstr);
return rstr;
} else {
CharString uncomp;
uncomp.resize(bucket.elem[idx].uncomp_size + 1);
smaz_decompress(&sptr[bucket.elem[idx].str_offset], bucket.elem[idx].comp_size, uncomp.ptrw(), bucket.elem[idx].uncomp_size);
uncomp.resize( bucket.elem[idx].uncomp_size+1 );
smaz_decompress(&sptr[ bucket.elem[idx].str_offset ], bucket.elem[idx].comp_size,uncomp.ptr(),bucket.elem[idx].uncomp_size );
String rstr;
rstr.parse_utf8(uncomp.get_data());
// print_line("Compressed, size: "+itos(bucket.elem[idx].comp_size));
// print_line("Return: "+rstr);
return rstr;
}
}
void PHashTranslation::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::POOL_INT_ARRAY, "hash_table"));
p_list->push_back(PropertyInfo(Variant::POOL_INT_ARRAY, "bucket_table"));
p_list->push_back(PropertyInfo(Variant::POOL_BYTE_ARRAY, "strings"));
p_list->push_back(PropertyInfo(Variant::OBJECT, "load_from", PROPERTY_HINT_RESOURCE_TYPE, "Translation", PROPERTY_USAGE_EDITOR));
void PHashTranslation::_get_property_list( List<PropertyInfo> *p_list) const{
p_list->push_back( PropertyInfo(Variant::INT_ARRAY, "hash_table"));
p_list->push_back( PropertyInfo(Variant::INT_ARRAY, "bucket_table"));
p_list->push_back( PropertyInfo(Variant::RAW_ARRAY, "strings"));
p_list->push_back( PropertyInfo(Variant::OBJECT, "load_from",PROPERTY_HINT_RESOURCE_TYPE,"Translation",PROPERTY_USAGE_EDITOR));
}
void PHashTranslation::_bind_methods() {
ClassDB::bind_method(D_METHOD("generate", "from"), &PHashTranslation::generate);
ObjectTypeDB::bind_method(_MD("generate","from:Translation"),&PHashTranslation::generate);
}
PHashTranslation::PHashTranslation() {
PHashTranslation::PHashTranslation()
{
}

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,30 +26,34 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef COMPRESSED_TRANSLATION_H
#define COMPRESSED_TRANSLATION_H
#include "core/translation.h"
#include "translation.h"
class PHashTranslation : public Translation {
GDCLASS(PHashTranslation, Translation);
OBJ_TYPE(PHashTranslation,Translation);
//this translation uses a sort of modified perfect hash algorithm
//it requires hashing strings twice and then does a binary search,
//it requieres hashing strings twice and then does a binary search,
//so it's slower, but at the same time it has an extreemly high chance
//of catching untranslated strings
//load/store friendly types
PoolVector<int> hash_table;
PoolVector<int> bucket_table;
PoolVector<uint8_t> strings;
DVector<int> hash_table;
DVector<int> bucket_table;
DVector<uint8_t> strings;
struct Bucket {
int size;
uint32_t func;
struct Elem {
uint32_t key;
uint32_t str_offset;
uint32_t comp_size;
@@ -60,26 +63,28 @@ class PHashTranslation : public Translation {
Elem elem[1];
};
_FORCE_INLINE_ uint32_t hash(uint32_t d, const char *p_str) const {
if (d == 0) {
d = 0x1000193;
}
while (*p_str) {
_FORCE_INLINE_ uint32_t hash( uint32_t d, const char *p_str ) const {
if (d==0)
d=0x1000193;
while(*p_str) {
d = (d * 0x1000193) ^ uint32_t(*p_str);
p_str++;
}
return d;
}
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
bool _set(const StringName& p_name, const Variant& p_value);
bool _get(const StringName& p_name,Variant &r_ret) const;
void _get_property_list( List<PropertyInfo> *p_list) const;
static void _bind_methods();
public:
virtual StringName get_message(const StringName &p_src_text) const; //overridable for other implementations
virtual StringName get_message(const StringName& p_src_text) const; //overridable for other implementations
void generate(const Ref<Translation> &p_from);
PHashTranslation();

View File

@@ -1,308 +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",
"Silver sponsors",
"Bronze sponsors",
"Mini sponsors",
"Gold donors",
"Silver donors",
"Bronze donors",
]
sections_id = [
"DONORS_SPONSOR_PLATINUM",
"DONORS_SPONSOR_GOLD",
"DONORS_SPONSOR_SILVER",
"DONORS_SPONSOR_BRONZE",
"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

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,48 +26,23 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "core_string_names.h"
CoreStringNames *CoreStringNames::singleton = nullptr;
CoreStringNames* CoreStringNames::singleton=NULL;
CoreStringNames::CoreStringNames() {
_free=StaticCString::create("free");
changed=StaticCString::create("changed");
_meta=StaticCString::create("__meta__");
_script=StaticCString::create("script/script");
script_changed=StaticCString::create("script_changed");
___pdcdata=StaticCString::create("___pdcdata");
__getvar=StaticCString::create("__getvar");
_iter_init=StaticCString::create("_iter_init");
_iter_next=StaticCString::create("_iter_next");
_iter_get=StaticCString::create("_iter_get");
get_rid=StaticCString::create("get_rid");
CoreStringNames::CoreStringNames() :
_free(StaticCString::create("free")),
changed(StaticCString::create("changed")),
_meta(StaticCString::create("__meta__")),
_script(StaticCString::create("script")),
script_changed(StaticCString::create("script_changed")),
___pdcdata(StaticCString::create("___pdcdata")),
__getvar(StaticCString::create("__getvar")),
_iter_init(StaticCString::create("_iter_init")),
_iter_next(StaticCString::create("_iter_next")),
_iter_get(StaticCString::create("_iter_get")),
get_rid(StaticCString::create("get_rid")),
_to_string(StaticCString::create("_to_string")),
#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")) {
}

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,28 +26,25 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef CORE_STRING_NAMES_H
#define CORE_STRING_NAMES_H
#include "core/string_name.h"
#include "string_db.h"
class CoreStringNames {
friend void register_core_types();
friend void unregister_core_types();
friend void register_core_types();
friend void unregister_core_types();
static CoreStringNames* singleton;
static void create() { singleton = memnew(CoreStringNames); }
static void free() {
memdelete(singleton);
singleton = nullptr;
}
static void free() { memdelete( singleton); singleton=NULL; }
CoreStringNames();
public:
_FORCE_INLINE_ static CoreStringNames *get_singleton() { return singleton; }
_FORCE_INLINE_ static CoreStringNames* get_singleton() { return singleton; }
static CoreStringNames *singleton;
StringName _free;
StringName changed;
@@ -61,34 +57,7 @@ public:
StringName _iter_next;
StringName _iter_get;
StringName get_rid;
StringName _to_string;
#ifdef TOOLS_ENABLED
StringName _sections_unfolded;
#endif
StringName _custom_features;
StringName x;
StringName y;
StringName z;
StringName w;
StringName r;
StringName g;
StringName b;
StringName a;
StringName position;
StringName size;
StringName end;
StringName basis;
StringName origin;
StringName normal;
StringName d;
StringName h;
StringName s;
StringName v;
StringName r8;
StringName g8;
StringName b8;
StringName a8;
};
#endif // SCENE_STRING_NAMES_H

View File

@@ -1,387 +0,0 @@
/*************************************************************************/
/* cowdata.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 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/error_macros.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;
#if !defined(NO_THREADS)
SAFE_NUMERIC_TYPE_PUN_GUARANTEES(uint32_t)
#endif
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_ SafeNumeric<uint32_t> *_get_refcount() const {
if (!_ptr) {
return nullptr;
}
return reinterpret_cast<SafeNumeric<uint32_t> *>(_ptr) - 2;
}
_FORCE_INLINE_ uint32_t *_get_size() const {
if (!_ptr) {
return nullptr;
}
return reinterpret_cast<uint32_t *>(_ptr) - 1;
}
_FORCE_INLINE_ T *_get_data() const {
if (!_ptr) {
return nullptr;
}
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);
uint32_t _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 == nullptr; }
_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;
}
SafeNumeric<uint32_t> *refc = _get_refcount();
if (refc->decrement() > 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>
uint32_t CowData<T>::_copy_on_write() {
if (!_ptr) {
return 0;
}
SafeNumeric<uint32_t> *refc = _get_refcount();
uint32_t rc = refc->get();
if (likely(rc > 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);
new (mem_new - 2, sizeof(uint32_t), "") SafeNumeric<uint32_t>(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;
rc = 1;
}
return rc;
}
template <class T>
Error CowData<T>::resize(int p_size) {
ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER);
int current_size = size();
if (p_size == current_size) {
return OK;
}
if (p_size == 0) {
// wants to clean up
_unref(_ptr);
_ptr = nullptr;
return OK;
}
// possibly changing size, copy on write
uint32_t rc = _copy_on_write();
size_t current_alloc_size = _get_alloc_size(current_size);
size_t alloc_size;
ERR_FAIL_COND_V(!_get_alloc_size_checked(p_size, &alloc_size), ERR_OUT_OF_MEMORY);
if (p_size > current_size) {
if (alloc_size != current_alloc_size) {
if (current_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
new (ptr - 2, sizeof(uint32_t), "") SafeNumeric<uint32_t>(1); //refcount
_ptr = (T *)ptr;
} else {
uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true);
ERR_FAIL_COND_V(!_ptrnew, ERR_OUT_OF_MEMORY);
new (_ptrnew - 2, sizeof(uint32_t), "") SafeNumeric<uint32_t>(rc); //refcount
_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 < current_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();
}
}
if (alloc_size != current_alloc_size) {
uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true);
ERR_FAIL_COND_V(!_ptrnew, ERR_OUT_OF_MEMORY);
new (_ptrnew - 2, sizeof(uint32_t), "") SafeNumeric<uint32_t>(rc); //refcount
_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 = nullptr;
if (!p_from._ptr) {
return; //nothing to do
}
if (p_from._get_refcount()->conditional_increment() > 0) { // could reference
_ptr = p_from._ptr;
}
}
template <class T>
CowData<T>::CowData() {
_ptr = nullptr;
}
template <class T>
CowData<T>::~CowData() {
_unref(_ptr);
}
#endif /* COW_H_ */

View File

@@ -1,51 +0,0 @@
#!/usr/bin/env python
Import("env")
env_crypto = env.Clone()
is_builtin = env["builtin_mbedtls"]
has_module = env["module_mbedtls_enabled"]
thirdparty_obj = []
if is_builtin or not has_module:
# Use our headers for builtin or if the module is not going to be compiled.
# We decided not to depend on system mbedtls just for these few files that can
# be easily extracted.
env_crypto.Prepend(CPPPATH=["#thirdparty/mbedtls/include"])
# MbedTLS core functions (for CryptoCore).
# If the mbedtls module is compiled we don't need to add the .c files with our
# custom config since they will be built by the module itself.
# Only if the module is not enabled, we must compile here the required sources
# to make a "light" build with only the necessary mbedtls files.
if not has_module:
env_thirdparty = env_crypto.Clone()
env_thirdparty.disable_warnings()
# Custom config file
env_thirdparty.Append(
CPPDEFINES=[("MBEDTLS_CONFIG_FILE", '\\"thirdparty/mbedtls/include/godot_core_mbedtls_config.h\\"')]
)
thirdparty_mbedtls_dir = "#thirdparty/mbedtls/library/"
thirdparty_mbedtls_sources = [
"aes.c",
"base64.c",
"md5.c",
"sha1.c",
"sha256.c",
"godot_core_mbedtls_platform.c",
]
thirdparty_mbedtls_sources = [thirdparty_mbedtls_dir + file for file in thirdparty_mbedtls_sources]
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_mbedtls_sources)
env.core_sources += thirdparty_obj
# Godot source files
core_obj = []
env_crypto.add_source_files(core_obj, "*.cpp")
env.core_sources += core_obj
# Needed to force rebuilding the core files when the thirdparty library is updated.
env.Depends(core_obj, thirdparty_obj)

View File

@@ -1,116 +0,0 @@
/*************************************************************************/
/* aes_context.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 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 "core/crypto/aes_context.h"
Error AESContext::start(Mode p_mode, PoolByteArray p_key, PoolByteArray p_iv) {
ERR_FAIL_COND_V_MSG(mode != MODE_MAX, ERR_ALREADY_IN_USE, "AESContext already started. Call 'finish' before starting a new one.");
ERR_FAIL_COND_V_MSG(p_mode < 0 || p_mode >= MODE_MAX, ERR_INVALID_PARAMETER, "Invalid mode requested.");
// Key check.
int key_bits = p_key.size() << 3;
ERR_FAIL_COND_V_MSG(key_bits != 128 && key_bits != 256, ERR_INVALID_PARAMETER, "AES key must be either 16 or 32 bytes");
// Initialization vector.
if (p_mode == MODE_CBC_ENCRYPT || p_mode == MODE_CBC_DECRYPT) {
ERR_FAIL_COND_V_MSG(p_iv.size() != 16, ERR_INVALID_PARAMETER, "The initialization vector (IV) must be exactly 16 bytes.");
iv.resize(0);
iv.append_array(p_iv);
}
// Encryption/decryption key.
if (p_mode == MODE_CBC_ENCRYPT || p_mode == MODE_ECB_ENCRYPT) {
ctx.set_encode_key(p_key.read().ptr(), key_bits);
} else {
ctx.set_decode_key(p_key.read().ptr(), key_bits);
}
mode = p_mode;
return OK;
}
PoolByteArray AESContext::update(PoolByteArray p_src) {
ERR_FAIL_COND_V_MSG(mode < 0 || mode >= MODE_MAX, PoolByteArray(), "AESContext not started. Call 'start' before calling 'update'.");
int len = p_src.size();
ERR_FAIL_COND_V_MSG(len % 16, PoolByteArray(), "The number of bytes to be encrypted must be multiple of 16. Add padding if needed");
PoolByteArray out;
out.resize(len);
const uint8_t *src_ptr = p_src.read().ptr();
uint8_t *out_ptr = out.write().ptr();
switch (mode) {
case MODE_ECB_ENCRYPT: {
for (int i = 0; i < len; i += 16) {
Error err = ctx.encrypt_ecb(src_ptr + i, out_ptr + i);
ERR_FAIL_COND_V(err != OK, PoolByteArray());
}
} break;
case MODE_ECB_DECRYPT: {
for (int i = 0; i < len; i += 16) {
Error err = ctx.decrypt_ecb(src_ptr + i, out_ptr + i);
ERR_FAIL_COND_V(err != OK, PoolByteArray());
}
} break;
case MODE_CBC_ENCRYPT: {
Error err = ctx.encrypt_cbc(len, iv.write().ptr(), p_src.read().ptr(), out.write().ptr());
ERR_FAIL_COND_V(err != OK, PoolByteArray());
} break;
case MODE_CBC_DECRYPT: {
Error err = ctx.decrypt_cbc(len, iv.write().ptr(), p_src.read().ptr(), out.write().ptr());
ERR_FAIL_COND_V(err != OK, PoolByteArray());
} break;
default:
ERR_FAIL_V_MSG(PoolByteArray(), "Bug!");
}
return out;
}
PoolByteArray AESContext::get_iv_state() {
ERR_FAIL_COND_V_MSG(mode != MODE_CBC_ENCRYPT && mode != MODE_CBC_DECRYPT, PoolByteArray(), "Calling 'get_iv_state' only makes sense when the context is started in CBC mode.");
PoolByteArray out;
out.append_array(iv);
return out;
}
void AESContext::finish() {
mode = MODE_MAX;
iv.resize(0);
}
void AESContext::_bind_methods() {
ClassDB::bind_method(D_METHOD("start", "mode", "key", "iv"), &AESContext::start, DEFVAL(PoolByteArray()));
ClassDB::bind_method(D_METHOD("update", "src"), &AESContext::update);
ClassDB::bind_method(D_METHOD("get_iv_state"), &AESContext::get_iv_state);
ClassDB::bind_method(D_METHOD("finish"), &AESContext::finish);
BIND_ENUM_CONSTANT(MODE_ECB_ENCRYPT);
BIND_ENUM_CONSTANT(MODE_ECB_DECRYPT);
BIND_ENUM_CONSTANT(MODE_CBC_ENCRYPT);
BIND_ENUM_CONSTANT(MODE_CBC_DECRYPT);
BIND_ENUM_CONSTANT(MODE_MAX);
}
AESContext::AESContext() {
mode = MODE_MAX;
}

View File

@@ -1,68 +0,0 @@
/*************************************************************************/
/* aes_context.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 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 AES_CONTEXT_H
#define AES_CONTEXT_H
#include "core/crypto/crypto_core.h"
#include "core/reference.h"
class AESContext : public Reference {
GDCLASS(AESContext, Reference);
public:
enum Mode {
MODE_ECB_ENCRYPT,
MODE_ECB_DECRYPT,
MODE_CBC_ENCRYPT,
MODE_CBC_DECRYPT,
MODE_MAX
};
private:
Mode mode;
CryptoCore::AESContext ctx;
PoolByteArray iv;
protected:
static void _bind_methods();
public:
Error start(Mode p_mode, PoolByteArray p_key, PoolByteArray p_iv = PoolByteArray());
PoolByteArray update(PoolByteArray p_src);
PoolByteArray get_iv_state();
void finish();
AESContext();
};
VARIANT_ENUM_CAST(AESContext::Mode);
#endif // AES_CONTEXT_H

View File

@@ -1,222 +0,0 @@
/*************************************************************************/
/* crypto.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 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 "crypto.h"
#include "core/engine.h"
#include "core/io/certs_compressed.gen.h"
#include "core/io/compression.h"
/// Resources
CryptoKey *(*CryptoKey::_create)() = nullptr;
CryptoKey *CryptoKey::create() {
if (_create) {
return _create();
}
return nullptr;
}
void CryptoKey::_bind_methods() {
ClassDB::bind_method(D_METHOD("save", "path", "public_only"), &CryptoKey::save, DEFVAL(false));
ClassDB::bind_method(D_METHOD("load", "path", "public_only"), &CryptoKey::load, DEFVAL(false));
ClassDB::bind_method(D_METHOD("is_public_only"), &CryptoKey::is_public_only);
ClassDB::bind_method(D_METHOD("save_to_string", "public_only"), &CryptoKey::save_to_string, DEFVAL(false));
ClassDB::bind_method(D_METHOD("load_from_string", "string_key", "public_only"), &CryptoKey::load_from_string, DEFVAL(false));
}
X509Certificate *(*X509Certificate::_create)() = nullptr;
X509Certificate *X509Certificate::create() {
if (_create) {
return _create();
}
return nullptr;
}
void X509Certificate::_bind_methods() {
ClassDB::bind_method(D_METHOD("save", "path"), &X509Certificate::save);
ClassDB::bind_method(D_METHOD("load", "path"), &X509Certificate::load);
}
/// HMACContext
void HMACContext::_bind_methods() {
ClassDB::bind_method(D_METHOD("start", "hash_type", "key"), &HMACContext::start);
ClassDB::bind_method(D_METHOD("update", "data"), &HMACContext::update);
ClassDB::bind_method(D_METHOD("finish"), &HMACContext::finish);
}
HMACContext *(*HMACContext::_create)() = nullptr;
HMACContext *HMACContext::create() {
if (_create) {
return _create();
}
ERR_FAIL_V_MSG(nullptr, "HMACContext is not available when the mbedtls module is disabled.");
}
/// Crypto
void (*Crypto::_load_default_certificates)(String p_path) = nullptr;
Crypto *(*Crypto::_create)() = nullptr;
Crypto *Crypto::create() {
if (_create) {
return _create();
}
ERR_FAIL_V_MSG(nullptr, "Crypto is not available when the mbedtls module is disabled.");
}
void Crypto::load_default_certificates(String p_path) {
if (_load_default_certificates) {
_load_default_certificates(p_path);
}
}
PoolByteArray Crypto::hmac_digest(HashingContext::HashType p_hash_type, PoolByteArray p_key, PoolByteArray p_msg) {
Ref<HMACContext> ctx = Ref<HMACContext>(HMACContext::create());
ERR_FAIL_COND_V_MSG(ctx.is_null(), PoolByteArray(), "HMAC is not available without mbedtls module.");
Error err = ctx->start(p_hash_type, p_key);
ERR_FAIL_COND_V(err != OK, PoolByteArray());
err = ctx->update(p_msg);
ERR_FAIL_COND_V(err != OK, PoolByteArray());
return ctx->finish();
}
// Compares two HMACS for equality without leaking timing information in order to prevent timing attakcs.
// @see: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy
bool Crypto::constant_time_compare(PoolByteArray p_trusted, PoolByteArray p_received) {
const uint8_t *t = p_trusted.read().ptr();
const uint8_t *r = p_received.read().ptr();
int tlen = p_trusted.size();
int rlen = p_received.size();
// If the lengths are different then nothing else matters.
if (tlen != rlen) {
return false;
}
uint8_t v = 0;
for (int i = 0; i < tlen; i++) {
v |= t[i] ^ r[i];
}
return v == 0;
}
void Crypto::_bind_methods() {
ClassDB::bind_method(D_METHOD("generate_random_bytes", "size"), &Crypto::generate_random_bytes);
ClassDB::bind_method(D_METHOD("generate_rsa", "size"), &Crypto::generate_rsa);
ClassDB::bind_method(D_METHOD("generate_self_signed_certificate", "key", "issuer_name", "not_before", "not_after"), &Crypto::generate_self_signed_certificate, DEFVAL("CN=myserver,O=myorganisation,C=IT"), DEFVAL("20140101000000"), DEFVAL("20340101000000"));
ClassDB::bind_method(D_METHOD("sign", "hash_type", "hash", "key"), &Crypto::sign);
ClassDB::bind_method(D_METHOD("verify", "hash_type", "hash", "signature", "key"), &Crypto::verify);
ClassDB::bind_method(D_METHOD("encrypt", "key", "plaintext"), &Crypto::encrypt);
ClassDB::bind_method(D_METHOD("decrypt", "key", "ciphertext"), &Crypto::decrypt);
ClassDB::bind_method(D_METHOD("hmac_digest", "hash_type", "key", "msg"), &Crypto::hmac_digest);
ClassDB::bind_method(D_METHOD("constant_time_compare", "trusted", "received"), &Crypto::constant_time_compare);
}
Crypto::Crypto() {
}
/// Resource loader/saver
RES ResourceFormatLoaderCrypto::load(const String &p_path, const String &p_original_path, Error *r_error) {
String el = p_path.get_extension().to_lower();
if (el == "crt") {
X509Certificate *cert = X509Certificate::create();
if (cert) {
cert->load(p_path);
}
return cert;
} else if (el == "key") {
CryptoKey *key = CryptoKey::create();
if (key) {
key->load(p_path, false);
}
return key;
} else if (el == "pub") {
CryptoKey *key = CryptoKey::create();
if (key) {
key->load(p_path, true);
}
return key;
}
return nullptr;
}
void ResourceFormatLoaderCrypto::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("crt");
p_extensions->push_back("key");
p_extensions->push_back("pub");
}
bool ResourceFormatLoaderCrypto::handles_type(const String &p_type) const {
return p_type == "X509Certificate" || p_type == "CryptoKey";
}
String ResourceFormatLoaderCrypto::get_resource_type(const String &p_path) const {
String el = p_path.get_extension().to_lower();
if (el == "crt") {
return "X509Certificate";
} else if (el == "key" || el == "pub") {
return "CryptoKey";
}
return "";
}
Error ResourceFormatSaverCrypto::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
Error err;
Ref<X509Certificate> cert = p_resource;
Ref<CryptoKey> key = p_resource;
if (cert.is_valid()) {
err = cert->save(p_path);
} else if (key.is_valid()) {
String el = p_path.get_extension().to_lower();
err = key->save(p_path, el == "pub");
} else {
ERR_FAIL_V(ERR_INVALID_PARAMETER);
}
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save Crypto resource to file '" + p_path + "'.");
return OK;
}
void ResourceFormatSaverCrypto::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
const X509Certificate *cert = Object::cast_to<X509Certificate>(*p_resource);
const CryptoKey *key = Object::cast_to<CryptoKey>(*p_resource);
if (cert) {
p_extensions->push_back("crt");
}
if (key) {
if (!key->is_public_only()) {
p_extensions->push_back("key");
}
p_extensions->push_back("pub");
}
}
bool ResourceFormatSaverCrypto::recognize(const RES &p_resource) const {
return Object::cast_to<X509Certificate>(*p_resource) || Object::cast_to<CryptoKey>(*p_resource);
}

View File

@@ -1,134 +0,0 @@
/*************************************************************************/
/* crypto.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 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 CRYPTO_H
#define CRYPTO_H
#include "core/crypto/hashing_context.h"
#include "core/reference.h"
#include "core/resource.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
class CryptoKey : public Resource {
GDCLASS(CryptoKey, Resource);
protected:
static void _bind_methods();
static CryptoKey *(*_create)();
public:
static CryptoKey *create();
virtual Error load(String p_path, bool p_public_only = false) = 0;
virtual Error save(String p_path, bool p_public_only = false) = 0;
virtual String save_to_string(bool p_public_only = false) = 0;
virtual Error load_from_string(String p_string_key, bool p_public_only = false) = 0;
virtual bool is_public_only() const = 0;
};
class X509Certificate : public Resource {
GDCLASS(X509Certificate, Resource);
protected:
static void _bind_methods();
static X509Certificate *(*_create)();
public:
static X509Certificate *create();
virtual Error load(String p_path) = 0;
virtual Error load_from_memory(const uint8_t *p_buffer, int p_len) = 0;
virtual Error save(String p_path) = 0;
};
class HMACContext : public Reference {
GDCLASS(HMACContext, Reference);
protected:
static void _bind_methods();
static HMACContext *(*_create)();
public:
static HMACContext *create();
virtual Error start(HashingContext::HashType p_hash_type, PoolByteArray p_key) = 0;
virtual Error update(PoolByteArray p_data) = 0;
virtual PoolByteArray finish() = 0;
HMACContext() {}
virtual ~HMACContext() {}
};
class Crypto : public Reference {
GDCLASS(Crypto, Reference);
protected:
static void _bind_methods();
static Crypto *(*_create)();
static void (*_load_default_certificates)(String p_path);
public:
static Crypto *create();
static void load_default_certificates(String p_path);
virtual PoolByteArray generate_random_bytes(int p_bytes) = 0;
virtual Ref<CryptoKey> generate_rsa(int p_bytes) = 0;
virtual Ref<X509Certificate> generate_self_signed_certificate(Ref<CryptoKey> p_key, String p_issuer_name, String p_not_before, String p_not_after) = 0;
virtual Vector<uint8_t> sign(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Ref<CryptoKey> p_key) = 0;
virtual bool verify(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Vector<uint8_t> p_signature, Ref<CryptoKey> p_key) = 0;
virtual Vector<uint8_t> encrypt(Ref<CryptoKey> p_key, Vector<uint8_t> p_plaintext) = 0;
virtual Vector<uint8_t> decrypt(Ref<CryptoKey> p_key, Vector<uint8_t> p_ciphertext) = 0;
PoolByteArray hmac_digest(HashingContext::HashType p_hash_type, PoolByteArray p_key, PoolByteArray p_msg);
// Compares two PoolByteArrays for equality without leaking timing information in order to prevent timing attacks.
// @see: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy
bool constant_time_compare(PoolByteArray p_trusted, PoolByteArray p_received);
Crypto();
};
class ResourceFormatLoaderCrypto : public ResourceFormatLoader {
public:
virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr);
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;
};
class ResourceFormatSaverCrypto : public ResourceFormatSaver {
public:
virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const;
virtual bool recognize(const RES &p_resource) const;
};
#endif // CRYPTO_H

View File

@@ -1,193 +0,0 @@
/*************************************************************************/
/* crypto_core.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 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 "crypto_core.h"
#include <mbedtls/aes.h>
#include <mbedtls/base64.h>
#include <mbedtls/md5.h>
#include <mbedtls/sha1.h>
#include <mbedtls/sha256.h>
// MD5
CryptoCore::MD5Context::MD5Context() {
ctx = memalloc(sizeof(mbedtls_md5_context));
mbedtls_md5_init((mbedtls_md5_context *)ctx);
}
CryptoCore::MD5Context::~MD5Context() {
mbedtls_md5_free((mbedtls_md5_context *)ctx);
memfree((mbedtls_md5_context *)ctx);
}
Error CryptoCore::MD5Context::start() {
int ret = mbedtls_md5_starts_ret((mbedtls_md5_context *)ctx);
return ret ? FAILED : OK;
}
Error CryptoCore::MD5Context::update(const uint8_t *p_src, size_t p_len) {
int ret = mbedtls_md5_update_ret((mbedtls_md5_context *)ctx, p_src, p_len);
return ret ? FAILED : OK;
}
Error CryptoCore::MD5Context::finish(unsigned char r_hash[16]) {
int ret = mbedtls_md5_finish_ret((mbedtls_md5_context *)ctx, r_hash);
return ret ? FAILED : OK;
}
// SHA1
CryptoCore::SHA1Context::SHA1Context() {
ctx = memalloc(sizeof(mbedtls_sha1_context));
mbedtls_sha1_init((mbedtls_sha1_context *)ctx);
}
CryptoCore::SHA1Context::~SHA1Context() {
mbedtls_sha1_free((mbedtls_sha1_context *)ctx);
memfree((mbedtls_sha1_context *)ctx);
}
Error CryptoCore::SHA1Context::start() {
int ret = mbedtls_sha1_starts_ret((mbedtls_sha1_context *)ctx);
return ret ? FAILED : OK;
}
Error CryptoCore::SHA1Context::update(const uint8_t *p_src, size_t p_len) {
int ret = mbedtls_sha1_update_ret((mbedtls_sha1_context *)ctx, p_src, p_len);
return ret ? FAILED : OK;
}
Error CryptoCore::SHA1Context::finish(unsigned char r_hash[20]) {
int ret = mbedtls_sha1_finish_ret((mbedtls_sha1_context *)ctx, r_hash);
return ret ? FAILED : OK;
}
// SHA256
CryptoCore::SHA256Context::SHA256Context() {
ctx = memalloc(sizeof(mbedtls_sha256_context));
mbedtls_sha256_init((mbedtls_sha256_context *)ctx);
}
CryptoCore::SHA256Context::~SHA256Context() {
mbedtls_sha256_free((mbedtls_sha256_context *)ctx);
memfree((mbedtls_sha256_context *)ctx);
}
Error CryptoCore::SHA256Context::start() {
int ret = mbedtls_sha256_starts_ret((mbedtls_sha256_context *)ctx, 0);
return ret ? FAILED : OK;
}
Error CryptoCore::SHA256Context::update(const uint8_t *p_src, size_t p_len) {
int ret = mbedtls_sha256_update_ret((mbedtls_sha256_context *)ctx, p_src, p_len);
return ret ? FAILED : OK;
}
Error CryptoCore::SHA256Context::finish(unsigned char r_hash[32]) {
int ret = mbedtls_sha256_finish_ret((mbedtls_sha256_context *)ctx, r_hash);
return ret ? FAILED : OK;
}
// AES256
CryptoCore::AESContext::AESContext() {
ctx = memalloc(sizeof(mbedtls_aes_context));
mbedtls_aes_init((mbedtls_aes_context *)ctx);
}
CryptoCore::AESContext::~AESContext() {
mbedtls_aes_free((mbedtls_aes_context *)ctx);
memfree((mbedtls_aes_context *)ctx);
}
Error CryptoCore::AESContext::set_encode_key(const uint8_t *p_key, size_t p_bits) {
int ret = mbedtls_aes_setkey_enc((mbedtls_aes_context *)ctx, p_key, p_bits);
return ret ? FAILED : OK;
}
Error CryptoCore::AESContext::set_decode_key(const uint8_t *p_key, size_t p_bits) {
int ret = mbedtls_aes_setkey_dec((mbedtls_aes_context *)ctx, p_key, p_bits);
return ret ? FAILED : OK;
}
Error CryptoCore::AESContext::encrypt_ecb(const uint8_t p_src[16], uint8_t r_dst[16]) {
int ret = mbedtls_aes_crypt_ecb((mbedtls_aes_context *)ctx, MBEDTLS_AES_ENCRYPT, p_src, r_dst);
return ret ? FAILED : OK;
}
Error CryptoCore::AESContext::decrypt_ecb(const uint8_t p_src[16], uint8_t r_dst[16]) {
int ret = mbedtls_aes_crypt_ecb((mbedtls_aes_context *)ctx, MBEDTLS_AES_DECRYPT, p_src, r_dst);
return ret ? FAILED : OK;
}
Error CryptoCore::AESContext::encrypt_cbc(size_t p_length, uint8_t r_iv[16], const uint8_t *p_src, uint8_t *r_dst) {
int ret = mbedtls_aes_crypt_cbc((mbedtls_aes_context *)ctx, MBEDTLS_AES_ENCRYPT, p_length, r_iv, p_src, r_dst);
return ret ? FAILED : OK;
}
Error CryptoCore::AESContext::decrypt_cbc(size_t p_length, uint8_t r_iv[16], const uint8_t *p_src, uint8_t *r_dst) {
int ret = mbedtls_aes_crypt_cbc((mbedtls_aes_context *)ctx, MBEDTLS_AES_DECRYPT, p_length, r_iv, p_src, r_dst);
return ret ? FAILED : OK;
}
// CryptoCore
String CryptoCore::b64_encode_str(const uint8_t *p_src, int p_src_len) {
int b64len = p_src_len / 3 * 4 + 4 + 1;
PoolVector<uint8_t> b64buff;
b64buff.resize(b64len);
PoolVector<uint8_t>::Write w64 = b64buff.write();
size_t strlen = 0;
int ret = b64_encode(&w64[0], b64len, &strlen, p_src, p_src_len);
w64[strlen] = 0;
return ret ? String() : (const char *)&w64[0];
}
Error CryptoCore::b64_encode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len) {
int ret = mbedtls_base64_encode(r_dst, p_dst_len, r_len, p_src, p_src_len);
return ret ? FAILED : OK;
}
Error CryptoCore::b64_decode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len) {
int ret = mbedtls_base64_decode(r_dst, p_dst_len, r_len, p_src, p_src_len);
return ret ? FAILED : OK;
}
Error CryptoCore::md5(const uint8_t *p_src, int p_src_len, unsigned char r_hash[16]) {
int ret = mbedtls_md5_ret(p_src, p_src_len, r_hash);
return ret ? FAILED : OK;
}
Error CryptoCore::sha1(const uint8_t *p_src, int p_src_len, unsigned char r_hash[20]) {
int ret = mbedtls_sha1_ret(p_src, p_src_len, r_hash);
return ret ? FAILED : OK;
}
Error CryptoCore::sha256(const uint8_t *p_src, int p_src_len, unsigned char r_hash[32]) {
int ret = mbedtls_sha256_ret(p_src, p_src_len, r_hash, 0);
return ret ? FAILED : OK;
}

View File

@@ -1,101 +0,0 @@
/*************************************************************************/
/* crypto_core.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 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 CRYPTO_CORE_H
#define CRYPTO_CORE_H
#include "core/reference.h"
class CryptoCore {
public:
class MD5Context {
private:
void *ctx; // To include, or not to include...
public:
MD5Context();
~MD5Context();
Error start();
Error update(const uint8_t *p_src, size_t p_len);
Error finish(unsigned char r_hash[16]);
};
class SHA1Context {
private:
void *ctx; // To include, or not to include...
public:
SHA1Context();
~SHA1Context();
Error start();
Error update(const uint8_t *p_src, size_t p_len);
Error finish(unsigned char r_hash[20]);
};
class SHA256Context {
private:
void *ctx; // To include, or not to include...
public:
SHA256Context();
~SHA256Context();
Error start();
Error update(const uint8_t *p_src, size_t p_len);
Error finish(unsigned char r_hash[32]);
};
class AESContext {
private:
void *ctx; // To include, or not to include...
public:
AESContext();
~AESContext();
Error set_encode_key(const uint8_t *p_key, size_t p_bits);
Error set_decode_key(const uint8_t *p_key, size_t p_bits);
Error encrypt_ecb(const uint8_t p_src[16], uint8_t r_dst[16]);
Error decrypt_ecb(const uint8_t p_src[16], uint8_t r_dst[16]);
Error encrypt_cbc(size_t p_length, uint8_t r_iv[16], const uint8_t *p_src, uint8_t *r_dst);
Error decrypt_cbc(size_t p_length, uint8_t r_iv[16], const uint8_t *p_src, uint8_t *r_dst);
};
static String b64_encode_str(const uint8_t *p_src, int p_src_len);
static Error b64_encode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len);
static Error b64_decode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len);
static Error md5(const uint8_t *p_src, int p_src_len, unsigned char r_hash[16]);
static Error sha1(const uint8_t *p_src, int p_src_len, unsigned char r_hash[20]);
static Error sha256(const uint8_t *p_src, int p_src_len, unsigned char r_hash[32]);
};
#endif // CRYPTO_CORE_H

View File

@@ -1,138 +0,0 @@
/*************************************************************************/
/* hashing_context.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 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 "hashing_context.h"
#include "core/crypto/crypto_core.h"
Error HashingContext::start(HashType p_type) {
ERR_FAIL_COND_V(ctx != nullptr, ERR_ALREADY_IN_USE);
_create_ctx(p_type);
ERR_FAIL_COND_V(ctx == nullptr, ERR_UNAVAILABLE);
switch (type) {
case HASH_MD5:
return ((CryptoCore::MD5Context *)ctx)->start();
case HASH_SHA1:
return ((CryptoCore::SHA1Context *)ctx)->start();
case HASH_SHA256:
return ((CryptoCore::SHA256Context *)ctx)->start();
}
return ERR_UNAVAILABLE;
}
Error HashingContext::update(PoolByteArray p_chunk) {
ERR_FAIL_COND_V(ctx == nullptr, ERR_UNCONFIGURED);
size_t len = p_chunk.size();
ERR_FAIL_COND_V(len == 0, FAILED);
PoolByteArray::Read r = p_chunk.read();
switch (type) {
case HASH_MD5:
return ((CryptoCore::MD5Context *)ctx)->update(&r[0], len);
case HASH_SHA1:
return ((CryptoCore::SHA1Context *)ctx)->update(&r[0], len);
case HASH_SHA256:
return ((CryptoCore::SHA256Context *)ctx)->update(&r[0], len);
}
return ERR_UNAVAILABLE;
}
PoolByteArray HashingContext::finish() {
ERR_FAIL_COND_V(ctx == nullptr, PoolByteArray());
PoolByteArray out;
Error err = FAILED;
switch (type) {
case HASH_MD5:
out.resize(16);
err = ((CryptoCore::MD5Context *)ctx)->finish(out.write().ptr());
break;
case HASH_SHA1:
out.resize(20);
err = ((CryptoCore::SHA1Context *)ctx)->finish(out.write().ptr());
break;
case HASH_SHA256:
out.resize(32);
err = ((CryptoCore::SHA256Context *)ctx)->finish(out.write().ptr());
break;
}
_delete_ctx();
ERR_FAIL_COND_V(err != OK, PoolByteArray());
return out;
}
void HashingContext::_create_ctx(HashType p_type) {
type = p_type;
switch (type) {
case HASH_MD5:
ctx = memnew(CryptoCore::MD5Context);
break;
case HASH_SHA1:
ctx = memnew(CryptoCore::SHA1Context);
break;
case HASH_SHA256:
ctx = memnew(CryptoCore::SHA256Context);
break;
default:
ctx = nullptr;
}
}
void HashingContext::_delete_ctx() {
switch (type) {
case HASH_MD5:
memdelete((CryptoCore::MD5Context *)ctx);
break;
case HASH_SHA1:
memdelete((CryptoCore::SHA1Context *)ctx);
break;
case HASH_SHA256:
memdelete((CryptoCore::SHA256Context *)ctx);
break;
}
ctx = nullptr;
}
void HashingContext::_bind_methods() {
ClassDB::bind_method(D_METHOD("start", "type"), &HashingContext::start);
ClassDB::bind_method(D_METHOD("update", "chunk"), &HashingContext::update);
ClassDB::bind_method(D_METHOD("finish"), &HashingContext::finish);
BIND_ENUM_CONSTANT(HASH_MD5);
BIND_ENUM_CONSTANT(HASH_SHA1);
BIND_ENUM_CONSTANT(HASH_SHA256);
}
HashingContext::HashingContext() {
ctx = nullptr;
}
HashingContext::~HashingContext() {
if (ctx != nullptr) {
_delete_ctx();
}
}

View File

@@ -1,66 +0,0 @@
/*************************************************************************/
/* hashing_context.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 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 HASHING_CONTEXT_H
#define HASHING_CONTEXT_H
#include "core/reference.h"
class HashingContext : public Reference {
GDCLASS(HashingContext, Reference);
public:
enum HashType {
HASH_MD5,
HASH_SHA1,
HASH_SHA256
};
private:
void *ctx;
HashType type;
protected:
static void _bind_methods();
void _create_ctx(HashType p_type);
void _delete_ctx();
public:
Error start(HashType p_type);
Error update(PoolByteArray p_chunk);
PoolByteArray finish();
HashingContext();
~HashingContext();
};
VARIANT_ENUM_CAST(HashingContext::HashType);
#endif // HASHING_CONTEXT_H

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,243 +26,239 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "dictionary.h"
#include "safe_refcount.h"
#include "variant.h"
#include "io/json.h"
#include "core/ordered_hash_map.h"
#include "core/safe_refcount.h"
#include "core/variant.h"
struct _DictionaryVariantHash {
struct DictionaryPrivate {
SafeRefCount refcount;
OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> variant_map;
static _FORCE_INLINE_ uint32_t hash(const Variant &p_variant) { return p_variant.hash(); }
};
void Dictionary::get_key_list(List<Variant> *p_keys) const {
if (_p->variant_map.empty()) {
struct DictionaryPrivate {
SafeRefCount refcount;
HashMap<Variant,Variant,_DictionaryVariantHash> variant_map;
bool shared;
};
void Dictionary::get_key_list( List<Variant> *p_keys) const {
_p->variant_map.get_key_list(p_keys);
}
void Dictionary::_copy_on_write() const {
//make a copy of what we have
if (_p->shared)
return;
}
for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
p_keys->push_back(E.key());
}
DictionaryPrivate *p = memnew(DictionaryPrivate);
p->shared=_p->shared;
p->variant_map=_p->variant_map;
p->refcount.init();
_unref();
_p=p;
}
Variant Dictionary::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++;
}
Variant& Dictionary::operator[](const Variant& p_key) {
return Variant();
}
_copy_on_write();
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];
}
const Variant &Dictionary::operator[](const Variant &p_key) const {
const Variant& Dictionary::operator[](const Variant& p_key) const {
return _p->variant_map[p_key];
}
const Variant *Dictionary::getptr(const Variant &p_key) const {
OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
if (!E) {
return nullptr;
}
return &E.get();
}
const Variant* Dictionary::getptr(const Variant& p_key) const {
return _p->variant_map.getptr(p_key);
}
Variant* Dictionary::getptr(const Variant& p_key) {
_copy_on_write();
return _p->variant_map.getptr(p_key);
}
Variant *Dictionary::getptr(const Variant &p_key) {
OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.find(p_key);
Variant Dictionary::get_valid(const Variant& p_key) const {
if (!E) {
return nullptr;
}
return &E.get();
}
Variant Dictionary::get_valid(const Variant &p_key) const {
OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
if (!E) {
const Variant *v = getptr(p_key);
if (!v)
return Variant();
}
return E.get();
return *v;
}
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();
}
bool Dictionary::empty() const {
return !_p->variant_map.size();
}
bool Dictionary::has(const Variant &p_key) const {
bool Dictionary::has(const Variant& p_key) const {
return _p->variant_map.has(p_key);
}
bool Dictionary::has_all(const Array &p_keys) const {
for (int i = 0; i < p_keys.size(); i++) {
if (!has(p_keys[i])) {
bool Dictionary::has_all(const Array& p_keys) const {
for (int i=0;i<p_keys.size();i++) {
if( !has(p_keys[i]) ) {
return false;
}
}
return true;
}
bool Dictionary::erase(const Variant &p_key) {
return _p->variant_map.erase(p_key);
void Dictionary::erase(const Variant& p_key) {
_copy_on_write();
_p->variant_map.erase(p_key);
}
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;
}
bool Dictionary::operator!=(const Dictionary &p_dictionary) const {
return _p != p_dictionary._p;
}
void Dictionary::_ref(const Dictionary& p_from) const {
void Dictionary::_ref(const Dictionary &p_from) const {
//make a copy first (thread safe)
if (!p_from._p->refcount.ref()) {
if (!p_from._p->refcount.ref())
return; // couldn't copy
}
//if this is the same, unreference the other one
if (p_from._p == _p) {
if (p_from._p==_p) {
_p->refcount.unref();
return;
}
if (_p) {
if (_p)
_unref();
}
_p = p_from._p;
_p=p_from._p;
}
void Dictionary::clear() {
_copy_on_write();
_p->variant_map.clear();
}
bool Dictionary::is_shared() const {
return _p->shared;
}
void Dictionary::_unref() const {
ERR_FAIL_COND(!_p);
if (_p->refcount.unref()) {
memdelete(_p);
}
_p = nullptr;
_p=NULL;
}
uint32_t Dictionary::hash() const {
uint32_t h = hash_djb2_one_32(Variant::DICTIONARY);
for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
h = hash_djb2_one_32(E.key().hash(), h);
h = hash_djb2_one_32(E.value().hash(), h);
uint32_t h=hash_djb2_one_32(Variant::DICTIONARY);
List<Variant> keys;
get_key_list(&keys);
for (List<Variant>::Element *E=keys.front();E;E=E->next()) {
h = hash_djb2_one_32( E->get().hash(), h);
h = hash_djb2_one_32( operator[](E->get()).hash(), h);
}
return h;
}
Array Dictionary::keys() const {
Array varr;
if (_p->variant_map.empty()) {
return varr;
Array karr;
karr.resize(size());
const Variant *K=NULL;
int idx=0;
while((K=next(K))) {
karr[idx++]=(*K);
}
return karr;
varr.resize(size());
int i = 0;
for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
varr[i] = E.key();
i++;
}
return varr;
}
Array Dictionary::values() const {
Array varr;
if (_p->variant_map.empty()) {
return varr;
}
varr.resize(size());
int i = 0;
for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
varr[i] = E.get();
i++;
const Variant *key=NULL;
int i=0;
while((key=next(key))){
varr[i++] = _p->variant_map[*key];
}
return varr;
}
const Variant *Dictionary::next(const Variant *p_key) const {
if (p_key == nullptr) {
// caller wants to get the first element
if (_p->variant_map.front()) {
return &_p->variant_map.front().key();
const Variant* Dictionary::next(const Variant* p_key) const {
return _p->variant_map.next(p_key);
}
Error Dictionary::parse_json(const String& p_json) {
String errstr;
int errline=0;
if (p_json != ""){
Error err = JSON::parse(p_json,*this,errstr,errline);
if (err!=OK) {
ERR_EXPLAIN("Error parsing JSON: "+errstr+" at line: "+itos(errline));
ERR_FAIL_COND_V(err!=OK,err);
}
return nullptr;
}
OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.find(*p_key);
if (E && E.next()) {
return &E.next().key();
}
return nullptr;
return OK;
}
Dictionary Dictionary::duplicate(bool p_deep) const {
Dictionary n;
String Dictionary::to_json() const {
for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
n[E.key()] = p_deep ? E.value().duplicate(true) : E.value();
}
return n;
return JSON::print(*this);
}
void Dictionary::operator=(const Dictionary &p_dictionary) {
void Dictionary::operator=(const Dictionary& p_dictionary) {
_ref(p_dictionary);
}
const void *Dictionary::id() const {
return _p->variant_map.id();
}
Dictionary::Dictionary(const Dictionary &p_from) {
_p = nullptr;
Dictionary::Dictionary(const Dictionary& p_from) {
_p=NULL;
_ref(p_from);
}
Dictionary::Dictionary() {
_p = memnew(DictionaryPrivate);
Dictionary::Dictionary(bool p_shared) {
_p=memnew( DictionaryPrivate );
_p->refcount.init();
_p->shared=p_shared;
}
Dictionary::~Dictionary() {
_unref();
}

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,64 +26,65 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef DICTIONARY_H
#define DICTIONARY_H
#include "core/array.h"
#include "core/list.h"
#include "core/ustring.h"
#include "list.h"
#include "array.h"
#include "ustring.h"
class Variant;
struct DictionaryPrivate;
class Dictionary {
mutable DictionaryPrivate *_p;
void _ref(const Dictionary &p_from) const;
void _copy_on_write() const;
void _ref(const Dictionary& p_from) const;
void _unref() const;
public:
void get_key_list(List<Variant> *p_keys) const;
Variant 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;
void get_key_list( List<Variant> *p_keys) const;
const Variant *getptr(const Variant &p_key) const;
Variant *getptr(const Variant &p_key);
Variant& operator[](const Variant& p_key);
const Variant& operator[](const Variant& p_key) const;
Variant get_valid(const Variant &p_key) const;
Variant get(const Variant &p_key, const Variant &p_default) const;
const Variant* getptr(const Variant& p_key) const;
Variant* getptr(const Variant& p_key);
Variant get_valid(const Variant& p_key) const;
int size() const;
bool empty() const;
void clear();
bool has(const Variant &p_key) const;
bool has_all(const Array &p_keys) const;
bool erase(const Variant &p_key);
Error parse_json(const String& p_json);
String to_json() const;
bool operator==(const Dictionary &p_dictionary) const;
bool operator!=(const Dictionary &p_dictionary) const;
bool is_shared() const;
bool has(const Variant& p_key) const;
bool has_all(const Array& p_keys) const;
void erase(const Variant& p_key);
bool operator==(const Dictionary& p_dictionary) const;
uint32_t hash() const;
void operator=(const Dictionary &p_dictionary);
void operator=(const Dictionary& p_dictionary);
const Variant *next(const Variant *p_key = nullptr) const;
const Variant* next(const Variant* p_key=NULL) const;
Array keys() const;
Array values() const;
Dictionary duplicate(bool p_deep = false) const;
const void *id() const;
Dictionary(const Dictionary &p_from);
Dictionary();
Dictionary(const Dictionary& p_from);
Dictionary(bool p_shared=false);
~Dictionary();
};

32
core/dvector.cpp Normal file
View File

@@ -0,0 +1,32 @@
/*************************************************************************/
/* dvector.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "dvector.h"
Mutex* dvector_lock=NULL;

442
core/dvector.h Normal file
View File

@@ -0,0 +1,442 @@
/*************************************************************************/
/* dvector.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef DVECTOR_H
#define DVECTOR_H
#include "os/memory.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
extern Mutex* dvector_lock;
template<class T>
class DVector {
mutable MID mem;
void copy_on_write() {
if (!mem.is_valid())
return;
if (dvector_lock)
dvector_lock->lock();
MID_Lock lock( mem );
if ( *(int*)lock.data() == 1 ) {
// one reference, means no refcount changes
if (dvector_lock)
dvector_lock->unlock();
return;
}
MID new_mem= dynalloc( mem.get_size() );
if (!new_mem.is_valid()) {
if (dvector_lock)
dvector_lock->unlock();
ERR_FAIL_COND( new_mem.is_valid() ); // out of memory
}
MID_Lock dst_lock( new_mem );
int *rc = (int*)dst_lock.data();
*rc=1;
T * dst = (T*)(rc + 1 );
T * src =(T*) ((int*)lock.data() + 1 );
int count = (mem.get_size() - sizeof(int)) / sizeof(T);
for (int i=0;i<count;i++) {
memnew_placement( &dst[i], T(src[i]) );
}
(*(int*)lock.data())--;
// unlock all
dst_lock=MID_Lock();
lock=MID_Lock();
mem=new_mem;
if (dvector_lock)
dvector_lock->unlock();
}
void reference( const DVector& p_dvector ) {
unreference();
if (dvector_lock)
dvector_lock->lock();
if (!p_dvector.mem.is_valid()) {
if (dvector_lock)
dvector_lock->unlock();
return;
}
MID_Lock lock(p_dvector.mem);
int * rc = (int*)lock.data();
(*rc)++;
lock = MID_Lock();
mem=p_dvector.mem;
if (dvector_lock)
dvector_lock->unlock();
}
void unreference() {
if (dvector_lock)
dvector_lock->lock();
if (!mem.is_valid()) {
if (dvector_lock)
dvector_lock->unlock();
return;
}
MID_Lock lock(mem);
int * rc = (int*)lock.data();
(*rc)--;
if (*rc==0) {
// no one else using it, destruct
T * t= (T*)(rc+1);
int count = (mem.get_size() - sizeof(int)) / sizeof(T);
for (int i=0;i<count;i++) {
t[i].~T();
}
}
lock = MID_Lock();
mem = MID ();
if (dvector_lock)
dvector_lock->unlock();
}
public:
class Read {
friend class DVector;
MID_Lock lock;
const T * mem;
public:
_FORCE_INLINE_ const T& operator[](int p_index) const { return mem[p_index]; }
_FORCE_INLINE_ const T *ptr() const { return mem; }
Read() { mem=NULL; }
};
class Write {
friend class DVector;
MID_Lock lock;
T * mem;
public:
_FORCE_INLINE_ T& operator[](int p_index) { return mem[p_index]; }
_FORCE_INLINE_ T *ptr() { return mem; }
Write() { mem=NULL; }
};
Read read() const {
Read r;
if (mem.is_valid()) {
r.lock = MID_Lock( mem );
r.mem = (const T*)((int*)r.lock.data()+1);
}
return r;
}
Write write() {
Write w;
if (mem.is_valid()) {
copy_on_write();
w.lock = MID_Lock( mem );
w.mem = (T*)((int*)w.lock.data()+1);
}
return w;
}
template<class MC>
void fill_with(const MC& p_mc) {
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 DVector<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];
}
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;
}
bool is_locked() const { return mem.is_locked(); }
inline const T operator[](int p_index) const;
Error resize(int p_size);
void invert();
void operator=(const DVector& p_dvector) { reference(p_dvector); }
DVector() {}
DVector(const DVector& p_dvector) { reference(p_dvector); }
~DVector() { unreference(); }
};
template<class T>
int DVector<T>::size() const {
return mem.is_valid() ? ((mem.get_size() - sizeof(int)) / sizeof(T) ) : 0;
}
template<class T>
T DVector<T>::get(int p_index) const {
return operator[](p_index);
}
template<class T>
void DVector<T>::set(int p_index, const T& p_val) {
if (p_index<0 || p_index>=size()) {
ERR_FAIL_COND(p_index<0 || p_index>=size());
}
Write w = write();
w[p_index]=p_val;
}
template<class T>
void DVector<T>::push_back(const T& p_val) {
resize( size() + 1 );
set( size() -1, p_val );
}
template<class T>
const T DVector<T>::operator[](int p_index) const {
if (p_index<0 || p_index>=size()) {
T& aux=*((T*)0); //nullreturn
ERR_FAIL_COND_V(p_index<0 || p_index>=size(),aux);
}
Read r = read();
return r[p_index];
}
template<class T>
Error DVector<T>::resize(int p_size) {
if (dvector_lock)
dvector_lock->lock();
bool same = p_size==size();
if (dvector_lock)
dvector_lock->unlock();
// no further locking is necesary because we are supposed to own the only copy of this (using copy on write)
if (same)
return OK;
if (p_size == 0 ) {
unreference();
return OK;
}
copy_on_write(); // make it unique
ERR_FAIL_COND_V( mem.is_locked(), ERR_LOCKED ); // if after copy on write, memory is locked, fail.
if (p_size > size() ) {
int oldsize=size();
MID_Lock lock;
if (oldsize==0) {
mem = dynalloc( p_size * sizeof(T) + sizeof(int) );
lock=MID_Lock(mem);
int *rc = ((int*)lock.data());
*rc=1;
} else {
if (dynrealloc( mem, p_size * sizeof(T) + sizeof(int) )!=OK ) {
ERR_FAIL_V(ERR_OUT_OF_MEMORY); // out of memory
}
lock=MID_Lock(mem);
}
T *t = (T*)((int*)lock.data() + 1);
for (int i=oldsize;i<p_size;i++) {
memnew_placement(&t[i], T );
}
lock = MID_Lock(); // clear
} else {
int oldsize=size();
MID_Lock lock(mem);
T *t = (T*)((int*)lock.data() + 1);
for (int i=p_size;i<oldsize;i++) {
t[i].~T();
}
lock = MID_Lock(); // clear
if (dynrealloc( mem, p_size * sizeof(T) + sizeof(int) )!=OK ) {
ERR_FAIL_V(ERR_OUT_OF_MEMORY); // wtf error
}
}
return OK;
}
template<class T>
void DVector<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

@@ -1,251 +0,0 @@
/*************************************************************************/
/* engine.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "engine.h"
#include "core/authors.gen.h"
#include "core/donors.gen.h"
#include "core/license.gen.h"
#include "core/version.h"
#include "core/version_hash.gen.h"
void Engine::set_iterations_per_second(int p_ips) {
ERR_FAIL_COND_MSG(p_ips <= 0, "Engine iterations per second must be greater than 0.");
ips = p_ips;
}
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;
}
int Engine::get_target_fps() const {
return _target_fps;
}
uint64_t Engine::get_frames_drawn() {
return frames_drawn;
}
void Engine::set_frame_delay(uint32_t p_msec) {
_frame_delay = p_msec;
}
uint32_t Engine::get_frame_delay() const {
return _frame_delay;
}
void Engine::set_time_scale(float p_scale) {
_time_scale = p_scale;
}
float Engine::get_time_scale() const {
return _time_scale;
}
void Engine::set_portals_active(bool p_active) {
_portals_active = p_active;
}
Dictionary Engine::get_version_info() const {
Dictionary dict;
dict["major"] = VERSION_MAJOR;
dict["minor"] = VERSION_MINOR;
dict["patch"] = VERSION_PATCH;
dict["hex"] = VERSION_HEX;
dict["status"] = VERSION_STATUS;
dict["build"] = VERSION_BUILD;
dict["year"] = VERSION_YEAR;
String hash = VERSION_HASH;
dict["hash"] = hash.length() == 0 ? String("unknown") : hash;
String stringver = String(dict["major"]) + "." + String(dict["minor"]);
if ((int)dict["patch"] != 0) {
stringver += "." + String(dict["patch"]);
}
stringver += "-" + String(dict["status"]) + " (" + String(dict["build"]) + ")";
dict["string"] = stringver;
return dict;
}
static Array array_from_info(const char *const *info_list) {
Array arr;
for (int i = 0; info_list[i] != nullptr; i++) {
arr.push_back(String::utf8(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(String::utf8(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"] = String::utf8(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"] = String::utf8(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_PLATINUM);
donors["gold_sponsors"] = array_from_info(DONORS_SPONSOR_GOLD);
donors["silver_sponsors"] = array_from_info(DONORS_SPONSOR_SILVER);
donors["bronze_sponsors"] = array_from_info(DONORS_SPONSOR_BRONZE);
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::set_print_error_messages(bool p_enabled) {
_print_error_enabled = p_enabled;
}
bool Engine::is_printing_error_messages() const {
return _print_error_enabled;
}
void Engine::add_singleton(const Singleton &p_singleton) {
singletons.push_back(p_singleton);
singleton_ptrs[p_singleton.name] = p_singleton.ptr;
}
Object *Engine::get_singleton_object(const String &p_name) const {
const Map<StringName, Object *>::Element *E = singleton_ptrs.find(p_name);
ERR_FAIL_COND_V_MSG(!E, nullptr, "Failed to retrieve non-existent singleton '" + p_name + "'.");
return E->get();
};
bool Engine::has_singleton(const String &p_name) const {
return singleton_ptrs.has(p_name);
};
void Engine::get_singletons(List<Singleton> *p_singletons) {
for (List<Singleton>::Element *E = singletons.front(); E; E = E->next()) {
p_singletons->push_back(E->get());
}
}
Engine *Engine::singleton = nullptr;
Engine *Engine::get_singleton() {
return singleton;
}
Engine::Engine() {
singleton = this;
frames_drawn = 0;
ips = 60;
physics_jitter_fix = 0.5;
_physics_interpolation_fraction = 0.0f;
_frame_delay = 0;
_fps = 1;
_target_fps = 0;
_time_scale = 1.0;
_gpu_pixel_snap = false;
_physics_frames = 0;
_idle_frames = 0;
_in_physics = false;
_frame_ticks = 0;
_frame_step = 0;
editor_hint = false;
_portals_active = false;
}
Engine::Singleton::Singleton(const StringName &p_name, Object *p_ptr) :
name(p_name),
ptr(p_ptr) {
#ifdef DEBUG_ENABLED
Reference *ref = Object::cast_to<Reference>(p_ptr);
if (ref && !ref->is_referenced()) {
WARN_PRINT("You must use Ref<> to ensure the lifetime of a Reference object intended to be used as a singleton.");
}
#endif
}

View File

@@ -1,136 +0,0 @@
/*************************************************************************/
/* engine.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef ENGINE_H
#define ENGINE_H
#include "core/list.h"
#include "core/os/main_loop.h"
#include "core/ustring.h"
#include "core/vector.h"
class Engine {
public:
struct Singleton {
StringName name;
Object *ptr;
Singleton(const StringName &p_name = StringName(), Object *p_ptr = nullptr);
};
private:
friend class Main;
uint64_t frames_drawn;
uint32_t _frame_delay;
uint64_t _frame_ticks;
float _frame_step;
int ips;
float physics_jitter_fix;
float _fps;
int _target_fps;
float _time_scale;
bool _gpu_pixel_snap;
uint64_t _physics_frames;
float _physics_interpolation_fraction;
bool _portals_active;
bool _occlusion_culling_active;
uint64_t _idle_frames;
bool _in_physics;
List<Singleton> singletons;
Map<StringName, Object *> singleton_ptrs;
bool editor_hint;
static Engine *singleton;
public:
static Engine *get_singleton();
virtual void set_iterations_per_second(int p_ips);
virtual int get_iterations_per_second() const;
void set_physics_jitter_fix(float p_threshold);
float get_physics_jitter_fix() const;
virtual void set_target_fps(int p_fps);
virtual int get_target_fps() const;
virtual float get_frames_per_second() const { return _fps; }
uint64_t get_frames_drawn();
uint64_t get_physics_frames() const { return _physics_frames; }
uint64_t get_idle_frames() const { return _idle_frames; }
bool is_in_physics_frame() const { return _in_physics; }
uint64_t get_idle_frame_ticks() const { return _frame_ticks; }
float get_idle_frame_step() const { return _frame_step; }
float get_physics_interpolation_fraction() const { return _physics_interpolation_fraction; }
void set_time_scale(float p_scale);
float get_time_scale() const;
void set_frame_delay(uint32_t p_msec);
uint32_t get_frame_delay() const;
void set_print_error_messages(bool p_enabled);
bool is_printing_error_messages() const;
void add_singleton(const Singleton &p_singleton);
void get_singletons(List<Singleton> *p_singletons);
bool has_singleton(const String &p_name) const;
Object *get_singleton_object(const String &p_name) const;
_FORCE_INLINE_ bool get_use_gpu_pixel_snap() const { return _gpu_pixel_snap; }
bool are_portals_active() const { return _portals_active; }
void set_portals_active(bool p_active);
#ifdef TOOLS_ENABLED
_FORCE_INLINE_ void set_editor_hint(bool p_enabled) { editor_hint = p_enabled; }
_FORCE_INLINE_ bool is_editor_hint() const { return editor_hint; }
#else
_FORCE_INLINE_ void set_editor_hint(bool p_enabled) {}
_FORCE_INLINE_ bool is_editor_hint() const { return false; }
#endif
Dictionary get_version_info() const;
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

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,7 +26,6 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef ERROR_LIST_H
#define ERROR_LIST_H
@@ -39,17 +37,17 @@
*/
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
ERR_UNCONFIGURED, ///< The object being used hasnt been properly set up yet
ERR_UNAUTHORIZED, ///< Missing credentials for requested resource
ERR_PARAMETER_RANGE_ERROR, ///< Parameter given out of range (5)
ERR_OUT_OF_MEMORY, ///< Out of memory
ERR_FILE_NOT_FOUND,
ERR_FILE_BAD_DRIVE,
ERR_FILE_BAD_PATH,
ERR_FILE_NO_PERMISSION, // (10)
ERR_FILE_NO_PERMISSION, // (10)
ERR_FILE_ALREADY_IN_USE,
ERR_FILE_CANT_OPEN,
ERR_FILE_CANT_WRITE,
@@ -59,35 +57,40 @@ enum Error {
ERR_FILE_MISSING_DEPENDENCIES,
ERR_FILE_EOF,
ERR_CANT_OPEN, ///< Can't open a resource/socket/file
ERR_CANT_CREATE, // (20)
ERR_QUERY_FAILED,
ERR_CANT_CREATE, // (20)
ERROR_QUERY_FAILED,
ERR_ALREADY_IN_USE,
ERR_LOCKED, ///< resource is locked
ERR_TIMEOUT,
ERR_CANT_CONNECT, // (25)
ERR_LOCKED, ///< resource is locked
ERR_TIMEOUT,
ERR_CANT_CONNECT, // (25)
ERR_CANT_RESOLVE,
ERR_CONNECTION_ERROR,
ERR_CANT_ACQUIRE_RESOURCE,
ERR_CANT_AQUIRE_RESOURCE,
ERR_CANT_FORK,
ERR_INVALID_DATA, ///< Data passed is invalid (30)
ERR_INVALID_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,
ERR_METHOD_NOT_FOUND,
ERR_LINK_FAILED,
ERR_SCRIPT_FAILED,
ERR_CYCLIC_LINK, // (40)
ERR_CYCLIC_LINK, // (40)
ERR_INVALID_DECLARATION,
ERR_DUPLICATE_SYMBOL,
ERR_PARSE_ERROR,
ERR_BUSY,
ERR_SKIP, // (45)
ERR_SKIP, // (45)
ERR_HELP, ///< user requested help!!
ERR_BUG, ///< a bug in the software certainly happened, due to a double check failing or unexpected behavior.
ERR_PRINTER_ON_FIRE, /// the parallel port printer is engulfed in flames
ERR_OMFG_THIS_IS_VERY_VERY_BAD, ///< shit happens, has never been used, though
ERR_WTF = ERR_OMFG_THIS_IS_VERY_VERY_BAD ///< short version of the above
};
#endif

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,87 +26,77 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "error_macros.h"
#include "core/io/logger.h"
#include "core/ustring.h"
#include "os/os.h"
static ErrorHandlerList *error_handler_list = nullptr;
bool _err_error_exists=false;
static ErrorHandlerList *error_handler_list=NULL;
void _err_set_last_error(const char* p_err) {
OS::get_singleton()->set_last_error(p_err);
}
void _err_clear_last_error() {
OS::get_singleton()->clear_last_error();
}
void add_error_handler(ErrorHandlerList *p_handler) {
_global_lock();
p_handler->next = error_handler_list;
error_handler_list = p_handler;
p_handler->next=error_handler_list;
error_handler_list=p_handler;
_global_unlock();
}
void remove_error_handler(ErrorHandlerList *p_handler) {
_global_lock();
ErrorHandlerList *prev = nullptr;
ErrorHandlerList *prev = NULL;
ErrorHandlerList *l = error_handler_list;
while (l) {
if (l == p_handler) {
if (prev) {
prev->next = l->next;
} else {
error_handler_list = l->next;
}
while(l) {
if (l==p_handler) {
if (prev)
prev->next=l->next;
else
error_handler_list=l->next;
break;
}
prev = l;
l = l->next;
prev=l;
l=l->next;
}
_global_unlock();
}
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type) {
_err_print_error(p_function, p_file, p_line, p_error, "", p_type);
}
void _err_print_error(const char* p_function, const char* p_file,int p_line,const char *p_error,ErrorHandlerType p_type) {
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, ErrorHandlerType p_type) {
_err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), "", p_type);
}
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, ErrorHandlerType p_type) {
OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, p_message, (Logger::ErrorType)p_type);
OS::get_singleton()->print_error(p_function,p_file,p_line,p_error,_err_error_exists?OS::get_singleton()->get_last_error():"",(OS::ErrorType)p_type);
_global_lock();
ErrorHandlerList *l = error_handler_list;
while (l) {
l->errfunc(l->userdata, p_function, p_file, p_line, p_error, p_message, p_type);
l = l->next;
while(l) {
l->errfunc(l->userdata,p_function,p_file,p_line,p_error,_err_error_exists?OS::get_singleton()->get_last_error():"",p_type);
l=l->next;
}
_global_unlock();
}
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, ErrorHandlerType p_type) {
_err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message, p_type);
}
if (_err_error_exists) {
OS::get_singleton()->clear_last_error();
_err_error_exists=false;
}
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, ErrorHandlerType p_type) {
_err_print_error(p_function, p_file, p_line, p_error, p_message.utf8().get_data(), p_type);
}
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, ErrorHandlerType p_type) {
_err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message.utf8().get_data(), p_type);
}
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message, bool fatal) {
String fstr(fatal ? "FATAL: " : "");
String err(fstr + "Index " + p_index_str + " = " + itos(p_index) + " is out of bounds (" + p_size_str + " = " + itos(p_size) + ").");
_err_print_error(p_function, p_file, p_line, err.utf8().get_data(), p_message);
}
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool fatal) {
_err_print_index_error(p_function, p_file, p_line, p_index, p_size, p_index_str, p_size_str, p_message.utf8().get_data(), fatal);
}
void _err_flush_stdout() {
fflush(stdout);
}

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,23 +26,20 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef ERROR_MACROS_H
#define ERROR_MACROS_H
#include "core/safe_refcount.h"
#include "core/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 engine can keep working well.
* Error macros. Unlike exceptions and asserts, these macros try to mantain consistency and stability
* inside the code. It is recommended to always return processable data, so in case of an error, the
* engine can stay working well.
* In most cases, bugs and/or invalid data are not fatal and should never allow a perfectly running application
* to fail or crash.
*/
/**
* Pointer to the error macro printing function. Reassign to any function to have errors printed
* Pointer to the error macro priting function. Reassign to any function to have errors printed
*/
/** Function used by the error macros */
@@ -53,47 +49,51 @@
enum ErrorHandlerType {
ERR_HANDLER_ERROR,
ERR_HANDLER_WARNING,
ERR_HANDLER_SCRIPT,
ERR_HANDLER_SHADER,
ERR_HANDLER_SCRIPT
};
class String;
typedef void (*ErrorHandlerFunc)(void *, const char *, const char *, int p_line, const char *, const char *, ErrorHandlerType p_type);
typedef void (*ErrorHandlerFunc)(void*,const char*,const char*,int p_line,const char *, const char *,ErrorHandlerType p_type);
void _err_set_last_error(const char* p_err);
void _err_clear_last_error();
struct ErrorHandlerList {
ErrorHandlerFunc errfunc;
void *userdata;
ErrorHandlerList *next;
ErrorHandlerList*next;
ErrorHandlerList() {
errfunc = nullptr;
next = nullptr;
userdata = nullptr;
}
ErrorHandlerList() { errfunc=0; next=0; userdata=0; }
};
void add_error_handler(ErrorHandlerList *p_handler);
void remove_error_handler(ErrorHandlerList *p_handler);
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool fatal = false);
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool fatal = false);
void _err_flush_stdout();
void _err_print_error(const char* p_function,const char* p_file,int p_line,const char *p_error,ErrorHandlerType p_type=ERR_HANDLER_ERROR);
#ifndef _STR
#define _STR(m_x) #m_x
#define _MKSTR(m_x) _STR(m_x)
#endif
#define _FNL __FILE__ ":"
#define _FNL __FILE__":"
/** An index has failed if m_index<0 or m_index >=m_size, the function exits */
/** An index has failed if m_index<0 or m_index >=m_size, the function exists */
extern bool _err_error_exists;
#ifdef DEBUG_ENABLED
/** Print a warning string.
*/
#define ERR_EXPLAINC(m_reason) {_err_set_last_error(m_reason); _err_error_exists=true;}
#define ERR_EXPLAIN(m_string) {_err_set_last_error(String(m_string).utf8().get_data()); _err_error_exists=true;}
#else
#define ERR_EXPLAIN( m_text )
#define ERR_EXPLAINC( m_text )
#endif
#ifdef __GNUC__
//#define FUNCTION_STR __PRETTY_FUNCTION__ - too annoying
@@ -102,455 +102,131 @@ void _err_flush_stdout();
#define FUNCTION_STR __FUNCTION__
#endif
// Don't use this directly; instead, use any of the CRASH_* macros
#ifdef _MSC_VER
#define GENERATE_TRAP \
__debugbreak(); \
/* Avoid warning about control paths */ \
for (;;) { \
}
#else
#define GENERATE_TRAP __builtin_trap();
#endif
#define ERR_FAIL_INDEX(m_index,m_size) \
do {if ((m_index)<0 || (m_index)>=(m_size)) { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Index " _STR(m_index)" out of size (" _STR(m_size)")."); \
return; \
} else _err_error_exists=false; } while(0); \
// (*): See https://stackoverflow.com/questions/257418/do-while-0-what-is-it-good-for
/** An index has failed if m_index<0 or m_index >=m_size, the function exists.
* This function returns an error value, if returning Error, please select the most
* appropriate error condition from error_macros.h
*/
/**
* If `m_index` is less than 0 or greater than or equal to `m_size`, prints a generic
* error message and returns from the function. This macro should be preferred to
* `ERR_FAIL_COND` for bounds checking.
#define ERR_FAIL_INDEX_V(m_index,m_size,m_retval) \
do {if ((m_index)<0 || (m_index)>=(m_size)) { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Index " _STR(m_index)" out of size (" _STR(m_size)")."); \
return m_retval; \
} else _err_error_exists=false;} while (0);
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the function will exit.
*/
#define ERR_FAIL_NULL(m_param) \
{ if ( !m_param ) { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Parameter ' " _STR(m_param)" ' is null."); \
return; \
}else _err_error_exists=false; } \
#define ERR_FAIL_NULL_V(m_param,m_retval) \
{ if ( !m_param ) { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Parameter ' " _STR(m_param)" ' is null."); \
return m_retval; \
}else _err_error_exists=false; } \
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the function will exit.
*/
#define ERR_FAIL_INDEX(m_index, m_size) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
return; \
} else \
((void)0)
/**
* If `m_index` is less than 0 or greater than or equal to `m_size`, prints a custom
* error message and returns from the function. This macro should be preferred to
* `ERR_FAIL_COND_MSG` for bounds checking.
*/
#define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
return; \
} else \
((void)0)
#define ERR_FAIL_COND(m_cond) \
{ if ( m_cond ) { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true."); \
return; \
}else _err_error_exists=false; } \
/**
* If `m_index` is less than 0 or greater than or equal to `m_size`,
* prints a generic error message and returns the value specified in `m_retval`.
* This macro should be preferred to `ERR_FAIL_COND_V` for bounds checking.
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the function will exit.
* This function returns an error value, if returning Error, please select the most
* appropriate error condition from error_macros.h
*/
#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
return m_retval; \
} else \
((void)0)
/**
* If `m_index` is less than 0 or greater than or equal to `m_size`,
* prints a custom error message and returns the value specified in `m_retval`.
* This macro should be preferred to `ERR_FAIL_COND_V_MSG` for bounds checking.
*/
#define ERR_FAIL_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
return m_retval; \
} else \
((void)0)
#define ERR_FAIL_COND_V(m_cond,m_retval) \
{ if ( m_cond ) { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true. returned: " _STR(m_retval)); \
return m_retval; \
}else _err_error_exists=false; } \
/**
* If `m_index` is greater than or equal to `m_size`,
* prints a generic error message and returns the value specified in `m_retval`.
* This macro should be preferred to `ERR_FAIL_COND_V` for unsigned bounds checking.
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the loop will skip to the next iteration.
*/
#define ERR_FAIL_UNSIGNED_INDEX(m_index, m_size) \
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; \
} else \
((void)0)
/**
* If `m_index` is greater than or equal to `m_size`,
* prints a generic error message and returns the value specified in `m_retval`.
* This macro should be preferred to `ERR_FAIL_COND_V` for unsigned bounds checking.
*/
#define ERR_FAIL_UNSIGNED_INDEX_V(m_index, m_size, m_retval) \
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 \
((void)0)
#define ERR_CONTINUE(m_cond) \
{ if ( m_cond ) { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true. Continuing..:"); \
continue;\
} else _err_error_exists=false;} \
/**
* If `m_index` is greater than or equal to `m_size`,
* prints a custom error message and returns the value specified in `m_retval`.
* This macro should be preferred to `ERR_FAIL_COND_V_MSG` for unsigned bounds checking.
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the loop will break
*/
#define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
if (unlikely((m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
return m_retval; \
} else \
((void)0)
/**
* If `m_index` is less than 0 or greater than or equal to `m_size`,
* crashes the engine immediately with a generic error message.
* Only use this if there's no sensible fallback (i.e. the error is unrecoverable).
* This macro should be preferred to `CRASH_COND` for bounds checking.
*/
#define CRASH_BAD_INDEX(m_index, m_size) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", true); \
GENERATE_TRAP \
} else \
((void)0)
#define ERR_BREAK(m_cond) \
{ if ( m_cond ) { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true. Breaking..:"); \
break;\
} else _err_error_exists=false;} \
/**
* If `m_index` is less than 0 or greater than or equal to `m_size`,
* crashes the engine immediately with a custom error message.
* Only use this if there's no sensible fallback (i.e. the error is unrecoverable).
* This macro should be preferred to `CRASH_COND` for bounds checking.
/** Print an error string and return
*/
#define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
GENERATE_TRAP \
} else \
((void)0)
/**
* If `m_index` is greater than or equal to `m_size`,
* crashes the engine immediately with a generic error message.
* Only use this if there's no sensible fallback (i.e. the error is unrecoverable).
* This macro should be preferred to `CRASH_COND` for bounds checking.
*/
#define CRASH_BAD_UNSIGNED_INDEX(m_index, m_size) \
if (unlikely((m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", true); \
GENERATE_TRAP \
} else \
((void)0)
#define ERR_FAIL() \
{ \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Method/Function Failed."); \
_err_error_exists=false;\
return;\
} \
/**
* If `m_param` is `null`, prints a generic error message and returns from the function.
/** Print an error string and return with value
*/
#define ERR_FAIL_NULL(m_param) \
if (unlikely(!m_param)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \
return; \
} else \
((void)0)
/**
* If `m_param` is `null`, prints a custom error message and returns from the function.
*/
#define ERR_FAIL_NULL_MSG(m_param, m_msg) \
if (unlikely(!m_param)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg); \
return; \
} else \
((void)0)
#define ERR_FAIL_V(m_value) \
{ \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Method/Function Failed, returning: " __STR(m_value)); \
_err_error_exists=false; \
return m_value;\
} \
/**
* If `m_param` is `null`, prints a generic error message and returns the value specified in `m_retval`.
/** Print an error string.
*/
#define ERR_FAIL_NULL_V(m_param, m_retval) \
if (unlikely(!m_param)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \
return m_retval; \
} else \
((void)0)
/**
* If `m_param` is `null`, prints a custom error message and returns the value specified in `m_retval`.
*/
#define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg) \
if (unlikely(!m_param)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg); \
return m_retval; \
} else \
((void)0)
/**
* If `m_cond` evaluates to `true`, prints a generic error message and returns from the function.
*/
#define ERR_FAIL_COND(m_cond) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true."); \
return; \
} else \
((void)0)
/**
* If `m_cond` evaluates to `true`, prints a custom error message and returns from the function.
*/
#define ERR_FAIL_COND_MSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", m_msg); \
return; \
} else \
((void)0)
/**
* If `m_cond` evaluates to `true`, crashes the engine immediately with a generic error message.
* Only use this if there's no sensible fallback (i.e. the error is unrecoverable).
*/
#define CRASH_COND(m_cond) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true."); \
GENERATE_TRAP \
} else \
((void)0)
/**
* If `m_cond` evaluates to `true`, crashes the engine immediately with a custom error message.
* Only use this if there's no sensible fallback (i.e. the error is unrecoverable).
*/
#define CRASH_COND_MSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true.", m_msg); \
GENERATE_TRAP \
} else \
((void)0)
/**
* If `m_cond` evaluates to `true`, prints a generic error message and returns the value specified in `m_retval`.
*/
#define ERR_FAIL_COND_V(m_cond, m_retval) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returned: " _STR(m_retval)); \
return m_retval; \
} else \
((void)0)
/**
* If `m_cond` evaluates to `true`, prints a custom error message and returns the value specified in `m_retval`.
*/
#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returned: " _STR(m_retval), m_msg); \
return m_retval; \
} else \
((void)0)
/**
* If `m_cond` evaluates to `true`, prints a custom error message and continues the loop the macro is located in.
*/
#define ERR_CONTINUE(m_cond) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing."); \
continue; \
} else \
((void)0)
/**
* If `m_cond` evaluates to `true`, prints a custom error message and continues the loop the macro is located in.
*/
#define ERR_CONTINUE_MSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", m_msg); \
continue; \
} else \
((void)0)
/**
* If `m_cond` evaluates to `true`, prints a generic error message and breaks from the loop the macro is located in.
*/
#define ERR_BREAK(m_cond) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking."); \
break; \
} else \
((void)0)
/**
* If `m_cond` evaluates to `true`, prints a custom error message and breaks from the loop the macro is located in.
*/
#define ERR_BREAK_MSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", m_msg); \
break; \
} else \
((void)0)
/**
* Prints a generic error message and returns from the function.
*/
#define ERR_FAIL() \
if (true) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method failed."); \
return; \
} else \
((void)0)
/**
* Prints a custom error message and returns from the function.
*/
#define ERR_FAIL_MSG(m_msg) \
if (true) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method failed.", m_msg); \
return; \
} else \
((void)0)
/**
* Prints a generic error message and returns the value specified in `m_retval`.
*/
#define ERR_FAIL_V(m_retval) \
if (true) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method failed. Returning: " __STR(m_retval)); \
return m_retval; \
} else \
((void)0)
/**
* Prints a custom error message and returns the value specified in `m_retval`.
*/
#define ERR_FAIL_V_MSG(m_retval, m_msg) \
if (true) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method failed. Returning: " __STR(m_retval), m_msg); \
return m_retval; \
} else \
((void)0)
/**
* Crashes the engine immediately with a generic error message.
* Only use this if there's no sensible fallback (i.e. the error is unrecoverable).
*/
#define CRASH_NOW() \
if (true) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method failed."); \
void _err_flush_stdout(); \
GENERATE_TRAP \
} else \
((void)0)
/**
* Crashes the engine immediately with a custom error message.
* Only use this if there's no sensible fallback (i.e. the error is unrecoverable).
*/
#define CRASH_NOW_MSG(m_msg) \
if (true) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method failed.", m_msg); \
void _err_flush_stdout(); \
GENERATE_TRAP \
} else \
((void)0)
/**
* Prints an error message without returning.
*/
#define ERR_PRINT(m_string) \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string)
{ \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,m_string); \
_err_error_exists=false;\
} \
/**
* Prints an error message without returning, but only do so once in the application lifecycle.
* This can be used to avoid spamming the console with error messages.
*/
#define ERR_PRINT_ONCE(m_string) \
if (true) { \
static bool first_print = true; \
if (first_print) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string); \
first_print = false; \
} \
} else \
((void)0)
#define ERR_PRINTS(m_string) \
{ \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,String(m_string).utf8().get_data()); \
_err_error_exists=false;\
} \
/**
* Prints a warning message without returning. To warn about deprecated usage,
* use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
/** Print a warning string.
*/
#define WARN_PRINT(m_string) \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string, ERR_HANDLER_WARNING)
{ \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,m_string,ERR_HANDLER_WARNING); \
_err_error_exists=false;\
} \
/**
* Prints a warning message without returning, but only do so once in the application lifecycle.
* This can be used to avoid spamming the console with warning messages.
*/
#define WARN_PRINT_ONCE(m_string) \
if (true) { \
static bool first_print = true; \
if (first_print) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string, ERR_HANDLER_WARNING); \
first_print = false; \
} \
} else \
((void)0)
/**
* Prints a generic deprecation warning message without returning.
* This should be preferred to `WARN_PRINT` for deprecation warnings.
*/
#define WARN_DEPRECATED \
if (true) { \
static SafeFlag warning_shown; \
if (!warning_shown.is_set()) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", ERR_HANDLER_WARNING); \
warning_shown.set(); \
} \
} else \
((void)0)
/**
* Prints a custom deprecation warning message without returning.
* This should be preferred to `WARN_PRINT` for deprecation warnings.
*/
#define WARN_DEPRECATED_MSG(m_msg) \
if (true) { \
static SafeFlag warning_shown; \
if (!warning_shown.is_set()) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", m_msg, ERR_HANDLER_WARNING); \
warning_shown.set(); \
} \
} else \
((void)0)
#define WARN_PRINTS(m_string) \
{ \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,String(m_string).utf8().get_data(),ERR_HANDLER_WARNING); \
_err_error_exists=false;\
} \
#endif
/**
* This should be a 'free' assert for program flow and should not be needed in any releases,
* only used in dev builds.
*/
#ifdef DEV_ENABLED
#define DEV_ASSERT(m_cond) \
if (unlikely(!(m_cond))) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: DEV_ASSERT failed \"" _STR(m_cond) "\" is false."); \
void _err_flush_stdout(); \
GENERATE_TRAP \
} else \
((void)0)
#else
#define DEV_ASSERT(m_cond)
#endif
/**
* These should be 'free' checks for program flow and should not be needed in any releases,
* only used in dev builds.
*/
#ifdef DEV_ENABLED
#define DEV_CHECK(m_cond) \
if (unlikely(!(m_cond))) { \
ERR_PRINT("DEV_CHECK failed \"" _STR(m_cond) "\" is false."); \
} else \
((void)0)
#else
#define DEV_CHECK(m_cond)
#endif
#ifdef DEV_ENABLED
#define DEV_CHECK_ONCE(m_cond) \
if (unlikely(!(m_cond))) { \
ERR_PRINT_ONCE("DEV_CHECK_ONCE failed \"" _STR(m_cond) "\" is false."); \
} else \
((void)0)
#else
#define DEV_CHECK_ONCE(m_cond)
#endif

161
core/event_queue.cpp Normal file
View File

@@ -0,0 +1,161 @@
/*************************************************************************/
/* event_queue.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "event_queue.h"
Error EventQueue::push_call(uint32_t p_instance_ID, const StringName& p_method, VARIANT_ARG_DECLARE) {
uint8_t room_needed=sizeof(Event);
int args=0;
if (p_arg5.get_type()!=Variant::NIL)
args=5;
else if (p_arg4.get_type()!=Variant::NIL)
args=4;
else if (p_arg3.get_type()!=Variant::NIL)
args=3;
else if (p_arg2.get_type()!=Variant::NIL)
args=2;
else if (p_arg1.get_type()!=Variant::NIL)
args=1;
else
args=0;
room_needed+=sizeof(Variant)*args;
ERR_FAIL_COND_V( (buffer_end+room_needed) >= buffer_size , ERR_OUT_OF_MEMORY );
Event * ev = memnew_placement( &event_buffer[ buffer_end ], Event );
ev->args=args;
ev->instance_ID=p_instance_ID;
ev->method=p_method;
buffer_end+=sizeof(Event);
if (args>=1) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg1;
}
if (args>=2) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg2;
}
if (args>=3) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg3;
}
if (args>=4) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg4;
}
if (args>=5) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg5;
}
if (buffer_end > buffer_max_used)
buffer_max_used=buffer_end;
return OK;
}
void EventQueue::flush_events() {
uint32_t read_pos=0;
while (read_pos < buffer_end ) {
Event *event = (Event*)&event_buffer[ read_pos ];
Variant *args= (Variant*)(event+1);
Object *obj = ObjectDB::get_instance(event->instance_ID);
if (obj) {
// events don't expect a return value
obj->call( event->method,
(event->args>=1) ? args[0] : Variant(),
(event->args>=2) ? args[1] : Variant(),
(event->args>=3) ? args[2] : Variant(),
(event->args>=4) ? args[3] : Variant(),
(event->args>=5) ? args[4] : Variant() );
}
if (event->args>=1) args[0].~Variant();
if (event->args>=2) args[1].~Variant();
if (event->args>=3) args[2].~Variant();
if (event->args>=4) args[3].~Variant();
if (event->args>=5) args[4].~Variant();
event->~Event();
read_pos+=sizeof(Event)+sizeof(Variant)*event->args;
}
buffer_end=0; // reset buffer
}
EventQueue::EventQueue(uint32_t p_buffer_size) {
buffer_end=0;
buffer_max_used=0;
buffer_size=p_buffer_size;
event_buffer = memnew_arr( uint8_t, buffer_size );
}
EventQueue::~EventQueue() {
uint32_t read_pos=0;
while (read_pos < buffer_end ) {
Event *event = (Event*)&event_buffer[ read_pos ];
Variant *args= (Variant*)(event+1);
for (int i=0;i<event->args;i++)
args[i].~Variant();
event->~Event();
read_pos+=sizeof(Event)+sizeof(Variant)*event->args;
}
memdelete_arr(event_buffer);
event_buffer=NULL;
}

66
core/event_queue.h Normal file
View File

@@ -0,0 +1,66 @@
/*************************************************************************/
/* event_queue.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef EVENT_QUEUE_H
#define EVENT_QUEUE_H
#include "object.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
class EventQueue {
enum {
DEFAULT_EVENT_QUEUE_SIZE_KB=256
};
struct Event {
uint32_t instance_ID;
StringName method;
int args;
};
uint8_t *event_buffer;
uint32_t buffer_end;
uint32_t buffer_max_used;
uint32_t buffer_size;
public:
Error push_call(uint32_t p_instance_ID, const StringName& p_method, VARIANT_ARG_LIST);
void flush_events();
EventQueue(uint32_t p_buffer_size=DEFAULT_EVENT_QUEUE_SIZE_KB*1024);
~EventQueue();
};
#endif

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,79 +26,57 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "func_ref.h"
Variant FuncRef::call_func(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
if (id == 0) {
r_error.error = Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL;
Variant FuncRef::call_func(const Variant** p_args, int p_argcount, Variant::CallError& r_error) {
if (id==0) {
r_error.error=Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL;
return Variant();
}
Object *obj = ObjectDB::get_instance(id);
Object* obj = ObjectDB::get_instance(id);
if (!obj) {
r_error.error = Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL;
r_error.error=Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL;
return Variant();
}
return obj->call(function, p_args, p_argcount, r_error);
return obj->call(function,p_args,p_argcount,r_error);
}
Variant FuncRef::call_funcv(const Array &p_args) {
ERR_FAIL_COND_V(id == 0, Variant());
void FuncRef::set_instance(Object *p_obj){
Object *obj = ObjectDB::get_instance(id);
ERR_FAIL_COND_V(!obj, Variant());
return obj->callv(function, p_args);
}
void FuncRef::set_instance(Object *p_obj) {
ERR_FAIL_NULL(p_obj);
id = p_obj->get_instance_id();
id=p_obj->get_instance_ID();
}
void FuncRef::set_function(const StringName& p_func){
void FuncRef::set_function(const StringName &p_func) {
function = p_func;
}
StringName FuncRef::get_function() {
return function;
}
bool FuncRef::is_valid() const {
if (id == 0) {
return false;
}
Object *obj = ObjectDB::get_instance(id);
if (!obj) {
return false;
}
return obj->has_method(function);
function=p_func;
}
void FuncRef::_bind_methods() {
{
MethodInfo mi;
mi.name = "call_func";
mi.name="call_func";
Vector<Variant> defargs;
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_func", &FuncRef::call_func, mi, defargs);
for(int i=0;i<10;i++) {
mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
defargs.push_back(Variant());
}
ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_func",&FuncRef::call_func,mi,defargs);
}
ClassDB::bind_method(D_METHOD("call_funcv", "arg_array"), &FuncRef::call_funcv);
ObjectTypeDB::bind_method(_MD("set_instance","instance"),&FuncRef::set_instance);
ObjectTypeDB::bind_method(_MD("set_function","name"),&FuncRef::set_function);
ClassDB::bind_method(D_METHOD("set_instance", "instance"), &FuncRef::set_instance);
ClassDB::bind_method(D_METHOD("is_valid"), &FuncRef::is_valid);
ClassDB::bind_method(D_METHOD("set_function", "name"), &FuncRef::set_function);
ClassDB::bind_method(D_METHOD("get_function"), &FuncRef::get_function);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "function"), "set_function", "get_function");
}
FuncRef::FuncRef() :
id(0) {
FuncRef::FuncRef(){
id=0;
}

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,27 +26,25 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef FUNC_REF_H
#define FUNC_REF_H
#include "core/reference.h"
#include "reference.h"
class FuncRef : public Reference {
GDCLASS(FuncRef, Reference);
class FuncRef : public Reference{
OBJ_TYPE(FuncRef,Reference);
ObjectID id;
StringName function;
protected:
static void _bind_methods();
static void _bind_methods();
public:
Variant call_func(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
Variant call_funcv(const Array &p_args);
Variant call_func(const Variant** p_args, int p_argcount, Variant::CallError& r_error);
void set_instance(Object *p_obj);
void set_function(const StringName &p_func);
StringName get_function();
bool is_valid() const;
void set_function(const StringName& p_func);
FuncRef();
};

File diff suppressed because it is too large Load Diff

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,17 +26,14 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef GLOBAL_CONSTANTS_H
#define GLOBAL_CONSTANTS_H
#include "core/string_name.h"
class GlobalConstants {
public:
static int get_global_constant_count();
static StringName get_global_constant_enum(int p_idx);
static bool get_ignore_value_in_docs(int p_idx);
static const char *get_global_constant_name(int p_idx);
static int get_global_constant_value(int p_idx);
};

1562
core/globals.cpp Normal file

File diff suppressed because it is too large Load Diff

154
core/globals.h Normal file
View File

@@ -0,0 +1,154 @@
/*************************************************************************/
/* globals.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef GLOBALS_H
#define GLOBALS_H
#include "object.h"
#include "set.h"
#include "os/thread_safe.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
class Globals : public Object {
OBJ_TYPE( Globals, Object );
_THREAD_SAFE_CLASS_
public:
typedef Map<String,Variant> CustomMap;
struct Singleton {
StringName name;
Object *ptr;
Singleton(const StringName& p_name=StringName(), Object *p_ptr=NULL) { name=p_name; ptr=p_ptr; }
};
protected:
enum {
NO_ORDER_BASE=1<<18
};
struct VariantContainer {
int order;
bool persist;
Variant variant;
bool hide_from_editor;
bool overrided;
VariantContainer(){ order=0; hide_from_editor=false; persist=false; overrided=false; }
VariantContainer(const Variant& p_variant, int p_order, bool p_persist=false) { variant=p_variant; order=p_order; hide_from_editor=false; persist=p_persist; overrided=false; }
};
bool registering_order;
int last_order;
Map<StringName,VariantContainer> props;
String resource_path;
Map<StringName,PropertyInfo> custom_prop_info;
bool disable_platform_override;
bool using_datapack;
List<String> input_presets;
bool _set(const StringName& p_name, const Variant& p_value);
bool _get(const StringName& p_name,Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
static Globals *singleton;
Error _load_settings(const String p_path);
Error _load_settings_binary(const String p_path);
Error _save_settings_text(const String& p_file,const Map<String,List<String> > &props,const CustomMap& p_custom=CustomMap());
Error _save_settings_binary(const String& p_file,const Map<String,List<String> > &props,const CustomMap& p_custom=CustomMap());
List<Singleton> singletons;
Error _save_custom_bnd(const String& p_file);
bool _load_resource_pack(const String& p_pack);
void _add_property_info_bind(const Dictionary& p_info);
protected:
static void _bind_methods();
public:
bool has(String p_var) const;
String localize_path(const String& p_path) const;
String globalize_path(const String& p_path) const;
void set_persisting(const String& p_name, bool p_persist);
bool is_persisting(const String& p_name) const;
String get_resource_path() const;
static Globals *get_singleton();
void clear(const String& p_name);
int get_order(const String& p_name) const;
void set_order(const String& p_name, int p_order);
Error setup(const String& p_path, const String &p_main_pack);
Error save_custom(const String& p_path="",const CustomMap& p_custom=CustomMap(),const Set<String>& p_ignore_masks=Set<String>());
Error save();
void set_custom_property_info(const String& p_prop,const PropertyInfo& p_info);
void add_singleton(const Singleton &p_singleton);
void get_singletons(List<Singleton> *p_singletons);
bool has_singleton(const String& p_name) const;
Vector<String> get_optimizer_presets() const;
List<String> get_input_presets() const { return input_presets; }
void set_disable_platform_override(bool p_disable);
Object* get_singleton_object(const String& p_name) const;
void register_global_defaults();
bool is_using_datapack() const;
void set_registering_order(bool p_registering);
Globals();
~Globals();
};
//not a macro any longer
Variant _GLOBAL_DEF( const String& p_var, const Variant& p_default);
#define GLOBAL_DEF(m_var,m_value) _GLOBAL_DEF(m_var,m_value)
#endif

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,16 +26,43 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef HASH_MAP_H
#define HASH_MAP_H
#include "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 "hashfuncs.h"
#include "error_macros.h"
#include "ustring.h"
#include "os/memory.h"
#include "list.h"
class HashMapHahserDefault {
public:
static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }
static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); }
static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) {
uint64_t v=p_int;
v = (~v) + (v << 18); // v = (v << 18) - v - 1;
v = v ^ (v >> 31);
v = v * 21; // v = (v + (v << 2)) + (v << 4);
v = v ^ (v >> 11);
v = v + (v << 6);
v = v ^ (v >> 22);
return (int) v;
}
static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); }
static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return p_int; }
static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return (uint32_t)p_int; }
static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return p_int; }
static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return (uint32_t)p_int; }
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; }
static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; }
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; }
// static _FORCE_INLINE_ uint32_t hash(const void* p_ptr) { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); }
};
/**
* @class HashMap
@@ -48,228 +74,242 @@
* @param TKey Key, search is based on it, needs to be hasheable. It is unique in this container.
* @param TData Data, data associated with the key
* @param Hasher Hasher object, needs to provide a valid static hash function for TKey
* @param Comparator comparator object, needs to be able to safely compare two TKey values. It needs to ensure that x == x for any items inserted in the map. Bear in mind that nan != nan when implementing an equality check.
* @param MIN_HASH_TABLE_POWER Miminum size of the hash table, as a power of two. You rarely need to change this parameter.
* @param RELATIONSHIP Relationship at which the hash table is resized. if amount of elements is RELATIONSHIP
* times bigger than the hash table, table is resized to solve this condition. if RELATIONSHIP is zero, table is always MIN_HASH_TABLE_POWER.
*
*/
*/
template <class TKey, class TData, class Hasher = HashMapHasherDefault, class Comparator = HashMapComparatorDefault<TKey>, uint8_t MIN_HASH_TABLE_POWER = 3, uint8_t RELATIONSHIP = 8>
template<class TKey, class TData, class Hasher=HashMapHahserDefault,uint8_t MIN_HASH_TABLE_POWER=3,uint8_t RELATIONSHIP=8>
class HashMap {
public:
struct Pair {
TKey key;
TData data;
Pair() {}
Pair(const TKey &p_key, const TData &p_data) :
key(p_key),
data(p_data) {
}
Pair(const TKey& p_key, const TData& p_data) { key=p_key; data=p_data; }
};
struct Element {
private:
friend class HashMap;
uint32_t hash;
Element *next;
Element() { next = nullptr; }
Pair pair;
public:
const TKey &key() const {
return pair.key;
}
TData &value() {
return pair.data;
}
const TData &value() const {
return pair.value();
}
};
private:
Element **hash_table;
struct Entry {
uint32_t hash;
Entry *next;
Pair pair;
Entry() { next=0; }
};
Entry **hash_table;
uint8_t hash_table_power;
uint32_t elements;
void make_hash_table() {
ERR_FAIL_COND(hash_table);
hash_table = memnew_arr(Element *, (1 << MIN_HASH_TABLE_POWER));
ERR_FAIL_COND( hash_table );
hash_table = memnew_arr( Entry*, (1<<MIN_HASH_TABLE_POWER) );
hash_table_power = MIN_HASH_TABLE_POWER;
elements = 0;
for (int i = 0; i < (1 << MIN_HASH_TABLE_POWER); i++) {
hash_table[i] = nullptr;
}
elements=0;
for (int i=0;i<(1<<MIN_HASH_TABLE_POWER);i++)
hash_table[i]=0;
}
void erase_hash_table() {
ERR_FAIL_COND_MSG(elements, "Cannot erase hash table if there are still elements inside.");
memdelete_arr(hash_table);
hash_table = nullptr;
hash_table_power = 0;
elements = 0;
ERR_FAIL_COND(elements);
memdelete_arr( hash_table );
hash_table=0;
hash_table_power=0;
elements=0;
}
void check_hash_table() {
int new_hash_table_power = -1;
if ((int)elements > ((1 << hash_table_power) * RELATIONSHIP)) {
int new_hash_table_power=-1;
if ((int)elements > ( (1<<hash_table_power) * RELATIONSHIP ) ) {
/* rehash up */
new_hash_table_power = hash_table_power + 1;
new_hash_table_power=hash_table_power+1;
while( (int)elements > ( (1<<new_hash_table_power) * RELATIONSHIP ) ) {
while ((int)elements > ((1 << new_hash_table_power) * RELATIONSHIP)) {
new_hash_table_power++;
}
} else if ((hash_table_power > (int)MIN_HASH_TABLE_POWER) && ((int)elements < ((1 << (hash_table_power - 1)) * RELATIONSHIP))) {
/* rehash down */
new_hash_table_power = hash_table_power - 1;
} else if ( (hash_table_power>(int)MIN_HASH_TABLE_POWER) && ((int)elements < ( (1<<(hash_table_power-1)) * RELATIONSHIP ) ) ) {
/* rehash down */
new_hash_table_power=hash_table_power-1;
while( (int)elements < ( (1<<(new_hash_table_power-1)) * RELATIONSHIP ) ) {
while ((int)elements < ((1 << (new_hash_table_power - 1)) * RELATIONSHIP)) {
new_hash_table_power--;
}
if (new_hash_table_power < (int)MIN_HASH_TABLE_POWER) {
new_hash_table_power = MIN_HASH_TABLE_POWER;
}
if (new_hash_table_power<(int)MIN_HASH_TABLE_POWER)
new_hash_table_power=MIN_HASH_TABLE_POWER;
}
if (new_hash_table_power == -1) {
if (new_hash_table_power==-1)
return;
Entry ** new_hash_table = memnew_arr( Entry*, (1<<new_hash_table_power) );
if (!new_hash_table) {
ERR_PRINT("Out of Memory");
return;
}
Element **new_hash_table = memnew_arr(Element *, ((uint64_t)1 << new_hash_table_power));
ERR_FAIL_COND_MSG(!new_hash_table, "Out of memory.");
for (int i=0;i<(1<<new_hash_table_power);i++) {
for (int i = 0; i < (1 << new_hash_table_power); i++) {
new_hash_table[i] = nullptr;
new_hash_table[i]=0;
}
if (hash_table) {
for (int i = 0; i < (1 << hash_table_power); i++) {
while (hash_table[i]) {
Element *se = hash_table[i];
hash_table[i] = se->next;
int new_pos = se->hash & ((1 << new_hash_table_power) - 1);
se->next = new_hash_table[new_pos];
new_hash_table[new_pos] = se;
}
for (int i=0;i<(1<<hash_table_power);i++) {
while( hash_table[i] ) {
Entry *se=hash_table[i];
hash_table[i]=se->next;
int new_pos = se->hash & ((1<<new_hash_table_power)-1);
se->next=new_hash_table[new_pos];
new_hash_table[new_pos]=se;
}
memdelete_arr(hash_table);
}
hash_table = new_hash_table;
hash_table_power = new_hash_table_power;
if (hash_table)
memdelete_arr( hash_table );
hash_table=new_hash_table;
hash_table_power=new_hash_table_power;
}
/* I want to have only one function.. */
_FORCE_INLINE_ const Element *get_element(const TKey &p_key) const {
uint32_t hash = Hasher::hash(p_key);
uint32_t index = hash & ((1 << hash_table_power) - 1);
Element *e = hash_table[index];
/* I want to have only one function.. */
_FORCE_INLINE_ const Entry * get_entry( const TKey& p_key ) const {
uint32_t hash = Hasher::hash( p_key );
uint32_t index = hash&((1<<hash_table_power)-1);
Entry *e = hash_table[index];
while (e) {
/* checking hash first avoids comparing key, which may take longer */
if (e->hash == hash && Comparator::compare(e->pair.key, p_key)) {
if (e->hash == hash && e->pair.key == p_key ) {
/* the pair exists in this hashtable, so just update data */
return e;
}
e = e->next;
e=e->next;
}
return nullptr;
return NULL;
}
Element *create_element(const TKey &p_key) {
/* if element doesn't exist, create it */
Element *e = memnew(Element);
ERR_FAIL_COND_V_MSG(!e, nullptr, "Out of memory.");
uint32_t hash = Hasher::hash(p_key);
uint32_t index = hash & ((1 << hash_table_power) - 1);
Entry * create_entry(const TKey& p_key) {
/* if entry doesn't exist, create it */
Entry *e = memnew( Entry );
ERR_FAIL_COND_V(!e,NULL); /* out of memory */
uint32_t hash = Hasher::hash( p_key );
uint32_t index = hash&((1<<hash_table_power)-1);
e->next = hash_table[index];
e->hash = hash;
e->pair.key = p_key;
e->pair.data = TData();
e->pair.key=p_key;
hash_table[index] = e;
hash_table[index]=e;
elements++;
return e;
}
void copy_from(const HashMap &p_t) {
if (&p_t == this) {
void copy_from(const HashMap& p_t) {
if (&p_t==this)
return; /* much less bother with that */
}
clear();
if (!p_t.hash_table || p_t.hash_table_power == 0) {
if (!p_t.hash_table || p_t.hash_table_power==0)
return; /* not copying from empty table */
}
hash_table = memnew_arr(Element *, (uint64_t)1 << p_t.hash_table_power);
hash_table_power = p_t.hash_table_power;
elements = p_t.elements;
hash_table = memnew_arr(Entry*,1<<p_t.hash_table_power);
hash_table_power=p_t.hash_table_power;
elements=p_t.elements;
for (int i = 0; i < (1 << p_t.hash_table_power); i++) {
hash_table[i] = nullptr;
for (int i=0;i<( 1<<p_t.hash_table_power );i++) {
const Element *e = p_t.hash_table[i];
hash_table[i]=NULL;
/* elements will be in the reverse order, but it doesn't matter */
while (e) {
Element *le = memnew(Element); /* local element */
const Entry *e = p_t.hash_table[i];
*le = *e; /* copy data */
while(e) {
Entry *le = memnew( Entry ); /* local entry */
*le=*e; /* copy data */
/* add to list and reassign pointers */
le->next = hash_table[i];
hash_table[i] = le;
le->next=hash_table[i];
hash_table[i]=le;
e = e->next;
e=e->next;
}
}
}
}
}
public:
Element *set(const TKey &p_key, const TData &p_data) {
return set(Pair(p_key, p_data));
void set( const TKey& p_key, const TData& p_data ) {
set( Pair( p_key, p_data ) );
}
Element *set(const Pair &p_pair) {
Element *e = nullptr;
if (!hash_table) {
void set( const Pair& p_pair ) {
Entry *e=NULL;
if (!hash_table)
make_hash_table(); // if no table, make one
} else {
e = const_cast<Element *>(get_element(p_pair.key));
}
else
e = const_cast<Entry*>( get_entry(p_pair.key) );
/* if we made it up to here, the pair doesn't exist, create and assign */
if (!e) {
e = create_element(p_pair.key);
if (!e) {
return nullptr;
}
e=create_entry(p_pair.key);
if (!e)
return;
check_hash_table(); // perform mantenience routine
}
e->pair.data = p_pair.data;
return e;
}
bool has(const TKey &p_key) const {
return getptr(p_key) != nullptr;
bool has( const TKey& p_key ) const {
return getptr(p_key)!=NULL;
}
/**
@@ -278,15 +318,17 @@ public:
* first with has(key)
*/
const TData &get(const TKey &p_key) const {
const TData *res = getptr(p_key);
CRASH_COND_MSG(!res, "Map key not found.");
const TData& get( const TKey& p_key ) const {
const TData* res = getptr(p_key);
ERR_FAIL_COND_V(!res,*res);
return *res;
}
TData &get(const TKey &p_key) {
TData *res = getptr(p_key);
CRASH_COND_MSG(!res, "Map key not found.");
TData& get( const TKey& p_key ) {
TData* res = getptr(p_key);
ERR_FAIL_COND_V(!res,*res);
return *res;
}
@@ -295,32 +337,33 @@ public:
* This is mainly used for speed purposes.
*/
_FORCE_INLINE_ TData *getptr(const TKey &p_key) {
if (unlikely(!hash_table)) {
return nullptr;
}
Element *e = const_cast<Element *>(get_element(p_key));
_FORCE_INLINE_ TData* getptr( const TKey& p_key ) {
if (e) {
if (!hash_table)
return NULL;
Entry *e=const_cast<Entry*>(get_entry(p_key ));
if (e)
return &e->pair.data;
}
return nullptr;
return NULL;
}
_FORCE_INLINE_ const TData *getptr(const TKey &p_key) const {
if (unlikely(!hash_table)) {
return nullptr;
}
_FORCE_INLINE_ const TData* getptr( const TKey& p_key ) const {
const Element *e = const_cast<Element *>(get_element(p_key));
if (!hash_table)
return NULL;
if (e) {
const Entry *e=const_cast<Entry*>(get_entry(p_key ));
if (e)
return &e->pair.data;
}
return nullptr;
return NULL;
}
/**
@@ -328,117 +371,129 @@ public:
* This version is custom, will take a hash and a custom key (that should support operator==()
*/
template <class C>
_FORCE_INLINE_ TData *custom_getptr(C p_custom_key, uint32_t p_custom_hash) {
if (unlikely(!hash_table)) {
return nullptr;
}
template<class C>
_FORCE_INLINE_ TData* custom_getptr( C p_custom_key,uint32_t p_custom_hash ) {
uint32_t hash = p_custom_hash;
uint32_t index = hash & ((1 << hash_table_power) - 1);
Element *e = hash_table[index];
while (e) {
/* checking hash first avoids comparing key, which may take longer */
if (e->hash == hash && Comparator::compare(e->pair.key, p_custom_key)) {
/* the pair exists in this hashtable, so just update data */
return &e->pair.data;
}
e = e->next;
}
return nullptr;
}
template <class C>
_FORCE_INLINE_ const TData *custom_getptr(C p_custom_key, uint32_t p_custom_hash) const {
if (unlikely(!hash_table)) {
if (!hash_table)
return NULL;
}
uint32_t hash = p_custom_hash;
uint32_t index = hash & ((1 << hash_table_power) - 1);
uint32_t index = hash&((1<<hash_table_power)-1);
const Element *e = hash_table[index];
Entry *e = hash_table[index];
while (e) {
/* checking hash first avoids comparing key, which may take longer */
if (e->hash == hash && Comparator::compare(e->pair.key, p_custom_key)) {
if (e->hash == hash && e->pair.key == p_custom_key ) {
/* the pair exists in this hashtable, so just update data */
return &e->pair.data;
}
e = e->next;
e=e->next;
}
return NULL;
}
/**
* Erase an item, return true if erasing was successful
*/
template<class C>
_FORCE_INLINE_ const TData* custom_getptr( C p_custom_key,uint32_t p_custom_hash ) const {
bool erase(const TKey &p_key) {
if (unlikely(!hash_table)) {
return false;
if (!hash_table)
return NULL;
uint32_t hash = p_custom_hash;
uint32_t index = hash&((1<<hash_table_power)-1);
const Entry *e = hash_table[index];
while (e) {
/* checking hash first avoids comparing key, which may take longer */
if (e->hash == hash && e->pair.key == p_custom_key ) {
/* the pair exists in this hashtable, so just update data */
return &e->pair.data;
}
e=e->next;
}
uint32_t hash = Hasher::hash(p_key);
uint32_t index = hash & ((1 << hash_table_power) - 1);
return NULL;
}
Element *e = hash_table[index];
Element *p = nullptr;
/**
* Erase an item, return true if erasing was succesful
*/
bool erase( const TKey& p_key ) {
if (!hash_table)
return false;
uint32_t hash = Hasher::hash( p_key );
uint32_t index = hash&((1<<hash_table_power)-1);
Entry *e = hash_table[index];
Entry *p=NULL;
while (e) {
/* checking hash first avoids comparing key, which may take longer */
if (e->hash == hash && Comparator::compare(e->pair.key, p_key)) {
if (e->hash == hash && e->pair.key == p_key ) {
if (p) {
p->next = e->next;
p->next=e->next;
} else {
//begin of list
hash_table[index] = e->next;
hash_table[index]=e->next;
}
memdelete(e);
elements--;
if (elements == 0) {
if (elements==0)
erase_hash_table();
} else {
else
check_hash_table();
}
return true;
}
p = e;
e = e->next;
p=e;
e=e->next;
}
return false;
}
inline const TData &operator[](const TKey &p_key) const { //constref
inline const TData& operator[](const TKey& p_key) const { //constref
return get(p_key);
}
inline TData &operator[](const TKey &p_key) { //assignment
inline TData& operator[](const TKey& p_key ) { //assignment
Element *e = nullptr;
if (!hash_table) {
Entry *e=NULL;
if (!hash_table)
make_hash_table(); // if no table, make one
} else {
e = const_cast<Element *>(get_element(p_key));
}
else
e = const_cast<Entry*>( get_entry(p_key) );
/* if we made it up to here, the pair doesn't exist, create */
if (!e) {
e = create_element(p_key);
CRASH_COND(!e);
e=create_entry(p_key);
if (!e)
return *(TData*)NULL; /* panic! */
check_hash_table(); // perform mantenience routine
}
return e->pair.data;
}
/**
@@ -454,16 +509,16 @@ public:
*
* print( *k );
* }
*
*/
const TKey *next(const TKey *p_key) const {
if (unlikely(!hash_table)) {
return nullptr;
}
*
*/
const TKey* next(const TKey* p_key) const {
if (!hash_table) return NULL;
if (!p_key) { /* get the first key */
for (int i = 0; i < (1 << hash_table_power); i++) {
for (int i=0;i<(1<<hash_table_power);i++) {
if (hash_table[i]) {
return &hash_table[i]->pair.key;
}
@@ -471,16 +526,18 @@ public:
} else { /* get the next key */
const Element *e = get_element(*p_key);
ERR_FAIL_COND_V_MSG(!e, nullptr, "Invalid key supplied.");
const Entry *e = get_entry( *p_key );
ERR_FAIL_COND_V( !e, NULL ); /* invalid key supplied */
if (e->next) {
/* if there is a "next" in the list, return that */
return &e->next->pair.key;
} else {
/* go to next elements */
uint32_t index = e->hash & ((1 << hash_table_power) - 1);
/* go to next entries */
uint32_t index = e->hash&((1<<hash_table_power)-1);
index++;
for (int i = index; i < (1 << hash_table_power); i++) {
for (int i=index;i<(1<<hash_table_power);i++) {
if (hash_table[i]) {
return &hash_table[i]->pair.key;
}
@@ -488,86 +545,85 @@ public:
}
/* nothing found, was at end */
}
return nullptr; /* nothing found */
return NULL; /* nothing found */
}
inline unsigned int size() const {
return elements;
}
inline bool empty() const {
return elements == 0;
return elements==0;
}
void clear() {
/* clean up */
if (hash_table) {
for (int i = 0; i < (1 << hash_table_power); i++) {
for (int i=0;i<(1<<hash_table_power);i++) {
while (hash_table[i]) {
Element *e = hash_table[i];
hash_table[i] = e->next;
memdelete(e);
Entry *e=hash_table[i];
hash_table[i]=e->next;
memdelete( e );
}
}
memdelete_arr(hash_table);
memdelete_arr( hash_table );
}
hash_table = nullptr;
hash_table_power = 0;
elements = 0;
hash_table=0;
hash_table_power=0;
elements=0;
}
void operator=(const HashMap &p_table) {
void operator=(const HashMap& p_table) {
copy_from(p_table);
}
HashMap() {
hash_table = nullptr;
elements = 0;
hash_table_power = 0;
}
void get_key_value_ptr_array(const Pair **p_pairs) const {
if (unlikely(!hash_table)) {
return;
}
for (int i = 0; i < (1 << hash_table_power); i++) {
Element *e = hash_table[i];
while (e) {
*p_pairs = &e->pair;
p_pairs++;
e = e->next;
}
}
hash_table=NULL;
elements=0;
hash_table_power=0;
}
void get_key_list(List<TKey> *p_keys) const {
if (unlikely(!hash_table)) {
if (!hash_table)
return;
}
for (int i = 0; i < (1 << hash_table_power); i++) {
Element *e = hash_table[i];
while (e) {
for(int i=0;i<(1<<hash_table_power);i++) {
Entry *e=hash_table[i];
while(e) {
p_keys->push_back(e->pair.key);
e = e->next;
e=e->next;
}
}
}
HashMap(const HashMap &p_table) {
hash_table = nullptr;
elements = 0;
hash_table_power = 0;
HashMap(const HashMap& p_table) {
hash_table=NULL;
elements=0;
hash_table_power=0;
copy_from(p_table);
}
~HashMap() {
clear();
}
};
#endif

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,143 +26,94 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef HASHFUNCS_H
#define HASHFUNCS_H
#include "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 "typedefs.h"
/**
* Hashing functions
*/
/**
* DJB2 Hash function
* @param C String
* @return 32-bits hashcode
*/
static inline uint32_t hash_djb2(const char *p_cstr) {
const unsigned char *chr = (const unsigned char *)p_cstr;
const unsigned char* chr=(const unsigned char*)p_cstr;
uint32_t hash = 5381;
uint32_t c;
while ((c = *chr++)) {
while ((c = *chr++))
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
}
return hash;
}
static inline uint32_t hash_djb2_buffer(const uint8_t *p_buff, int p_len, uint32_t p_prev = 5381) {
static inline uint32_t hash_djb2_buffer(const uint8_t *p_buff, int p_len,uint32_t p_prev=5381) {
uint32_t hash = p_prev;
for (int i = 0; i < p_len; i++) {
for(int i=0;i<p_len;i++)
hash = ((hash << 5) + hash) + p_buff[i]; /* hash * 33 + c */
}
return hash;
}
static inline uint32_t hash_djb2_one_32(uint32_t p_in, uint32_t p_prev = 5381) {
return ((p_prev << 5) + p_prev) + p_in;
static inline uint32_t hash_djb2_one_32(uint32_t p_in,uint32_t p_prev=5381) {
return ((p_prev<<5)+p_prev)+p_in;
}
static inline uint32_t hash_one_uint64(const uint64_t p_int) {
uint64_t v = p_int;
v = (~v) + (v << 18); // v = (v << 18) - v - 1;
v = v ^ (v >> 31);
v = v * 21; // v = (v + (v << 2)) + (v << 4);
v = v ^ (v >> 11);
v = v + (v << 6);
v = v ^ (v >> 22);
return (int)v;
}
static inline uint32_t hash_djb2_one_float(double p_in, uint32_t p_prev = 5381) {
static inline uint32_t hash_djb2_one_float(float p_in,uint32_t p_prev=5381) {
union {
double d;
uint64_t i;
float f;
uint32_t i;
} u;
// Normalize +/- 0.0 and NaN values so they hash the same.
if (p_in == 0.0f) {
u.d = 0.0;
} else if (Math::is_nan(p_in)) {
u.d = Math_NAN;
} else {
u.d = p_in;
}
// handle -0 case
if (p_in==0.0f) u.f=0.0f;
else u.f=p_in;
return ((p_prev << 5) + p_prev) + hash_one_uint64(u.i);
return ((p_prev<<5)+p_prev)+u.i;
}
template <class T>
template<class T>
static inline uint32_t make_uint32_t(T p_in) {
union {
T t;
uint32_t _u32;
} _u;
_u._u32 = 0;
_u.t = p_in;
_u._u32=0;
_u.t=p_in;
return _u._u32;
}
static inline uint64_t hash_djb2_one_64(uint64_t p_in, uint64_t p_prev = 5381) {
return ((p_prev << 5) + p_prev) + p_in;
static inline uint64_t hash_djb2_one_64(uint64_t p_in,uint64_t p_prev=5381) {
return ((p_prev<<5)+p_prev)+p_in;
}
template <class T>
template<class T>
static inline uint64_t make_uint64_t(T p_in) {
union {
T t;
uint64_t _u64;
} _u;
_u._u64 = 0; // in case p_in is smaller
_u._u64=0; // in case p_in is smaller
_u.t = p_in;
_u.t=p_in;
return _u._u64;
}
struct HashMapHasherDefault {
static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }
static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); }
static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); }
static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); }
static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); }
static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_djb2_one_float(p_double); }
static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return p_int; }
static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return (uint32_t)p_int; }
static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return p_int; }
static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return (uint32_t)p_int; }
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; }
static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; }
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; }
static _FORCE_INLINE_ uint32_t hash(const 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); }
};
template <typename T>
struct HashMapComparatorDefault {
static bool compare(const T &p_lhs, const T &p_rhs) {
return p_lhs == p_rhs;
}
bool compare(const float &p_lhs, const float &p_rhs) {
return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs));
}
bool compare(const double &p_lhs, const double &p_rhs) {
return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs));
}
};
#endif

View File

@@ -0,0 +1,43 @@
/*************************************************************************/
/* value_evaluator.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef VALUE_EVALUATOR_H
#define VALUE_EVALUATOR_H
#include "core/object.h"
class ValueEvaluator : public Object {
OBJ_TYPE(ValueEvaluator, Object);
public:
virtual double eval(const String& p_text) {
return p_text.to_double();
}
};
#endif // VALUE_EVALUATOR_H

View File

@@ -16,8 +16,8 @@
#include "hq2x.h"
#include "math_funcs.h"
#include "core/math/math_funcs.h"
static const uint32_t AMASK = 0xFF000000;
static const uint32_t YMASK = 0x00FF0000;

View File

@@ -1,7 +1,7 @@
#ifndef HQ2X_H
#define HQ2X_H
#include "core/typedefs.h"
#include "typedefs.h"
uint32_t *hq2x_resize(

File diff suppressed because it is too large Load Diff

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,193 +26,211 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef IMAGE_H
#define IMAGE_H
#include "core/color.h"
#include "core/math/rect2.h"
#include "core/pool_vector.h"
#include "core/resource.h"
#include "dvector.h"
#include "color.h"
#include "math_2d.h"
/**
* @author Juan Linietsky <reduzio@gmail.com>
*
* Image storage class. This is used to store an image in user memory, as well as
* providing some basic methods for image manipulation.
* Images can be loaded from a file, or registered into the Render object as textures.
*/
*/
class Image;
typedef Error (*SavePNGFunc)(const String &p_path, const Ref<Image> &p_img);
typedef PoolVector<uint8_t> (*SavePNGBufferFunc)(const Ref<Image> &p_img);
typedef Ref<Image> (*ImageMemLoadFunc)(const uint8_t *p_png, int p_size);
typedef Error (*SavePNGFunc)(const String &p_path, Image& p_img);
typedef Error (*SaveEXRFunc)(const String &p_path, const Ref<Image> &p_img, bool p_grayscale);
class Image : public Resource {
GDCLASS(Image, Resource);
public:
static SavePNGFunc save_png_func;
static SaveEXRFunc save_exr_func;
static SavePNGBufferFunc save_png_buffer_func;
class Image {
enum {
MAX_WIDTH = 16384, // force a limit somehow
MAX_HEIGHT = 16384 // force a limit somehow
MAX_WIDTH=16384, // force a limit somehow
MAX_HEIGHT=16384// force a limit somehow
};
public:
static SavePNGFunc save_png_func;
enum Format {
FORMAT_L8, //luminance
FORMAT_LA8, //luminance-alpha
FORMAT_R8,
FORMAT_RG8,
FORMAT_RGB8,
FORMAT_RGBA8,
FORMAT_RGBA4444,
FORMAT_RGBA5551,
FORMAT_RF, //float
FORMAT_RGF,
FORMAT_RGBF,
FORMAT_RGBAF,
FORMAT_RH, //half float
FORMAT_RGH,
FORMAT_RGBH,
FORMAT_RGBAH,
FORMAT_RGBE9995,
FORMAT_DXT1, //s3tc bc1
FORMAT_DXT3, //bc2
FORMAT_DXT5, //bc3
FORMAT_RGTC_R,
FORMAT_RGTC_RG,
FORMAT_BPTC_RGBA, //btpc bc7
FORMAT_BPTC_RGBF, //float bc6h
FORMAT_BPTC_RGBFU, //unsigned float bc6hu
FORMAT_PVRTC2, //pvrtc
FORMAT_PVRTC2A,
FORMAT_GRAYSCALE, ///< one byte per pixel, 0-255
FORMAT_INTENSITY, ///< one byte per pixel, 0-255
FORMAT_GRAYSCALE_ALPHA, ///< two bytes per pixel, 0-255. alpha 0-255
FORMAT_RGB, ///< one byte R, one byte G, one byte B
FORMAT_RGBA, ///< one byte R, one byte G, one byte B, one byte A
FORMAT_INDEXED, ///< index byte 0-256, and after image end, 256*3 bytes of palette
FORMAT_INDEXED_ALPHA, ///< index byte 0-256, and after image end, 256*4 bytes of palette (alpha)
FORMAT_YUV_422,
FORMAT_YUV_444,
FORMAT_BC1, // DXT1
FORMAT_BC2, // DXT3
FORMAT_BC3, // DXT5
FORMAT_BC4, // ATI1
FORMAT_BC5, // ATI2
FORMAT_PVRTC2,
FORMAT_PVRTC2_ALPHA,
FORMAT_PVRTC4,
FORMAT_PVRTC4A,
FORMAT_ETC, //etc1
FORMAT_ETC2_R11, //etc2
FORMAT_ETC2_R11S, //signed, NOT srgb.
FORMAT_ETC2_RG11,
FORMAT_ETC2_RG11S,
FORMAT_ETC2_RGB8,
FORMAT_ETC2_RGBA8,
FORMAT_ETC2_RGB8A1,
FORMAT_PVRTC4_ALPHA,
FORMAT_ETC, // regular ETC, no transparency
FORMAT_ATC,
FORMAT_ATC_ALPHA_EXPLICIT,
FORMAT_ATC_ALPHA_INTERPOLATED,
/*FORMAT_ETC2_R, for the future..
FORMAT_ETC2_RG,
FORMAT_ETC2_RGB,
FORMAT_ETC2_RGBA1,
FORMAT_ETC2_RGBA,*/
FORMAT_CUSTOM,
FORMAT_MAX
};
static const char *format_names[FORMAT_MAX];
static const char* format_names[FORMAT_MAX];
enum Interpolation {
INTERPOLATE_NEAREST,
INTERPOLATE_BILINEAR,
INTERPOLATE_CUBIC,
INTERPOLATE_TRILINEAR,
INTERPOLATE_LANCZOS,
/* INTERPOLATE_TRICUBIC, */
/* INTERPOLATE GAUSS */
};
enum CompressSource {
COMPRESS_SOURCE_GENERIC,
COMPRESS_SOURCE_SRGB,
COMPRESS_SOURCE_NORMAL,
COMPRESS_SOURCE_LAYERED,
COMPRESS_SOURCE_MAX,
};
//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 ImageMemLoadFunc _tga_mem_loader_func;
static ImageMemLoadFunc _bmp_mem_loader_func;
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 Image (*_png_mem_loader_func)(const uint8_t* p_png,int p_size);
static Image (*_jpg_mem_loader_func)(const uint8_t* p_png,int p_size);
static void (*_image_compress_bc_func)(Image *);
static void (*_image_compress_pvrtc2_func)(Image *);
static void (*_image_compress_pvrtc4_func)(Image *);
static void (*_image_compress_etc1_func)(Image *, float);
static void (*_image_compress_etc2_func)(Image *, float, CompressSource p_source);
static void (*_image_compress_etc_func)(Image *);
static void (*_image_decompress_pvrtc)(Image *);
static void (*_image_decompress_bc)(Image *);
static void (*_image_decompress_bptc)(Image *);
static void (*_image_decompress_etc1)(Image *);
static void (*_image_decompress_etc2)(Image *);
static void (*_image_decompress_etc)(Image *);
static PoolVector<uint8_t> (*webp_lossy_packer)(const Ref<Image> &p_image, float p_quality);
static PoolVector<uint8_t> (*webp_lossless_packer)(const Ref<Image> &p_image);
static Ref<Image> (*webp_unpacker)(const PoolVector<uint8_t> &p_buffer);
static PoolVector<uint8_t> (*png_packer)(const Ref<Image> &p_image);
static Ref<Image> (*png_unpacker)(const PoolVector<uint8_t> &p_buffer);
PoolVector<uint8_t>::Write write_lock;
protected:
static void _bind_methods();
Error _decompress_bc();
static DVector<uint8_t> (*lossy_packer)(const Image& p_image,float p_quality);
static Image (*lossy_unpacker)(const DVector<uint8_t>& p_buffer);
static DVector<uint8_t> (*lossless_packer)(const Image& p_image);
static Image (*lossless_unpacker)(const DVector<uint8_t>& p_buffer);
private:
void _create_empty(int p_width, int p_height, bool p_use_mipmaps, Format p_format) {
create(p_width, p_height, p_use_mipmaps, p_format);
}
void _create_from_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const PoolVector<uint8_t> &p_data) {
create(p_width, p_height, p_use_mipmaps, p_format, p_data);
}
//internal byte based color
struct BColor {
union {
uint8_t col[4];
struct {
uint8_t r,g,b,a;
};
};
bool operator==(const BColor& p_color) const { for(int i=0;i<4;i++) {if (col[i]!=p_color.col[i]) return false; } return true; }
_FORCE_INLINE_ uint8_t gray() const { return (uint16_t(col[0])+uint16_t(col[1])+uint16_t(col[2]))/3; }
_FORCE_INLINE_ BColor() {}
BColor(uint8_t p_r,uint8_t p_g,uint8_t p_b,uint8_t p_a=255) { col[0]=p_r; col[1]=p_g; col[2]=p_b; col[3]=p_a; }
};
//median cut classes
struct BColorPos {
uint32_t index;
BColor color;
struct SortR {
bool operator()(const BColorPos& ca, const BColorPos& cb) const { return ca.color.r < cb.color.r; }
};
struct SortG {
bool operator()(const BColorPos& ca, const BColorPos& cb) const { return ca.color.g < cb.color.g; }
};
struct SortB {
bool operator()(const BColorPos& ca, const BColorPos& cb) const { return ca.color.b < cb.color.b; }
};
struct SortA {
bool operator()(const BColorPos& ca, const BColorPos& cb) const { return ca.color.a < cb.color.a; }
};
};
struct SPTree {
bool leaf;
uint8_t split_plane;
uint8_t split_value;
union {
int left;
int color;
};
int right;
SPTree() { leaf=true; left=-1; right=-1;}
};
struct MCBlock {
BColorPos min_color,max_color;
BColorPos *colors;
int sp_idx;
int color_count;
int get_longest_axis_index() const;
int get_longest_axis_length() const;
bool operator<(const MCBlock& p_block) const;
void shrink();
MCBlock();
MCBlock(BColorPos *p_colors,int p_color_count);
};
Format format;
PoolVector<uint8_t> data;
int width, height;
bool mipmaps;
DVector<uint8_t> data;
int width,height,mipmaps;
void _copy_internals_from(const Image &p_image) {
format = p_image.format;
width = p_image.width;
height = p_image.height;
mipmaps = p_image.mipmaps;
data = p_image.data;
}
_FORCE_INLINE_ void _get_mipmap_offset_and_size(int p_mipmap, int &r_offset, int &r_width, int &r_height) const; //get where the mipmap begins in data
static int _get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps = -1);
_FORCE_INLINE_ BColor _get_pixel(int p_x,int p_y,const unsigned char *p_data,int p_data_size) const;
_FORCE_INLINE_ BColor _get_pixelw(int p_x,int p_y,int p_width,const unsigned char *p_data,int p_data_size) const;
_FORCE_INLINE_ void _put_pixelw(int p_x,int p_y, int p_width, const BColor& p_color, unsigned char *p_data);
_FORCE_INLINE_ void _put_pixel(int p_x,int p_y, const BColor& p_color, unsigned char *p_data);
_FORCE_INLINE_ void _get_mipmap_offset_and_size(int p_mipmap,int &r_offset, int &r_width, int &r_height) const; //get where the mipmap begins in data
_FORCE_INLINE_ static void _get_format_min_data_size(Format p_format,int &r_w, int &r_h);
static int _get_dst_image_size(int p_width, int p_height, Format p_format,int &r_mipmaps,int p_mipmaps=-1);
bool _can_modify(Format p_format) const;
_FORCE_INLINE_ void _put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, const uint8_t *p_pixel);
_FORCE_INLINE_ void _get_pixelb(int p_x, int p_y, uint32_t p_pixelsize, const uint8_t *p_data, uint8_t *p_pixel);
void _set_data(const Dictionary &p_data);
Dictionary _get_data() const;
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
Vector2 get_size() const;
bool has_mipmaps() const;
int get_mipmap_count() const;
int get_mipmaps() const;
/**
* Convert the image to another format, conversion only to raw byte format
* Get a pixel from the image. for grayscale or indexed formats, use Color::gray to obtain the actual
* value.
*/
void convert(Format p_new_format);
Color get_pixel(int p_x,int p_y,int p_mipmap=0) const;
/**
* Set a pixel into the image. for grayscale or indexed formats, a suitable Color constructor.
*/
void put_pixel(int p_x,int p_y, const Color& p_color,int p_mipmap=0); /* alpha and index are averaged */
/**
* Convert the image to another format, as close as it can be done.
*/
void convert( Format p_new_format );
Image converted(int p_new_format) {
ERR_FAIL_INDEX_V(p_new_format, FORMAT_MAX, Image());
Image ret = *this;
ret.convert((Format)p_new_format);
return ret;
};
/**
* Get the current image format.
@@ -221,52 +238,57 @@ public:
Format get_format() const;
int get_mipmap_offset(int p_mipmap) const; //get where the mipmap begins in data
void get_mipmap_offset_and_size(int p_mipmap, int &r_ofs, int &r_size) const; //get where the mipmap begins in data
void get_mipmap_offset_size_and_dimensions(int p_mipmap, int &r_ofs, int &r_size, int &w, int &h) const; //get where the mipmap begins in data
void get_mipmap_offset_and_size(int p_mipmap,int &r_ofs, int &r_size) const; //get where the mipmap begins in data
void get_mipmap_offset_size_and_dimensions(int p_mipmap,int &r_ofs, int &r_size,int &w, int& h) const; //get where the mipmap begins in data
/**
* Resize the image, using the preferred interpolation method.
* Resize the image, using the prefered interpolation method.
* Indexed-Color images always use INTERPOLATE_NEAREST.
*/
void resize_to_po2(bool p_square = false, Interpolation p_interpolation = INTERPOLATE_BILINEAR);
void resize(int p_width, int p_height, Interpolation p_interpolation = INTERPOLATE_BILINEAR);
void resize_to_po2(bool p_square=false);
void resize( int p_width, int p_height, Interpolation p_interpolation=INTERPOLATE_BILINEAR );
Image resized( int p_width, int p_height, int p_interpolation=INTERPOLATE_BILINEAR );
void shrink_x2();
void expand_x2_hq2x();
bool is_size_po2() const;
/**
* Crop the image to a specific size, if larger, then the image is filled by black
*/
void crop_from_point(int p_x, int p_y, int p_width, int p_height);
void crop(int p_width, int p_height);
void crop( int p_width, int p_height );
void flip_x();
void flip_y();
/**
* Generate a mipmap to an image (creates an image 1/4 the size, with averaging of 4->1)
*/
Error generate_mipmaps(bool p_renormalize = false);
Error generate_mipmaps(int p_amount=-1,bool p_keep_existing=false);
void clear_mipmaps();
void normalize(); //for normal maps
/**
* Generate a normal map from a grayscale image
*/
void make_normalmap(float p_height_scale=1.0);
/**
* Create a new image of a given size and format. Current image will be lost
*/
void create(int p_width, int p_height, bool p_use_mipmaps, Format p_format);
void create(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const PoolVector<uint8_t> &p_data);
void create(int p_width, int p_height, int p_mipmaps, Format p_format, const DVector<uint8_t>& p_data);
void create(const char **p_xpm);
void create( const char ** p_xpm );
/**
* returns true when the image is empty (0,0) in size
*/
bool empty() const;
PoolVector<uint8_t> get_data() const;
DVector<uint8_t> get_data() const;
Error load(const String &p_path);
Error save_png(const String &p_path) const;
PoolVector<uint8_t> save_png_to_buffer() const;
Error save_exr(const String &p_path, bool p_grayscale) const;
Error load(const String& p_path);
Error save_png(const String& p_path);
/**
* create an empty image
@@ -279,7 +301,7 @@ public:
/**
* import an image of a specific size and format from a pointer
*/
Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const PoolVector<uint8_t> &p_data);
Image(int p_width, int p_height, int p_mipmaps, Format p_format, const DVector<uint8_t>& p_data);
enum AlphaMode {
ALPHA_NONE,
@@ -290,97 +312,57 @@ public:
AlphaMode detect_alpha() const;
bool is_invisible() const;
void put_indexed_pixel(int p_x, int p_y, uint8_t p_idx,int p_mipmap=0);
uint8_t get_indexed_pixel(int p_x, int p_y,int p_mipmap=0) const;
void set_pallete(const DVector<uint8_t>& p_data);
static int get_format_pixel_size(Format p_format);
static int get_format_pixel_rshift(Format p_format);
static int get_format_block_size(Format p_format);
static void get_format_min_pixel_size(Format p_format, int &r_w, int &r_h);
static int get_image_data_size(int p_width, int p_height, Format p_format, bool p_mipmaps = false);
static int get_format_pallete_size(Format p_format);
static int get_image_data_size(int p_width, int p_height, Format p_format,int p_mipmaps=0);
static int get_image_required_mipmaps(int p_width, int p_height, Format p_format);
static int get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap);
bool operator==(const Image& p_image) const;
void quantize();
enum CompressMode {
COMPRESS_S3TC,
COMPRESS_BC,
COMPRESS_PVRTC2,
COMPRESS_PVRTC4,
COMPRESS_ETC,
COMPRESS_ETC2,
COMPRESS_BPTC,
COMPRESS_MAX,
COMPRESS_ETC
};
Error compress(CompressMode p_mode = COMPRESS_S3TC, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7);
Error compress(CompressMode p_mode=COMPRESS_BC);
Image compressed(int p_mode); /* from the Image::CompressMode enum */
Error decompress();
Image decompressed() const;
bool is_compressed() const;
void fix_alpha_edges();
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);
void blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest);
void blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest);
void fill(const Color &c);
void blit_rect(const Image& p_src, const Rect2& p_src_rect,const Point2& p_dest);
void brush_transfer(const Image& p_src, const Image& p_brush, const Point2& p_dest);
Image brushed(const Image& p_src, const Image& p_brush, const Point2& p_dest) const;
Rect2 get_used_rect() const;
Ref<Image> get_rect(const Rect2 &p_area) const;
Image get_rect(const Rect2& p_area) const;
static void set_compress_bc_func(void (*p_compress_func)(Image *, 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 *));
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);
Error load_tga_from_buffer(const PoolVector<uint8_t> &p_array);
Error load_bmp_from_buffer(const PoolVector<uint8_t> &p_array);
Image(const uint8_t *p_mem_png_jpg, int p_len = -1);
Image(const uint8_t* p_mem_png_jpg, int p_len=-1);
Image(const char **p_xpm);
virtual Ref<Resource> duplicate(bool p_subresources = false) const;
void lock();
void unlock();
//this is used for compression
enum DetectChannels {
DETECTED_L,
DETECTED_LA,
DETECTED_R,
DETECTED_RG,
DETECTED_RGB,
DETECTED_RGBA,
};
DetectChannels get_detected_channels();
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_dst, 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) {
ERR_FAIL_COND_MSG(p_image.is_null(), "It's not a reference to a valid Image object.");
format = p_image->format;
width = p_image->width;
height = p_image->height;
mipmaps = p_image->mipmaps;
data = p_image->data;
}
~Image();
};
VARIANT_ENUM_CAST(Image::Format)
VARIANT_ENUM_CAST(Image::Interpolation)
VARIANT_ENUM_CAST(Image::CompressMode)
VARIANT_ENUM_CAST(Image::CompressSource)
VARIANT_ENUM_CAST(Image::AlphaMode)
#endif

365
core/image_quantize.cpp Normal file
View File

@@ -0,0 +1,365 @@
/*************************************************************************/
/* image_quantize.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "image.h"
#include <stdio.h>
#include "print_string.h"
#ifdef TOOLS_ENABLED
#include "set.h"
#include "sort.h"
#include "os/os.h"
//#define QUANTIZE_SPEED_OVER_QUALITY
Image::MCBlock::MCBlock() {
}
Image::MCBlock::MCBlock(BColorPos *p_colors,int p_color_count) {
colors=p_colors;
color_count=p_color_count;
min_color.color=BColor(255,255,255,255);
max_color.color=BColor(0,0,0,0);
shrink();
}
int Image::MCBlock::get_longest_axis_index() const {
int max_dist=-1;
int max_index=0;
for(int i=0;i<4;i++) {
int d = max_color.color.col[i]-min_color.color.col[i];
if (d>max_dist) {
max_index=i;
max_dist=d;
}
}
return max_index;
}
int Image::MCBlock::get_longest_axis_length() const {
int max_dist=-1;
for(int i=0;i<4;i++) {
int d = max_color.color.col[i]-min_color.color.col[i];
if (d>max_dist) {
max_dist=d;
}
}
return max_dist;
}
bool Image::MCBlock::operator<(const MCBlock& p_block) const {
int alen = get_longest_axis_length();
int blen = p_block.get_longest_axis_length();
if (alen==blen) {
return colors < p_block.colors;
} else
return alen < blen;
}
void Image::MCBlock::shrink() {
min_color=colors[0];
max_color=colors[0];
for(int i=1;i<color_count;i++) {
for(int j=0;j<4;j++) {
min_color.color.col[j]=MIN(min_color.color.col[j],colors[i].color.col[j]);
max_color.color.col[j]=MAX(max_color.color.col[j],colors[i].color.col[j]);
}
}
}
void Image::quantize() {
bool has_alpha = detect_alpha()!=ALPHA_NONE;
bool quantize_fast=OS::get_singleton()->has_environment("QUANTIZE_FAST");
convert(FORMAT_RGBA);
ERR_FAIL_COND( format!=FORMAT_RGBA );
DVector<uint8_t> indexed_data;
{
int color_count = data.size()/4;
ERR_FAIL_COND(color_count==0);
Set<MCBlock> block_queue;
DVector<BColorPos> data_colors;
data_colors.resize(color_count);
DVector<BColorPos>::Write dcw=data_colors.write();
DVector<uint8_t>::Read dr = data.read();
const BColor * drptr=(const BColor*)&dr[0];
BColorPos *bcptr=&dcw[0];
{
for(int i=0;i<color_count;i++) {
//uint32_t data_ofs=i<<2;
bcptr[i].color=drptr[i];//BColor(drptr[data_ofs+0],drptr[data_ofs+1],drptr[data_ofs+2],drptr[data_ofs+3]);
bcptr[i].index=i;
}
}
//printf("color count: %i\n",color_count);
/*
for(int i=0;i<color_count;i++) {
BColor bc = ((BColor*)&wb[0])[i];
printf("%i - %i,%i,%i,%i\n",i,bc.r,bc.g,bc.b,bc.a);
}*/
MCBlock initial_block((BColorPos*)&dcw[0],color_count);
block_queue.insert(initial_block);
while( block_queue.size() < 256 && block_queue.back()->get().color_count > 1 ) {
MCBlock longest = block_queue.back()->get();
//printf("longest: %i (%i)\n",longest.get_longest_axis_index(),longest.get_longest_axis_length());
block_queue.erase(block_queue.back());
BColorPos *first = longest.colors;
BColorPos *median = longest.colors + (longest.color_count+1)/2;
BColorPos *end = longest.colors + longest.color_count;
#if 0
int lai =longest.get_longest_axis_index();
switch(lai) {
#if 0
case 0: { SortArray<BColorPos,BColorPos::SortR> sort; sort.sort(first,end-first); } break;
case 1: { SortArray<BColorPos,BColorPos::SortG> sort; sort.sort(first,end-first); } break;
case 2: { SortArray<BColorPos,BColorPos::SortB> sort; sort.sort(first,end-first); } break;
case 3: { SortArray<BColorPos,BColorPos::SortA> sort; sort.sort(first,end-first); } break;
#else
case 0: { SortArray<BColorPos,BColorPos::SortR> sort; sort.nth_element(0,end-first,median-first,first); } break;
case 1: { SortArray<BColorPos,BColorPos::SortG> sort; sort.nth_element(0,end-first,median-first,first); } break;
case 2: { SortArray<BColorPos,BColorPos::SortB> sort; sort.nth_element(0,end-first,median-first,first); } break;
case 3: { SortArray<BColorPos,BColorPos::SortA> sort; sort.nth_element(0,end-first,median-first,first); } break;
#endif
}
//avoid same color from being split in 2
//search forward and flip
BColorPos *median_end=median;
BColorPos *p=median_end+1;
while(p!=end) {
if (median_end->color==p->color) {
SWAP(*(median_end+1),*p);
median_end++;
}
p++;
}
//search backward and flip
BColorPos *median_begin=median;
p=median_begin-1;
while(p!=(first-1)) {
if (median_begin->color==p->color) {
SWAP(*(median_begin-1),*p);
median_begin--;
}
p--;
}
if (first < median_begin) {
median=median_begin;
} else if (median_end < end-1) {
median=median_end+1;
} else {
break; //shouldn't have arrived here, since it means all pixels are equal, but wathever
}
MCBlock left(first,median-first);
MCBlock right(median,end-median);
block_queue.insert(left);
block_queue.insert(right);
#else
switch(longest.get_longest_axis_index()) {
case 0: { SortArray<BColorPos,BColorPos::SortR> sort; sort.nth_element(0,end-first,median-first,first); } break;
case 1: { SortArray<BColorPos,BColorPos::SortG> sort; sort.nth_element(0,end-first,median-first,first); } break;
case 2: { SortArray<BColorPos,BColorPos::SortB> sort; sort.nth_element(0,end-first,median-first,first); } break;
case 3: { SortArray<BColorPos,BColorPos::SortA> sort; sort.nth_element(0,end-first,median-first,first); } break;
}
MCBlock left(first,median-first);
MCBlock right(median,end-median);
block_queue.insert(left);
block_queue.insert(right);
#endif
}
while(block_queue.size() > 256) {
block_queue.erase(block_queue.front());// erase least significant
}
int res_colors=0;
int comp_size = (has_alpha?4:3);
indexed_data.resize(color_count + 256*comp_size);
DVector<uint8_t>::Write iw = indexed_data.write();
uint8_t *iwptr=&iw[0];
BColor pallete[256];
// print_line("applying quantization - res colors "+itos(block_queue.size()));
while(block_queue.size()) {
const MCBlock &b = block_queue.back()->get();
uint64_t sum[4]={0,0,0,0};
for(int i=0;i<b.color_count;i++) {
sum[0]+=b.colors[i].color.col[0];
sum[1]+=b.colors[i].color.col[1];
sum[2]+=b.colors[i].color.col[2];
sum[3]+=b.colors[i].color.col[3];
}
BColor c( sum[0]/b.color_count, sum[1]/b.color_count, sum[2]/b.color_count, sum[3]/b.color_count );
//printf(" %i: %i,%i,%i,%i out of %i\n",res_colors,c.r,c.g,c.b,c.a,b.color_count);
for(int i=0;i<comp_size;i++) {
iwptr[ color_count + res_colors * comp_size + i ] = c.col[i];
}
if (quantize_fast) {
for(int i=0;i<b.color_count;i++) {
iwptr[b.colors[i].index]=res_colors;
}
} else {
pallete[res_colors]=c;
}
res_colors++;
block_queue.erase(block_queue.back());
}
if (!quantize_fast) {
for(int i=0;i<color_count;i++) {
const BColor &c=drptr[i];
uint8_t best_dist_idx=0;
uint32_t dist=0xFFFFFFFF;
for(int j=0;j<res_colors;j++) {
const BColor &pc=pallete[j];
uint32_t d = 0;
{ int16_t v = (int16_t)c.r-(int16_t)pc.r; d+=v*v; }
{ int16_t v = (int16_t)c.g-(int16_t)pc.g; d+=v*v; }
{ int16_t v = (int16_t)c.b-(int16_t)pc.b; d+=v*v; }
{ int16_t v = (int16_t)c.a-(int16_t)pc.a; d+=v*v; }
if (d<=dist) {
best_dist_idx=j;
dist=d;
}
}
iwptr[ i ] = best_dist_idx;
}
}
//iw = DVector<uint8_t>::Write();
//dr = DVector<uint8_t>::Read();
//wb = DVector<uint8_t>::Write();
}
print_line(itos(indexed_data.size()));
data=indexed_data;
format=has_alpha?FORMAT_INDEXED_ALPHA:FORMAT_INDEXED;
} //do none
#else
void Image::quantize() {} //do none
#endif

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,85 +26,66 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "input_map.h"
#include "globals.h"
#include "os/keyboard.h"
#include "core/os/input.h"
#include "core/os/keyboard.h"
#include "core/project_settings.h"
InputMap *InputMap::singleton = nullptr;
int InputMap::ALL_DEVICES = -1;
InputMap *InputMap::singleton=NULL;
void InputMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_action", "action"), &InputMap::has_action);
ClassDB::bind_method(D_METHOD("get_actions"), &InputMap::_get_actions);
ClassDB::bind_method(D_METHOD("add_action", "action", "deadzone"), &InputMap::add_action, DEFVAL(0.5f));
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_get_deadzone", "action"), &InputMap::action_get_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", "exact_match"), &InputMap::event_is_action, DEFVAL(false));
ClassDB::bind_method(D_METHOD("load_from_globals"), &InputMap::load_from_globals);
ObjectTypeDB::bind_method(_MD("has_action","action"),&InputMap::has_action);
ObjectTypeDB::bind_method(_MD("get_action_id","action"),&InputMap::get_action_id);
ObjectTypeDB::bind_method(_MD("get_action_from_id","id"),&InputMap::get_action_from_id);
ObjectTypeDB::bind_method(_MD("get_actions"),&InputMap::_get_actions);
ObjectTypeDB::bind_method(_MD("add_action","action"),&InputMap::add_action);
ObjectTypeDB::bind_method(_MD("erase_action","action"),&InputMap::erase_action);
ObjectTypeDB::bind_method(_MD("action_add_event","action","event"),&InputMap::action_add_event);
ObjectTypeDB::bind_method(_MD("action_has_event","action","event"),&InputMap::action_has_event);
ObjectTypeDB::bind_method(_MD("action_erase_event","action","event"),&InputMap::action_erase_event);
ObjectTypeDB::bind_method(_MD("get_action_list","action"),&InputMap::_get_action_list);
ObjectTypeDB::bind_method(_MD("event_is_action","event","action"),&InputMap::event_is_action);
ObjectTypeDB::bind_method(_MD("load_from_globals"),&InputMap::load_from_globals);
}
/**
* Returns an nonexistent action error message with a suggestion of the closest
* matching action name (if possible).
*/
String InputMap::suggest_actions(const StringName &p_action) const {
List<StringName> actions = get_actions();
StringName closest_action;
float closest_similarity = 0.0;
// Find the most action with the most similar name.
for (List<StringName>::Element *E = actions.front(); E; E = E->next()) {
const float similarity = String(E->get()).similarity(p_action);
void InputMap::add_action(const StringName& p_action) {
if (similarity > closest_similarity) {
closest_action = E->get();
closest_similarity = similarity;
}
}
String error_message = vformat("The InputMap action \"%s\" doesn't exist.", p_action);
if (closest_similarity >= 0.4) {
// Only include a suggestion in the error message if it's similar enough.
error_message += vformat(" Did you mean \"%s\"?", closest_action);
}
return error_message;
}
void InputMap::add_action(const StringName &p_action, float p_deadzone) {
ERR_FAIL_COND_MSG(input_map.has(p_action), "InputMap already has action \"" + String(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;
ERR_FAIL_COND( input_map.has(p_action) );
input_map[p_action]=Action();
static int last_id=1;
input_map[p_action].id=last_id;
input_id_map[last_id]=p_action;
last_id++;
}
void InputMap::erase_action(const StringName &p_action) {
ERR_FAIL_COND_MSG(!input_map.has(p_action), suggest_actions(p_action));
void InputMap::erase_action(const StringName& p_action) {
ERR_FAIL_COND( !input_map.has(p_action) );
input_id_map.erase(input_map[p_action].id);
input_map.erase(p_action);
}
StringName InputMap::get_action_from_id(int p_id) const {
ERR_FAIL_COND_V(!input_id_map.has(p_id),StringName());
return input_id_map[p_id];
}
Array InputMap::_get_actions() {
Array ret;
List<StringName> actions = get_actions();
if (actions.empty()) {
if(actions.empty())
return ret;
}
for (const List<StringName>::Element *E = actions.front(); E; E = E->next()) {
for(const List<StringName>::Element *E=actions.front();E;E=E->next()) {
ret.push_back(E->get());
}
@@ -113,265 +93,240 @@ Array InputMap::_get_actions() {
}
List<StringName> InputMap::get_actions() const {
List<StringName> actions = List<StringName>();
if (input_map.empty()) {
if(input_map.empty()){
return actions;
}
for (Map<StringName, Action>::Element *E = input_map.front(); E; E = E->next()) {
for (Map<StringName, Action>::Element *E=input_map.front();E;E=E->next()) {
actions.push_back(E->key());
}
return actions;
}
List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match, bool *p_pressed, float *p_strength, float *p_raw_strength) const {
ERR_FAIL_COND_V(!p_event.is_valid(), nullptr);
List<InputEvent>::Element *InputMap::_find_event(List<InputEvent> &p_list,const InputEvent& p_event) const {
for (List<Ref<InputEvent>>::Element *E = p_action.inputs.front(); E; E = E->next()) {
const Ref<InputEvent> e = E->get();
for (List<InputEvent>::Element *E=p_list.front();E;E=E->next()) {
//if (e.type != Ref<InputEvent>::KEY && e.device != p_event.device) -- unsure about the KEY comparison, why is this here?
// continue;
const InputEvent& e=E->get();
if(e.type!=p_event.type)
continue;
if (e.type!=InputEvent::KEY && e.device!=p_event.device)
continue;
int device = e->get_device();
if (device == ALL_DEVICES || device == p_event->get_device()) {
if (p_exact_match && e->shortcut_match(p_event)) {
return E;
} else if (!p_exact_match && e->action_match(p_event, p_pressed, p_strength, p_raw_strength, p_action.deadzone)) {
return E;
}
bool same=false;
switch(p_event.type) {
case InputEvent::KEY: {
same=(e.key.scancode==p_event.key.scancode && e.key.mod == p_event.key.mod);
} break;
case InputEvent::JOYSTICK_BUTTON: {
same=(e.joy_button.button_index==p_event.joy_button.button_index);
} break;
case InputEvent::MOUSE_BUTTON: {
same=(e.mouse_button.button_index==p_event.mouse_button.button_index);
} break;
case InputEvent::JOYSTICK_MOTION: {
same=(e.joy_motion.axis==p_event.joy_motion.axis && (e.joy_motion.axis_value < 0) == (p_event.joy_motion.axis_value < 0));
} break;
}
if (same)
return E;
}
return nullptr;
return NULL;
}
bool InputMap::has_action(const StringName &p_action) const {
bool InputMap::has_action(const StringName& p_action) const {
return input_map.has(p_action);
}
float InputMap::action_get_deadzone(const StringName &p_action) {
ERR_FAIL_COND_V_MSG(!input_map.has(p_action), 0.0f, suggest_actions(p_action));
void InputMap::action_add_event(const StringName& p_action,const InputEvent& p_event) {
return input_map[p_action].deadzone;
}
void InputMap::action_set_deadzone(const StringName &p_action, float p_deadzone) {
ERR_FAIL_COND_MSG(!input_map.has(p_action), suggest_actions(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_MSG(p_event.is_null(), "It's not a reference to a valid InputEvent object.");
ERR_FAIL_COND_MSG(!input_map.has(p_action), suggest_actions(p_action));
if (_find_event(input_map[p_action], p_event, true)) {
return; // Already added.
}
ERR_FAIL_COND(p_event.type==InputEvent::ACTION);
ERR_FAIL_COND( !input_map.has(p_action) );
if (_find_event(input_map[p_action].inputs,p_event))
return; //already gots
input_map[p_action].inputs.push_back(p_event);
}
bool InputMap::action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
ERR_FAIL_COND_V_MSG(!input_map.has(p_action), false, suggest_actions(p_action));
return (_find_event(input_map[p_action], p_event, true) != nullptr);
int InputMap::get_action_id(const StringName& p_action) const {
ERR_FAIL_COND_V(!input_map.has(p_action),-1);
return input_map[p_action].id;
}
void InputMap::action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
ERR_FAIL_COND_MSG(!input_map.has(p_action), suggest_actions(p_action));
bool InputMap::action_has_event(const StringName& p_action,const InputEvent& p_event) {
List<Ref<InputEvent>>::Element *E = _find_event(input_map[p_action], p_event, true);
if (E) {
ERR_FAIL_COND_V( !input_map.has(p_action), false );
return (_find_event(input_map[p_action].inputs,p_event)!=NULL);
}
void InputMap::action_erase_event(const StringName& p_action,const InputEvent& p_event) {
ERR_FAIL_COND( !input_map.has(p_action) );
List<InputEvent>::Element *E=_find_event(input_map[p_action].inputs,p_event);
if (E)
input_map[p_action].inputs.erase(E);
if (Input::get_singleton()->is_action_pressed(p_action)) {
Input::get_singleton()->action_release(p_action);
}
}
}
void InputMap::action_erase_events(const StringName &p_action) {
ERR_FAIL_COND_MSG(!input_map.has(p_action), suggest_actions(p_action));
input_map[p_action].inputs.clear();
}
Array InputMap::_get_action_list(const StringName& p_action) {
Array InputMap::_get_action_list(const StringName &p_action) {
Array ret;
const List<Ref<InputEvent>> *al = get_action_list(p_action);
const List<InputEvent> *al = get_action_list(p_action);
if (al) {
for (const List<Ref<InputEvent>>::Element *E = al->front(); E; E = E->next()) {
ret.push_back(E->get());
for(const List<InputEvent>::Element *E=al->front();E;E=E->next()) {
ret.push_back(E->get());;
}
}
return ret;
}
const List<Ref<InputEvent>> *InputMap::get_action_list(const StringName &p_action) {
const Map<StringName, Action>::Element *E = input_map.find(p_action);
if (!E) {
return nullptr;
}
const List<InputEvent> *InputMap::get_action_list(const StringName& p_action) {
const Map<StringName, Action>::Element *E=input_map.find(p_action);
if (!E)
return NULL;
return &E->get().inputs;
}
bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match) const {
return event_get_action_status(p_event, p_action, p_exact_match);
}
bool InputMap::event_is_action(const InputEvent& p_event, const StringName& p_action) const {
bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match, bool *p_pressed, float *p_strength, float *p_raw_strength) const {
Map<StringName, Action>::Element *E = input_map.find(p_action);
ERR_FAIL_COND_V_MSG(!E, false, suggest_actions(p_action));
Ref<InputEventAction> input_event_action = p_event;
if (input_event_action.is_valid()) {
bool pressed = input_event_action->is_pressed();
if (p_pressed != nullptr) {
*p_pressed = pressed;
}
if (p_strength != nullptr) {
*p_strength = pressed ? input_event_action->get_strength() : 0.0f;
}
return input_event_action->get_action() == p_action;
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);
}
bool pressed;
float strength;
float raw_strength;
List<Ref<InputEvent>>::Element *event = _find_event(E->get(), p_event, p_exact_match, &pressed, &strength, &raw_strength);
if (event != nullptr) {
if (p_pressed != nullptr) {
*p_pressed = pressed;
}
if (p_strength != nullptr) {
*p_strength = strength;
}
if (p_raw_strength != nullptr) {
*p_raw_strength = raw_strength;
}
return true;
} else {
return false;
}
}
if (p_event.type==InputEvent::ACTION) {
const Map<StringName, InputMap::Action> &InputMap::get_action_map() const {
return input_map;
return p_event.action.action==E->get().id;
}
return _find_event(E->get().inputs,p_event)!=NULL;
}
void InputMap::load_from_globals() {
input_map.clear();
input_map.clear();;
List<PropertyInfo> pinfo;
ProjectSettings::get_singleton()->get_property_list(&pinfo);
Globals::get_singleton()->get_property_list(&pinfo);
for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
const PropertyInfo &pi = E->get();
for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
const PropertyInfo &pi=E->get();
if (!pi.name.begins_with("input/")) {
if (!pi.name.begins_with("input/"))
continue;
}
String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length());
String name = pi.name.substr(pi.name.find("/")+1,pi.name.length());
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 = Globals::get_singleton()->get(pi.name);;
for(int i=0;i<va.size();i++) {
InputEvent ie=va[i];
if (ie.type==InputEvent::NONE)
continue;
}
action_add_event(name, event);
action_add_event(name,ie);
}
}
}
void InputMap::load_default() {
Ref<InputEventKey> key;
InputEvent key;
key.type=InputEvent::KEY;
add_action("ui_accept");
key.instance();
key->set_scancode(KEY_ENTER);
action_add_event("ui_accept", key);
key.instance();
key->set_scancode(KEY_KP_ENTER);
action_add_event("ui_accept", key);
key.instance();
key->set_scancode(KEY_SPACE);
action_add_event("ui_accept", key);
key.key.scancode=KEY_RETURN;
action_add_event("ui_accept",key);
key.key.scancode=KEY_ENTER;
action_add_event("ui_accept",key);
key.key.scancode=KEY_SPACE;
action_add_event("ui_accept",key);
add_action("ui_select");
key.instance();
key->set_scancode(KEY_SPACE);
action_add_event("ui_select", key);
key.key.scancode=KEY_SPACE;
action_add_event("ui_select",key);
add_action("ui_cancel");
key.instance();
key->set_scancode(KEY_ESCAPE);
action_add_event("ui_cancel", key);
key.key.scancode=KEY_ESCAPE;
action_add_event("ui_cancel",key);
add_action("ui_focus_next");
key.instance();
key->set_scancode(KEY_TAB);
action_add_event("ui_focus_next", key);
key.key.scancode=KEY_TAB;
action_add_event("ui_focus_next",key);
add_action("ui_focus_prev");
key.instance();
key->set_scancode(KEY_TAB);
key->set_shift(true);
action_add_event("ui_focus_prev", key);
key.key.scancode=KEY_TAB;
key.key.mod.shift=true;
action_add_event("ui_focus_prev",key);
key.key.mod.shift=false;
add_action("ui_left");
key.instance();
key->set_scancode(KEY_LEFT);
action_add_event("ui_left", key);
key.key.scancode=KEY_LEFT;
action_add_event("ui_left",key);
add_action("ui_right");
key.instance();
key->set_scancode(KEY_RIGHT);
action_add_event("ui_right", key);
key.key.scancode=KEY_RIGHT;
action_add_event("ui_right",key);
add_action("ui_up");
key.instance();
key->set_scancode(KEY_UP);
action_add_event("ui_up", key);
key.key.scancode=KEY_UP;
action_add_event("ui_up",key);
add_action("ui_down");
key.instance();
key->set_scancode(KEY_DOWN);
action_add_event("ui_down", key);
key.key.scancode=KEY_DOWN;
action_add_event("ui_down",key);
add_action("ui_page_up");
key.instance();
key->set_scancode(KEY_PAGEUP);
action_add_event("ui_page_up", key);
key.key.scancode=KEY_PAGEUP;
action_add_event("ui_page_up",key);
add_action("ui_page_down");
key.instance();
key->set_scancode(KEY_PAGEDOWN);
action_add_event("ui_page_down", key);
key.key.scancode=KEY_PAGEDOWN;
action_add_event("ui_page_down",key);
// set("display/orientation", "landscape");
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);
}
InputMap::InputMap() {
ERR_FAIL_COND_MSG(singleton, "Singleton in InputMap already exist.");
singleton = this;
ERR_FAIL_COND(singleton);
singleton=this;
}

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,66 +26,55 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef INPUT_MAP_H
#define INPUT_MAP_H
#include "core/object.h"
#include "core/os/input_event.h"
#include "object.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;
OBJ_TYPE( InputMap, Object );
static InputMap *singleton;
struct Action {
int id;
float deadzone;
List<Ref<InputEvent>> inputs;
List<InputEvent> inputs;
};
private:
static InputMap *singleton;
mutable Map<StringName, Action> input_map;
mutable Map<int,StringName> input_id_map;
List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match = false, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
List<InputEvent>::Element *_find_event(List<InputEvent> &p_list,const InputEvent& p_event) const;
Array _get_action_list(const StringName &p_action);
Array _get_action_list(const StringName& p_action);
Array _get_actions();
protected:
static void _bind_methods();
static void _bind_methods();
public:
static _FORCE_INLINE_ InputMap *get_singleton() { return singleton; }
bool has_action(const StringName &p_action) const;
bool has_action(const StringName& p_action) const;
int get_action_id(const StringName& p_action) const;
StringName get_action_from_id(int p_id) const;
List<StringName> get_actions() const;
void add_action(const StringName &p_action, float p_deadzone = 0.5);
void erase_action(const StringName &p_action);
void add_action(const StringName& p_action);
void erase_action(const StringName& p_action);
float action_get_deadzone(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);
void action_add_event(const StringName& p_action,const InputEvent& p_event);
bool action_has_event(const StringName& p_action,const InputEvent& p_event);
void action_erase_event(const StringName& p_action,const InputEvent& p_event);
const List<InputEvent> *get_action_list(const StringName& p_action);
bool event_is_action(const InputEvent& p_event, const StringName& p_action) const;
const List<Ref<InputEvent>> *get_action_list(const StringName &p_action);
bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false) const;
bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
const Map<StringName, Action> &get_action_map() const;
void load_from_globals();
void load_default();
String suggest_actions(const StringName &p_action) const;
InputMap();
};

View File

@@ -3,10 +3,9 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,25 +29,25 @@
#ifdef _MSC_VER
typedef signed __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef signed __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef signed __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
typedef signed __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef signed __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef signed __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
#ifdef NO_STDINT_H
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned int uint32_t;
typedef signed int int32_t;
typedef long long int64_t;
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned int uint32_t;
typedef signed int int32_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
#else
#include <stdint.h>

View File

@@ -0,0 +1,60 @@
This is version 2007-Mar-4 of the Info-ZIP license.
The definitive version of this document should be available at
ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely and
a copy at http://www.info-zip.org/pub/infozip/license.html.
Copyright (c) 1990-2007 Info-ZIP. All rights reserved.
For the purposes of this copyright and license, "Info-ZIP" is defined as
the following set of individuals:
Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,
Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth,
Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz,
David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko,
Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,
Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda,
Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren,
Rich Wales, Mike White.
This software is provided "as is," without warranty of any kind, express
or implied. In no event shall Info-ZIP or its contributors be held liable
for any direct, indirect, incidental, special or consequential damages
arising out of the use of or inability to use this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the above disclaimer and the following restrictions:
1. Redistributions of source code (in whole or in part) must retain
the above copyright notice, definition, disclaimer, and this list
of conditions.
2. Redistributions in binary form (compiled executables and libraries)
must reproduce the above copyright notice, definition, disclaimer,
and this list of conditions in documentation and/or other materials
provided with the distribution. The sole exception to this condition
is redistribution of a standard UnZipSFX binary (including SFXWiz) as
part of a self-extracting archive; that is permitted without inclusion
of this license, as long as the normal SFX banner has not been removed
from the binary or disabled.
3. Altered versions--including, but not limited to, ports to new operating
systems, existing ports with new graphical interfaces, versions with
modified or added functionality, and dynamic, shared, or static library
versions not from Info-ZIP--must be plainly marked as such and must not
be misrepresented as being the original source or, if binaries,
compiled from the original source. Such altered versions also must not
be misrepresented as being Info-ZIP releases--including, but not
limited to, labeling of the altered versions with the names "Info-ZIP"
(or any variation thereof, including, but not limited to, different
capitalizations), "Pocket UnZip," "WiZ" or "MacZip" without the
explicit permission of Info-ZIP. Such altered versions are further
prohibited from misrepresentative use of the Zip-Bugs or Info-ZIP
e-mail addresses or the Info-ZIP URL(s), such as to imply Info-ZIP
will provide support for the altered versions.
4. Info-ZIP retains the right to use the names "Info-ZIP," "Zip," "UnZip,"
"UnZipSFX," "WiZ," "Pocket UnZip," "Pocket Zip," and "MacZip" for its
own source and binary releases.

View File

@@ -0,0 +1,32 @@
Credits
Gilles Vollant - Original MiniZip author
Even Rouault - ZIP64 unzip Support
Daniel Borca - BZip Compression method support in unzip
Mathias Svensson - ZIP64 zip support
Mathias Svensson - BZip Compression method support in zip
This version has been modified for Godot Engine
License
----------------------------------------------------------------------------
Condition of use and distribution are the same than zlib :
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
----------------------------------------------------------------------------

View File

@@ -1,5 +1,9 @@
#!/usr/bin/env python
Import("env")
Import('env')
env.add_source_files(env.core_sources, "*.cpp")
env.add_source_files(env.core_sources, "*.c")
# env.core_sources.append("io/fastlz.c")
Export('env')

399
core/io/aes256.cpp Normal file
View File

@@ -0,0 +1,399 @@
/*
* Byte-oriented AES-256 implementation.
* All lookup tables replaced with 'on the fly' calculations.
*
* Copyright (c) 2007-2011 Ilya O. Levin, http://www.literatecode.com
* Other contributors: Hal Finney
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "aes256.h"
#define FD(x) (((x) >> 1) ^ (((x) & 1) ? 0x8d : 0))
#define BACK_TO_TABLES
static uint8_t rj_xtime(uint8_t);
static void aes_subBytes(uint8_t *);
static void aes_subBytes_inv(uint8_t *);
static void aes_addRoundKey(uint8_t *, uint8_t *);
static void aes_addRoundKey_cpy(uint8_t *, uint8_t *, uint8_t *);
static void aes_shiftRows(uint8_t *);
static void aes_shiftRows_inv(uint8_t *);
static void aes_mixColumns(uint8_t *);
static void aes_mixColumns_inv(uint8_t *);
static void aes_expandEncKey(uint8_t *, uint8_t *);
static void aes_expandDecKey(uint8_t *, uint8_t *);
#ifndef BACK_TO_TABLES
static uint8_t gf_alog(uint8_t);
static uint8_t gf_log(uint8_t);
static uint8_t gf_mulinv(uint8_t);
static uint8_t rj_sbox(uint8_t);
static uint8_t rj_sbox_inv(uint8_t);
#endif
#ifdef BACK_TO_TABLES
static const uint8_t sbox[256] =
{
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};
static const uint8_t sboxinv[256] =
{
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};
#define rj_sbox(x) sbox[(x)]
#define rj_sbox_inv(x) sboxinv[(x)]
#else /* tableless subroutines */
/* -------------------------------------------------------------------------- */
static uint8_t gf_alog(uint8_t x) // calculate anti-logarithm gen 3
{
uint8_t y = 1, i;
for (i = 0; i < x; i++) y ^= rj_xtime(y);
return y;
} /* gf_alog */
/* -------------------------------------------------------------------------- */
static uint8_t gf_log(uint8_t x) // calculate logarithm gen 3
{
uint8_t y, i = 0;
if (x)
for (i = 1, y = 1; i > 0; i++ )
{
y ^= rj_xtime(y);
if (y == x) break;
}
return i;
} /* gf_log */
/* -------------------------------------------------------------------------- */
static uint8_t gf_mulinv(uint8_t x) // calculate multiplicative inverse
{
return (x) ? gf_alog(255 - gf_log(x)) : 0;
} /* gf_mulinv */
/* -------------------------------------------------------------------------- */
static uint8_t rj_sbox(uint8_t x)
{
uint8_t y, sb;
sb = y = gf_mulinv(x);
y = (uint8_t)(y << 1) | (y >> 7), sb ^= y;
y = (uint8_t)(y << 1) | (y >> 7), sb ^= y;
y = (uint8_t)(y << 1) | (y >> 7), sb ^= y;
y = (uint8_t)(y << 1) | (y >> 7), sb ^= y;
return (sb ^ 0x63);
} /* rj_sbox */
/* -------------------------------------------------------------------------- */
static uint8_t rj_sbox_inv(uint8_t x)
{
uint8_t y, sb;
y = x ^ 0x63;
sb = y = (uint8_t)(y << 1) | (y >> 7);
y = (uint8_t)(y << 2) | (y >> 6);
sb ^= y;
y = (uint8_t)(y << 3) | (y >> 5);
sb ^= y;
return gf_mulinv(sb);
} /* rj_sbox_inv */
#endif
/* -------------------------------------------------------------------------- */
static uint8_t rj_xtime(uint8_t x)
{
uint8_t y = (uint8_t)(x << 1);
return (x & 0x80) ? (y ^ 0x1b) : y;
} /* rj_xtime */
/* -------------------------------------------------------------------------- */
static void aes_subBytes(uint8_t *buf)
{
register uint8_t i = 16;
while (i--) buf[i] = rj_sbox(buf[i]);
} /* aes_subBytes */
/* -------------------------------------------------------------------------- */
static void aes_subBytes_inv(uint8_t *buf)
{
register uint8_t i = 16;
while (i--) buf[i] = rj_sbox_inv(buf[i]);
} /* aes_subBytes_inv */
/* -------------------------------------------------------------------------- */
static void aes_addRoundKey(uint8_t *buf, uint8_t *key)
{
register uint8_t i = 16;
while (i--) buf[i] ^= key[i];
} /* aes_addRoundKey */
/* -------------------------------------------------------------------------- */
static void aes_addRoundKey_cpy(uint8_t *buf, uint8_t *key, uint8_t *cpk)
{
register uint8_t i = 16;
while (i--) buf[i] ^= (cpk[i] = key[i]), cpk[16 + i] = key[16 + i];
} /* aes_addRoundKey_cpy */
/* -------------------------------------------------------------------------- */
static void aes_shiftRows(uint8_t *buf)
{
register uint8_t i, j; /* to make it potentially parallelable :) */
i = buf[1], buf[1] = buf[5], buf[5] = buf[9], buf[9] = buf[13], buf[13] = i;
i = buf[10], buf[10] = buf[2], buf[2] = i;
j = buf[3], buf[3] = buf[15], buf[15] = buf[11], buf[11] = buf[7], buf[7] = j;
j = buf[14], buf[14] = buf[6], buf[6] = j;
} /* aes_shiftRows */
/* -------------------------------------------------------------------------- */
static void aes_shiftRows_inv(uint8_t *buf)
{
register uint8_t i, j; /* same as above :) */
i = buf[1], buf[1] = buf[13], buf[13] = buf[9], buf[9] = buf[5], buf[5] = i;
i = buf[2], buf[2] = buf[10], buf[10] = i;
j = buf[3], buf[3] = buf[7], buf[7] = buf[11], buf[11] = buf[15], buf[15] = j;
j = buf[6], buf[6] = buf[14], buf[14] = j;
} /* aes_shiftRows_inv */
/* -------------------------------------------------------------------------- */
static void aes_mixColumns(uint8_t *buf)
{
register uint8_t i, a, b, c, d, e;
for (i = 0; i < 16; i += 4)
{
a = buf[i];
b = buf[i + 1];
c = buf[i + 2];
d = buf[i + 3];
e = a ^ b ^ c ^ d;
buf[i] ^= e ^ rj_xtime(a ^ b);
buf[i + 1] ^= e ^ rj_xtime(b ^ c);
buf[i + 2] ^= e ^ rj_xtime(c ^ d);
buf[i + 3] ^= e ^ rj_xtime(d ^ a);
}
} /* aes_mixColumns */
/* -------------------------------------------------------------------------- */
void aes_mixColumns_inv(uint8_t *buf)
{
register uint8_t i, a, b, c, d, e, x, y, z;
for (i = 0; i < 16; i += 4)
{
a = buf[i];
b = buf[i + 1];
c = buf[i + 2];
d = buf[i + 3];
e = a ^ b ^ c ^ d;
z = rj_xtime(e);
x = e ^ rj_xtime(rj_xtime(z ^ a ^ c));
y = e ^ rj_xtime(rj_xtime(z ^ b ^ d));
buf[i] ^= x ^ rj_xtime(a ^ b);
buf[i + 1] ^= y ^ rj_xtime(b ^ c);
buf[i + 2] ^= x ^ rj_xtime(c ^ d);
buf[i + 3] ^= y ^ rj_xtime(d ^ a);
}
} /* aes_mixColumns_inv */
/* -------------------------------------------------------------------------- */
static void aes_expandEncKey(uint8_t *k, uint8_t *rc)
{
register uint8_t i;
k[0] ^= rj_sbox(k[29]) ^ (*rc);
k[1] ^= rj_sbox(k[30]);
k[2] ^= rj_sbox(k[31]);
k[3] ^= rj_sbox(k[28]);
*rc = rj_xtime( *rc);
for(i = 4; i < 16; i += 4) k[i] ^= k[i - 4], k[i + 1] ^= k[i - 3],
k[i + 2] ^= k[i - 2], k[i + 3] ^= k[i - 1];
k[16] ^= rj_sbox(k[12]);
k[17] ^= rj_sbox(k[13]);
k[18] ^= rj_sbox(k[14]);
k[19] ^= rj_sbox(k[15]);
for(i = 20; i < 32; i += 4) k[i] ^= k[i - 4], k[i + 1] ^= k[i - 3],
k[i + 2] ^= k[i - 2], k[i + 3] ^= k[i - 1];
} /* aes_expandEncKey */
/* -------------------------------------------------------------------------- */
void aes_expandDecKey(uint8_t *k, uint8_t *rc)
{
uint8_t i;
for(i = 28; i > 16; i -= 4) k[i + 0] ^= k[i - 4], k[i + 1] ^= k[i - 3],
k[i + 2] ^= k[i - 2], k[i + 3] ^= k[i - 1];
k[16] ^= rj_sbox(k[12]);
k[17] ^= rj_sbox(k[13]);
k[18] ^= rj_sbox(k[14]);
k[19] ^= rj_sbox(k[15]);
for(i = 12; i > 0; i -= 4) k[i + 0] ^= k[i - 4], k[i + 1] ^= k[i - 3],
k[i + 2] ^= k[i - 2], k[i + 3] ^= k[i - 1];
*rc = FD(*rc);
k[0] ^= rj_sbox(k[29]) ^ (*rc);
k[1] ^= rj_sbox(k[30]);
k[2] ^= rj_sbox(k[31]);
k[3] ^= rj_sbox(k[28]);
} /* aes_expandDecKey */
/* -------------------------------------------------------------------------- */
void aes256_init(aes256_context *ctx, uint8_t *k)
{
uint8_t rcon = 1;
register uint8_t i;
for (i = 0; i < sizeof(ctx->key); i++) ctx->enckey[i] = ctx->deckey[i] = k[i];
for (i = 8; --i;) aes_expandEncKey(ctx->deckey, &rcon);
} /* aes256_init */
/* -------------------------------------------------------------------------- */
void aes256_done(aes256_context *ctx)
{
register uint8_t i;
for (i = 0; i < sizeof(ctx->key); i++)
ctx->key[i] = ctx->enckey[i] = ctx->deckey[i] = 0;
} /* aes256_done */
/* -------------------------------------------------------------------------- */
void aes256_encrypt_ecb(aes256_context *ctx, uint8_t *buf)
{
uint8_t i, rcon;
aes_addRoundKey_cpy(buf, ctx->enckey, ctx->key);
for(i = 1, rcon = 1; i < 14; ++i)
{
aes_subBytes(buf);
aes_shiftRows(buf);
aes_mixColumns(buf);
if( i & 1 ) aes_addRoundKey( buf, &ctx->key[16]);
else aes_expandEncKey(ctx->key, &rcon), aes_addRoundKey(buf, ctx->key);
}
aes_subBytes(buf);
aes_shiftRows(buf);
aes_expandEncKey(ctx->key, &rcon);
aes_addRoundKey(buf, ctx->key);
} /* aes256_encrypt */
/* -------------------------------------------------------------------------- */
void aes256_decrypt_ecb(aes256_context *ctx, uint8_t *buf)
{
uint8_t i, rcon;
aes_addRoundKey_cpy(buf, ctx->deckey, ctx->key);
aes_shiftRows_inv(buf);
aes_subBytes_inv(buf);
for (i = 14, rcon = 0x80; --i;)
{
if( ( i & 1 ) )
{
aes_expandDecKey(ctx->key, &rcon);
aes_addRoundKey(buf, &ctx->key[16]);
}
else aes_addRoundKey(buf, ctx->key);
aes_mixColumns_inv(buf);
aes_shiftRows_inv(buf);
aes_subBytes_inv(buf);
}
aes_addRoundKey( buf, ctx->key);
} /* aes256_decrypt */

46
core/io/aes256.h Normal file
View File

@@ -0,0 +1,46 @@
/*
* Byte-oriented AES-256 implementation.
* All lookup tables replaced with 'on the fly' calculations.
*
* Copyright (c) 2007-2009 Ilya O. Levin, http://www.literatecode.com
* Other contributors: Hal Finney
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef AES_256_H
#define AES_256_H
#include "typedefs.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint8_t key[32];
uint8_t enckey[32];
uint8_t deckey[32];
} aes256_context;
void aes256_init(aes256_context *, uint8_t * /* key */);
void aes256_done(aes256_context *);
void aes256_encrypt_ecb(aes256_context *, uint8_t * /* plaintext */);
void aes256_decrypt_ecb(aes256_context *, uint8_t * /* cipertext */);
#ifdef __cplusplus
}
#endif
#endif

110
core/io/base64.c Normal file
View File

@@ -0,0 +1,110 @@
#include <string.h>
char b64string[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
long base64_encode (to, from, len)
char *to, *from;
unsigned int len;
{
char *fromp = from;
char *top = to;
unsigned char cbyte;
unsigned char obyte;
char end[3];
for (; len >= 3; len -= 3) {
cbyte = *fromp++;
*top++ = b64string[(int)(cbyte >> 2)];
obyte = (cbyte << 4) & 0x30; /* 0011 0000 */
cbyte = *fromp++;
obyte |= (cbyte >> 4); /* 0000 1111 */
*top++ = b64string[(int)obyte];
obyte = (cbyte << 2) & 0x3C; /* 0011 1100 */
cbyte = *fromp++;
obyte |= (cbyte >> 6); /* 0000 0011 */
*top++ = b64string[(int)obyte];
*top++ = b64string[(int)(cbyte & 0x3F)];/* 0011 1111 */
}
if (len) {
end[0] = *fromp++;
if (--len) end[1] = *fromp++; else end[1] = 0;
end[2] = 0;
cbyte = end[0];
*top++ = b64string[(int)(cbyte >> 2)];
obyte = (cbyte << 4) & 0x30; /* 0011 0000 */
cbyte = end[1];
obyte |= (cbyte >> 4);
*top++ = b64string[(int)obyte];
obyte = (cbyte << 2) & 0x3C; /* 0011 1100 */
if (len) *top++ = b64string[(int)obyte];
else *top++ = '=';
*top++ = '=';
}
*top = 0;
return top - to;
}
/* badchar(): check if c is decent; puts either the */
/* location of c or null into p. */
#define badchar(c,p) (!(p = memchr(b64string, c, 64)))
long base64_decode (to, from, len)
char *to, *from;
unsigned int len;
{
char *fromp = from;
char *top = to;
char *p;
unsigned char cbyte;
unsigned char obyte;
int padding = 0;
for (; len >= 4; len -= 4) {
if ((cbyte = *fromp++) == '=') cbyte = 0;
else {
if (badchar(cbyte, p)) return -1;
cbyte = (p - b64string);
}
obyte = cbyte << 2; /* 1111 1100 */
if ((cbyte = *fromp++) == '=') cbyte = 0;
else {
if (badchar(cbyte, p)) return -1;
cbyte = p - b64string;
}
obyte |= cbyte >> 4; /* 0000 0011 */
*top++ = obyte;
obyte = cbyte << 4; /* 1111 0000 */
if ((cbyte = *fromp++) == '=') { cbyte = 0; padding++; }
else {
padding = 0;
if (badchar (cbyte, p)) return -1;
cbyte = p - b64string;
}
obyte |= cbyte >> 2; /* 0000 1111 */
*top++ = obyte;
obyte = cbyte << 6; /* 1100 0000 */
if ((cbyte = *fromp++) == '=') { cbyte = 0; padding++; }
else {
padding = 0;
if (badchar (cbyte, p)) return -1;
cbyte = p - b64string;
}
obyte |= cbyte; /* 0011 1111 */
*top++ = obyte;
}
*top = 0;
if (len) return -1;
return (top - to) - padding;
}

11
core/io/base64.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef BASE64_H
#define BASE64_H
extern "C" {
uint32_t base64_encode (char* to, char* from, uint32_t len);
uint32_t base64_decode (char* to, char* from, uint32_t len);
};
#endif /* BASE64_H */

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