summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-format5
-rw-r--r--.gitignore3
-rw-r--r--AUTHORS.md10
-rw-r--r--DONORS.md42
-rw-r--r--core/class_db.cpp19
-rw-r--r--core/class_db.h2
-rw-r--r--core/io/json.cpp6
-rw-r--r--core/io/json.h4
-rw-r--r--core/math/a_star.cpp4
-rw-r--r--core/math/math_2d.cpp29
-rw-r--r--core/math/math_2d.h5
-rw-r--r--core/os/os.h4
-rw-r--r--core/variant_call.cpp2
-rw-r--r--doc/classes/AStar.xml4
-rw-r--r--doc/classes/Animation.xml28
-rw-r--r--doc/classes/AnimationPlayer.xml40
-rw-r--r--doc/classes/AnimationTreePlayer.xml90
-rw-r--r--doc/classes/Array.xml10
-rw-r--r--doc/classes/CanvasItem.xml28
-rw-r--r--doc/classes/ConcavePolygonShape2D.xml1
-rw-r--r--doc/classes/CubeMap.xml29
-rw-r--r--doc/classes/EditorFileSystem.xml2
-rw-r--r--doc/classes/EditorPlugin.xml22
-rw-r--r--doc/classes/EditorResourceConversionPlugin.xml2
-rw-r--r--doc/classes/EditorSceneImporter.xml95
-rw-r--r--doc/classes/FileDialog.xml3
-rw-r--r--doc/classes/HTTPClient.xml104
-rw-r--r--doc/classes/HTTPRequest.xml23
-rw-r--r--doc/classes/IP.xml14
-rw-r--r--doc/classes/IP_Unix.xml2
-rw-r--r--doc/classes/KinematicBody.xml12
-rw-r--r--doc/classes/Mesh.xml4
-rw-r--r--doc/classes/MeshInstance.xml7
-rw-r--r--doc/classes/Node.xml2
-rw-r--r--doc/classes/PhysicsServer.xml40
-rw-r--r--doc/classes/PopupMenu.xml32
-rw-r--r--doc/classes/Rect2.xml6
-rw-r--r--doc/classes/RigidBody.xml21
-rw-r--r--doc/classes/SurfaceTool.xml2
-rw-r--r--doc/classes/TextEdit.xml11
-rw-r--r--doc/classes/Texture.xml10
-rw-r--r--doc/classes/TileMap.xml32
-rw-r--r--doc/classes/TileSet.xml4
-rw-r--r--doc/classes/VisualServer.xml284
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp23
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp16
-rw-r--r--drivers/gles3/shaders/particles.glsl2
-rw-r--r--drivers/unix/os_unix.cpp34
-rw-r--r--editor/animation_editor.cpp25
-rw-r--r--editor/editor_help.cpp5
-rw-r--r--editor/editor_node.cpp4
-rw-r--r--editor/editor_plugin.cpp5
-rw-r--r--editor/editor_plugin.h2
-rw-r--r--editor/editor_run.cpp9
-rw-r--r--editor/editor_settings.cpp2
-rw-r--r--editor/editor_themes.cpp7
-rw-r--r--editor/filesystem_dock.cpp104
-rw-r--r--editor/filesystem_dock.h6
-rw-r--r--editor/icons/icon_GUI_visibility_hidden.svg55
-rw-r--r--editor/icons/icon_GUI_visibility_visible.svg63
-rw-r--r--editor/icons/icon_GUI_visibility_xray.svg61
-rw-r--r--editor/import/editor_import_collada.cpp2
-rw-r--r--editor/import/editor_import_collada.h2
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp5
-rw-r--r--editor/import/editor_scene_importer_gltf.h2
-rw-r--r--editor/import/resource_importer_obj.h2
-rw-r--r--editor/import/resource_importer_scene.cpp173
-rw-r--r--editor/import/resource_importer_scene.h15
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp8
-rw-r--r--editor/plugins/asset_library_editor_plugin.h1
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp61
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h1
-rw-r--r--editor/plugins/mesh_instance_editor_plugin.cpp145
-rw-r--r--editor/plugins/mesh_instance_editor_plugin.h10
-rw-r--r--editor/plugins/script_text_editor.cpp25
-rw-r--r--editor/plugins/script_text_editor.h3
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp47
-rw-r--r--editor/plugins/spatial_editor_plugin.h8
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp2
-rw-r--r--editor/property_editor.cpp68
-rw-r--r--editor/property_selector.cpp18
-rw-r--r--editor/scene_tree_editor.cpp3
-rw-r--r--editor/spatial_editor_gizmos.cpp28
-rw-r--r--main/input_default.cpp81
-rw-r--r--main/main.cpp4
-rw-r--r--main/splash_sponsors.pngbin0 -> 39571 bytes
-rwxr-xr-xmisc/hooks/pre-commit-clang-format2
-rwxr-xr-xmisc/travis/clang-format.sh2
-rw-r--r--modules/bullet/bullet_physics_server.cpp10
-rw-r--r--modules/bullet/bullet_physics_server.h4
-rw-r--r--modules/bullet/godot_result_callbacks.h9
-rw-r--r--modules/bullet/rigid_body_bullet.cpp56
-rw-r--r--modules/bullet/rigid_body_bullet.h7
-rw-r--r--modules/bullet/space_bullet.cpp2
-rw-r--r--modules/gdnative/register_types.cpp7
-rw-r--r--modules/gdscript/gdscript_function.cpp4
-rw-r--r--modules/gdscript/gdscript_parser.cpp4
-rw-r--r--modules/thekla_unwrap/SCsub3
-rw-r--r--modules/thekla_unwrap/register_types.cpp85
-rw-r--r--modules/visual_script/visual_script.cpp1
-rw-r--r--platform/android/export/export.cpp11
-rw-r--r--platform/android/java/src/org/godotengine/godot/Dictionary.java7
-rw-r--r--platform/android/java/src/org/godotengine/godot/Godot.java812
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java18
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java55
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotIO.java273
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotLib.java56
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java25
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotView.java261
-rw-r--r--platform/android/java/src/org/godotengine/godot/input/GodotEditText.java61
-rw-r--r--platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java3
-rw-r--r--platform/android/java/src/org/godotengine/godot/input/InputManagerCompat.java204
-rw-r--r--platform/android/java/src/org/godotengine/godot/input/InputManagerV16.java144
-rw-r--r--platform/android/java/src/org/godotengine/godot/input/InputManagerV9.java352
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java38
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/GenericConsumeTask.java20
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java30
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/PaymentsCache.java45
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java87
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/PurchaseTask.java38
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java46
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/ValidateTask.java36
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/Crypt.java46
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java31
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java207
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/RequestParams.java34
-rw-r--r--platform/haiku/os_haiku.cpp1
-rw-r--r--platform/iphone/app_delegate.mm133
-rw-r--r--platform/iphone/in_app_store.mm8
-rw-r--r--platform/osx/os_osx.mm2
-rw-r--r--platform/uwp/os_uwp.cpp1
-rw-r--r--platform/windows/export/export.cpp126
-rw-r--r--platform/windows/os_windows.cpp2
-rw-r--r--platform/x11/os_x11.cpp46
-rw-r--r--platform/x11/os_x11.h1
-rw-r--r--scene/2d/canvas_item.cpp25
-rw-r--r--scene/2d/canvas_item.h2
-rw-r--r--scene/2d/path_2d.cpp75
-rw-r--r--scene/2d/path_2d.h5
-rw-r--r--scene/2d/tile_map.cpp52
-rw-r--r--scene/2d/tile_map.h12
-rw-r--r--scene/3d/gi_probe.cpp7
-rw-r--r--scene/3d/particles.cpp4
-rw-r--r--scene/3d/physics_body.cpp72
-rw-r--r--scene/3d/physics_body.h19
-rw-r--r--scene/animation/animation_player.cpp10
-rw-r--r--scene/animation/animation_tree_player.cpp6
-rw-r--r--scene/gui/button.cpp26
-rw-r--r--scene/gui/button.h2
-rw-r--r--scene/gui/check_box.cpp43
-rw-r--r--scene/gui/check_box.h2
-rw-r--r--scene/gui/check_button.cpp36
-rw-r--r--scene/gui/check_button.h1
-rw-r--r--scene/gui/control.cpp11
-rw-r--r--scene/gui/control.h5
-rw-r--r--scene/gui/file_dialog.cpp28
-rw-r--r--scene/gui/file_dialog.h5
-rw-r--r--scene/gui/menu_button.cpp1
-rw-r--r--scene/gui/option_button.cpp1
-rw-r--r--scene/gui/popup_menu.cpp95
-rw-r--r--scene/gui/popup_menu.h17
-rw-r--r--scene/gui/rich_text_label.cpp2
-rw-r--r--scene/gui/rich_text_label.h4
-rw-r--r--scene/gui/text_edit.cpp11
-rw-r--r--scene/gui/text_edit.h1
-rw-r--r--scene/main/viewport.cpp18
-rw-r--r--scene/resources/animation.cpp22
-rw-r--r--scene/resources/animation.h5
-rw-r--r--scene/resources/default_theme/default_theme.cpp10
-rw-r--r--scene/resources/mesh.cpp211
-rw-r--r--scene/resources/mesh.h7
-rw-r--r--scene/resources/sky_box.cpp4
-rw-r--r--scene/resources/surface_tool.cpp114
-rw-r--r--scene/resources/surface_tool.h3
-rw-r--r--scene/resources/tile_set.cpp20
-rw-r--r--scene/resources/tile_set.h2
-rw-r--r--servers/physics/body_sw.cpp48
-rw-r--r--servers/physics/body_sw.h6
-rw-r--r--servers/physics/physics_server_sw.cpp10
-rw-r--r--servers/physics/physics_server_sw.h4
-rw-r--r--servers/physics_server.cpp15
-rw-r--r--servers/physics_server.h18
-rw-r--r--servers/visual/rasterizer.h2
-rw-r--r--servers/visual/shader_language.cpp28
-rw-r--r--servers/visual/shader_language.h12
-rw-r--r--servers/visual/visual_server_canvas.cpp85
-rw-r--r--servers/visual/visual_server_canvas.h1
-rw-r--r--servers/visual/visual_server_raster.h1
-rw-r--r--servers/visual/visual_server_scene.cpp2
-rw-r--r--servers/visual/visual_server_wrap_mt.h1
-rw-r--r--servers/visual_server.h1
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/Atlas.cpp4
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/Atlas.h3
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp12
-rw-r--r--thirdparty/thekla_atlas/thekla/thekla_atlas.cpp271
-rw-r--r--thirdparty/thekla_atlas/thekla/thekla_atlas.h116
196 files changed, 4874 insertions, 2454 deletions
diff --git a/.clang-format b/.clang-format
index bc69a6a3a6..212bc25109 100644
--- a/.clang-format
+++ b/.clang-format
@@ -44,7 +44,6 @@ AllowShortIfStatementsOnASingleLine: true
BreakBeforeTernaryOperators: false
# BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: AfterColon
-# BreakAfterJavaFieldAnnotations: false
# BreakStringLiterals: true
ColumnLimit: 0
# CommentPragmas: '^ IWYU pragma:'
@@ -113,4 +112,8 @@ Language: ObjC
ObjCBlockIndentWidth: 4
# ObjCSpaceAfterProperty: false
# ObjCSpaceBeforeProtocolList: true
+---
+### Java specific config ###
+Language: Java
+# BreakAfterJavaFieldAnnotations: false
...
diff --git a/.gitignore b/.gitignore
index 0de1e682a0..cbb0b5b133 100644
--- a/.gitignore
+++ b/.gitignore
@@ -91,6 +91,9 @@ bld/
# Hints for improving IntelliSense, created together with VS project
cpp.hint
+# Visualizers for the VS debugger
+*.natvis
+
#NUNIT
*.VisualState.xml
TestResult.xml
diff --git a/AUTHORS.md b/AUTHORS.md
index 73712bbfc4..9a373896f8 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -32,6 +32,7 @@ name is available.
Alket Rexhepi (alketii)
Andrea Catania (AndreaCatania)
Andreas Haas (Hinsbart)
+ Andy Moss (MillionOstrich)
Anton Yabchinskiy (a12n)
Aren Villanueva (kurikaesu)
Ariel Manzur (punto-)
@@ -43,6 +44,7 @@ name is available.
Carl Olsson (not-surt)
Dana Olson (adolson)
Daniel J. Ramirez (djrm)
+ Dmitry Koteroff (Krakean)
Дмитрий Сальников (DmitriySalnikov)
Emmanuel Leblond (touilleMan)
Fabio Alessandrelli (Faless)
@@ -53,7 +55,7 @@ name is available.
George Marques (vnen)
Gerrit Großkopf (Grosskopf)
Gilles Roudiere (groud)
- Guilherme Felipe (guilhermefelipecgs)
+ Guilherme Felipe de C. G. da Silva (guilhermefelipecgs)
Hein-Pieter van Braam (hpvb)
Hiroshi Ogawa (hi-ogawa)
Hubert Jarosz (Marqin)
@@ -76,6 +78,7 @@ name is available.
Masoud BH (masoudbh3)
Matthias Hölzl (hoelzl)
Max Hilbrunner (mhilbrunner)
+ Michael Alexsander Silva Dias (YeldhamDev)
Nathan Warden (NathanWarden)
Nuno Donato (nunodonato)
Ovnuniarchos
@@ -97,13 +100,18 @@ name is available.
Timo (toger5)
V. Vamsi Krishna (vkbsb)
Vinzenz Feenstra (vinzenz)
+ Will Nations (willnationsdev)
Wilson E. Alvarez (Rubonnek)
+ Yuri Roubinski (Chaosus)
Zher Huei Lee (leezh)
ZuBsPaCe
박한얼 (volzhs)
bruvzg
est31
+ m4nu3lf
marynate
mrezai
+ rraallvv
romulox-x
+ sersoong
yg2f (SuperUserNameMan)
diff --git a/DONORS.md b/DONORS.md
index 3891a708ce..aea2ef5ae8 100644
--- a/DONORS.md
+++ b/DONORS.md
@@ -12,7 +12,7 @@ generous deed immortalized in the next stable release of Godot Engine.
## Platinum sponsors
-None so far, but your company could be the first! :)
+ Enjin Coin <https://enjincoin.io>
## Gold sponsors
@@ -22,15 +22,16 @@ None so far, but your company could be the first! :)
## Mini sponsors
Andreas
- Andreas Hirschauer
+ Brandon Lamb
Christian Uldall Pedersen
Christoph Woinke
E Hewert
Hein-Pieter van Braam
+ Jamal Alyafei
+ Jordan M Lucas
Matthieu Huvé
Nathan Warden
Neal Gompa (Conan Kudo)
- Olimpiu Metiu
Pascal Julien
Ruslan Mustakov
Slobodan Milnovic
@@ -48,15 +49,19 @@ None so far, but your company could be the first! :)
Officine Pixel S.n.c.
Rémi Verschelde
Stephan Lanfermann
+ Zaven Muradyan
Andreas Schüle
Austen McRae
Bernhard Liebl
+ Cody Brocious
Gerald E Butler
Jahn Johansen
- Jordan M Lucas
+ Johannes Wuensch
Kris Michael
+ Libre-Dépanne
Ranoller
+ Svenne Krap
BanjoNode2D
Chris Serino
@@ -80,40 +85,49 @@ None so far, but your company could be the first! :)
Amanda Haldy
Andreas Haas
- Andres Cuevas
Arnaud Verstuyf
- Bryanna M
Chris Brown
Cody Parker
D
+ Daniel Eliasinski
+ Daniel Langegger
+ Eric Monson
Ezra Theunissen
flesk
François Cantin
Giovanni Solimeno
- Hendrik Mans
Jeppe Zapp
Justin Arnold
Justo Delgado Baudí
Leandro Voltolino
Lucien Boudy
Noah
+ Patrick Schnorbus
+ Pete Goodwin
Ryan Estes
+ Ted
+ Travis Womack
Trent McPheron
## Silver donors
1D_Inc
+ Abe Pazos
+ Alder Stefano
Alessandro Senese
Alex Barsukov
+ Andres Cuevas
Anthony Bongiovanni
Avencherus
Bastian Böhm
Ben Vercammen
Blair Allen
Bryan Stevenson
+ Casey Foote
Christian Baune
Christian Winter
Collin Shooltz
+ Daniel Egger
Daniel Kaplan
David Cravens
David May
@@ -122,11 +136,13 @@ None so far, but your company could be the first! :)
Eric Martini
Fabian Becker
fengjiongmax
+ Francesco Lisi
Frank C. Simmons
+ Fredy Romero Sam
+ G3Dev sàrl
Geequlim
Gerrit Großkopf
Guldoman
- Gustav Dahlström
HardRound
hatniX
HeartBeast
@@ -134,6 +150,7 @@ None so far, but your company could be the first! :)
Hunter Jones
Jaime Ruiz-Borau Vizárraga
Jeff Hungerford
+ Jerry Chen
Jesse Liles
joe513
Jonathon
@@ -146,15 +163,15 @@ None so far, but your company could be the first! :)
Kevin Boyer
Kevin Kamper Meejach Petersen
Klavdij Voncina
- Kobi Malul
Linus Lind Lundgren
Lisandro Lorea
magodev
+ Markus Wiesner
Martin Novák
Matthew Fitzpatrick
- Matthew Valancy
Matthias Hölzl
Max R.R. Collada
+ memoryruins
mhilbrunner
Michael Gringauz
Michael Tintiuc
@@ -172,17 +189,18 @@ None so far, but your company could be the first! :)
Patrick Nafarrete
Paul Mason
Paweł Kowal
- Pete Goodwin
+ Pierre-Igor Berthet
Pietro Vertechi
rayos
Richman Stewart
+ Rodolfo Baeza
+ Roger Burgess
Roger Smith
Roman Tinkov
Sam Van Campenhout
Sasori Olkof
Scott D. Yelich
Sootstone
- TheHappieCat
Theo Cranmore
Thomas Norman
Tom Larrow
diff --git a/core/class_db.cpp b/core/class_db.cpp
index 57e88044b5..edd49fe95f 100644
--- a/core/class_db.cpp
+++ b/core/class_db.cpp
@@ -1036,7 +1036,6 @@ bool ClassDB::get_property(Object *p_object, const StringName &p_property, Varia
r_value = *c;
return true;
}
- //if (check->constant_map.fin)
check = check->inherits_ptr;
}
@@ -1163,24 +1162,6 @@ bool ClassDB::has_method(StringName p_class, StringName p_method, bool p_no_inhe
return false;
}
-bool ClassDB::get_setter_and_type_for_property(const StringName &p_class, const StringName &p_prop, StringName &r_class, StringName &r_setter) {
-
- ClassInfo *type = classes.getptr(p_class);
- ClassInfo *check = type;
- while (check) {
-
- if (check->property_setget.has(p_prop)) {
- r_class = check->name;
- r_setter = check->property_setget[p_prop].setter;
- return true;
- }
-
- check = check->inherits_ptr;
- }
-
- return false;
-}
-
#ifdef DEBUG_METHODS_ENABLED
MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount) {
StringName mdname = method_name.name;
diff --git a/core/class_db.h b/core/class_db.h
index b8b681301d..55fe01ec6d 100644
--- a/core/class_db.h
+++ b/core/class_db.h
@@ -349,8 +349,6 @@ public:
static StringName get_category(const StringName &p_node);
- static bool get_setter_and_type_for_property(const StringName &p_class, const StringName &p_prop, StringName &r_class, StringName &r_setter);
-
static void set_class_enabled(StringName p_class, bool p_enable);
static bool is_class_enabled(StringName p_class);
diff --git a/core/io/json.cpp b/core/io/json.cpp
index ddfc792cc7..82e938d2db 100644
--- a/core/io/json.cpp
+++ b/core/io/json.cpp
@@ -43,7 +43,7 @@ const char *JSON::tk_name[TK_MAX] = {
"EOF",
};
-static String _make_indent(const String& p_indent, int p_size) {
+static String _make_indent(const String &p_indent, int p_size) {
String indent_text = "";
if (!p_indent.empty()) {
@@ -53,7 +53,7 @@ static String _make_indent(const String& p_indent, int p_size) {
return indent_text;
}
-String JSON::_print_var(const Variant &p_var, const String& p_indent, int p_cur_indent, bool p_sort_keys) {
+String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys) {
String colon = ":";
String end_statement = "";
@@ -116,7 +116,7 @@ String JSON::_print_var(const Variant &p_var, const String& p_indent, int p_cur_
}
}
-String JSON::print(const Variant &p_var, const String& p_indent, bool p_sort_keys) {
+String JSON::print(const Variant &p_var, const String &p_indent, bool p_sort_keys) {
return _print_var(p_var, p_indent, 0, p_sort_keys);
}
diff --git a/core/io/json.h b/core/io/json.h
index 5e1a89f069..fbb7875c7c 100644
--- a/core/io/json.h
+++ b/core/io/json.h
@@ -64,7 +64,7 @@ class JSON {
static const char *tk_name[TK_MAX];
- static String _print_var(const Variant &p_var, const String& p_indent, int p_cur_indent, bool p_sort_keys);
+ static String _print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys);
static Error _get_token(const CharType *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str);
static Error _parse_value(Variant &value, Token &token, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str);
@@ -72,7 +72,7 @@ class JSON {
static Error _parse_object(Dictionary &object, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str);
public:
- static String print(const Variant &p_var, const String& p_indent = "", bool p_sort_keys = true);
+ static String print(const Variant &p_var, const String &p_indent = "", bool p_sort_keys = true);
static Error parse(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line);
};
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index 7e26761abf..4498efeb41 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -473,8 +473,8 @@ void AStar::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_point_path", "from_id", "to_id"), &AStar::get_point_path);
ClassDB::bind_method(D_METHOD("get_id_path", "from_id", "to_id"), &AStar::get_id_path);
- BIND_VMETHOD(MethodInfo("_estimate_cost", PropertyInfo(Variant::INT, "from_id"), PropertyInfo(Variant::INT, "to_id")));
- BIND_VMETHOD(MethodInfo("_compute_cost", PropertyInfo(Variant::INT, "from_id"), PropertyInfo(Variant::INT, "to_id")));
+ BIND_VMETHOD(MethodInfo(Variant::REAL, "_estimate_cost", PropertyInfo(Variant::INT, "from_id"), PropertyInfo(Variant::INT, "to_id")));
+ BIND_VMETHOD(MethodInfo(Variant::REAL, "_compute_cost", PropertyInfo(Variant::INT, "from_id"), PropertyInfo(Variant::INT, "to_id")));
}
AStar::AStar() {
diff --git a/core/math/math_2d.cpp b/core/math/math_2d.cpp
index c77fe96ff2..11003c1cd5 100644
--- a/core/math/math_2d.cpp
+++ b/core/math/math_2d.cpp
@@ -222,35 +222,6 @@ Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, c
(2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 +
(-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3);
return out;
-
- /*
- real_t mu = p_t;
- real_t mu2 = mu*mu;
-
- Vector2 a0 = p_post_b - p_b - p_pre_a + *this;
- Vector2 a1 = p_pre_a - *this - a0;
- Vector2 a2 = p_b - p_pre_a;
- Vector2 a3 = *this;
-
- return ( a0*mu*mu2 + a1*mu2 + a2*mu + a3 );
-*/
- /*
- real_t t = p_t;
- real_t t2 = t*t;
- real_t t3 = t2*t;
-
- real_t a = 2.0*t3- 3.0*t2 + 1;
- real_t b = -2.0*t3+ 3.0*t2;
- real_t c = t3- 2.0*t2 + t;
- real_t d = t3- t2;
-
- Vector2 p_a=*this;
-
- return Vector2(
- (a * p_a.x) + (b *p_b.x) + (c * p_pre_a.x) + (d * p_post_b.x),
- (a * p_a.y) + (b *p_b.y) + (c * p_pre_a.y) + (d * p_post_b.y)
- );
-*/
}
// slide returns the component of the vector along the given plane, specified by its normal vector.
diff --git a/core/math/math_2d.h b/core/math/math_2d.h
index d788318f5e..60351445c0 100644
--- a/core/math/math_2d.h
+++ b/core/math/math_2d.h
@@ -382,6 +382,11 @@ struct Rect2 {
size = end - begin;
}
+ inline Rect2 abs() const {
+
+ return Rect2(Point2(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0)), size.abs());
+ }
+
operator String() const { return String(position) + ", " + String(size); }
Rect2() {}
diff --git a/core/os/os.h b/core/os/os.h
index 4f968020cc..979ad7e92a 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -92,14 +92,16 @@ public:
bool resizable;
bool borderless_window;
bool maximized;
+ bool use_vsync;
float get_aspect() const { return (float)width / (float)height; }
- VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false, bool p_maximized = false) {
+ VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false, bool p_maximized = false, bool p_use_vsync = false) {
width = p_width;
height = p_height;
fullscreen = p_fullscreen;
resizable = p_resizable;
borderless_window = p_borderless_window;
maximized = p_maximized;
+ use_vsync = p_use_vsync;
}
};
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 991573e8d7..f66cce85c9 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -360,6 +360,7 @@ struct _VariantCall {
VCALL_LOCALMEM2R(Rect2, grow_margin);
VCALL_LOCALMEM4R(Rect2, grow_individual);
VCALL_LOCALMEM1R(Rect2, expand);
+ VCALL_LOCALMEM0R(Rect2, abs);
VCALL_LOCALMEM0R(Vector3, min_axis);
VCALL_LOCALMEM0R(Vector3, max_axis);
@@ -1526,6 +1527,7 @@ void register_variant_methods() {
ADDFUNC2R(RECT2, RECT2, Rect2, grow_margin, INT, "margin", REAL, "by", varray());
ADDFUNC4R(RECT2, RECT2, Rect2, grow_individual, REAL, "left", REAL, "top", REAL, "right", REAL, " bottom", varray());
ADDFUNC1R(RECT2, RECT2, Rect2, expand, VECTOR2, "to", varray());
+ ADDFUNC0R(RECT2, RECT2, Rect2, abs, varray());
ADDFUNC0R(VECTOR3, INT, Vector3, min_axis, varray());
ADDFUNC0R(VECTOR3, INT, Vector3, max_axis, varray());
diff --git a/doc/classes/AStar.xml b/doc/classes/AStar.xml
index eefdf4d7a7..e0e3261edf 100644
--- a/doc/classes/AStar.xml
+++ b/doc/classes/AStar.xml
@@ -13,7 +13,7 @@
</demos>
<methods>
<method name="_compute_cost" qualifiers="virtual">
- <return type="void">
+ <return type="float">
</return>
<argument index="0" name="from_id" type="int">
</argument>
@@ -24,7 +24,7 @@
</description>
</method>
<method name="_estimate_cost" qualifiers="virtual">
- <return type="void">
+ <return type="float">
</return>
<argument index="0" name="from_id" type="int">
</argument>
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index c3933443a0..93b01a466b 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -30,6 +30,16 @@
Clear the animation (clear all tracks and reset all).
</description>
</method>
+ <method name="copy_track">
+ <return type="void">
+ </return>
+ <argument index="0" name="track" type="int">
+ </argument>
+ <argument index="1" name="to_animation" type="Animation">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="find_track" qualifiers="const">
<return type="int">
</return>
@@ -244,6 +254,14 @@
Insert a generic key in a given track.
</description>
</method>
+ <method name="track_is_enabled" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="track_is_imported" qualifiers="const">
<return type="bool">
</return>
@@ -293,6 +311,16 @@
Remove a key by position (seconds) in a given track.
</description>
</method>
+ <method name="track_set_enabled">
+ <return type="void">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="track_set_imported">
<return type="void">
</return>
diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml
index 3b1ce37619..d61211bb6b 100644
--- a/doc/classes/AnimationPlayer.xml
+++ b/doc/classes/AnimationPlayer.xml
@@ -74,20 +74,6 @@
Returns the name of [code]animation[/code] or empty string if not found.
</description>
</method>
- <method name="get_anim_length" qualifiers="const">
- <return type="float">
- </return>
- <description>
- Get the length (in seconds) of the currently playing animation.
- </description>
- </method>
- <method name="get_anim_position" qualifiers="const">
- <return type="float">
- </return>
- <description>
- Get the position (in seconds) of the currently playing animation.
- </description>
- </method>
<method name="get_animation" qualifiers="const">
<return type="Animation">
</return>
@@ -115,11 +101,18 @@
Get the blend time (in seconds) between two animations, referenced by their names.
</description>
</method>
- <method name="get_current_animation" qualifiers="const">
- <return type="String">
+ <method name="get_current_animation_length" qualifiers="const">
+ <return type="float">
</return>
<description>
- Returns the name of the currently playing animation.
+ Get the length (in seconds) of the currently playing animation.
+ </description>
+ </method>
+ <method name="get_current_animation_position" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ Get the position (in seconds) of the currently playing animation.
</description>
</method>
<method name="has_animation" qualifiers="const">
@@ -217,15 +210,6 @@
Specify a blend time (in seconds) between two animations, referenced by their names.
</description>
</method>
- <method name="set_current_animation">
- <return type="void">
- </return>
- <argument index="0" name="anim" type="String">
- </argument>
- <description>
- Set the current animation (even if no playback occurs). Using set_current_animation() and set_active() are similar to calling play().
- </description>
- </method>
<method name="stop">
<return type="void">
</return>
@@ -250,8 +234,10 @@
<member name="autoplay" type="String" setter="set_autoplay" getter="get_autoplay">
The name of the animation to play when the scene loads. Default value: [code]""[/code].
</member>
+ <member name="current_animation" type="String" setter="set_current_animation" getter="get_current_animation">
+ The name of the current animation. Default value: [code]""[/code].
+ </member>
<member name="playback_default_blend_time" type="float" setter="set_default_blend_time" getter="get_default_blend_time">
- The default time in which to blend animations. Ranges from 0 to 4096 with 0.01 precision. Default value: [code]0[/code].
</member>
<member name="playback_process_mode" type="int" setter="set_animation_process_mode" getter="get_animation_process_mode" enum="AnimationPlayer.AnimationProcessMode">
The process notification in which to update animations. Default value: [enum ANIMATION_PROCESS_IDLE].
diff --git a/doc/classes/AnimationTreePlayer.xml b/doc/classes/AnimationTreePlayer.xml
index 4fb33eb5a3..ecd1f81951 100644
--- a/doc/classes/AnimationTreePlayer.xml
+++ b/doc/classes/AnimationTreePlayer.xml
@@ -4,7 +4,7 @@
Animation Player that uses a node graph for the blending.
</brief_description>
<description>
- Animation Player that uses a node graph for the blending. This kind of player is very useful when animating character or other skeleton based rigs, because it can combine several animations to form a desired pose.
+ A node graph tool for blending multiple animations bound to an [AnimationPlayer]. Especially useful for animating characters or other skeleton-based rigs. It can combine several animations to form a desired pose.
</description>
<tutorials>
</tutorials>
@@ -19,7 +19,7 @@
<argument index="1" name="id" type="String">
</argument>
<description>
- Add a node of a given type in the graph with given id.
+ Adds a [code]type[/code] node to the graph with name [code]id[/code].
</description>
</method>
<method name="advance">
@@ -28,6 +28,7 @@
<argument index="0" name="delta" type="float">
</argument>
<description>
+ Shifts position in the animation timeline. Delta is the time in seconds to shift.
</description>
</method>
<method name="animation_node_get_animation" qualifiers="const">
@@ -36,7 +37,7 @@
<argument index="0" name="id" type="String">
</argument>
<description>
- Returns an animation given its name.
+ Returns the [AnimationPlayer]'s animation bound to the [code]AnimationTreePlayer[/code]'s animation node with name [code]id[/code].
</description>
</method>
<method name="animation_node_get_master_animation" qualifiers="const">
@@ -45,6 +46,7 @@
<argument index="0" name="id" type="String">
</argument>
<description>
+ Returns the name of the [member master_player]'s animation bound to this animation node.
</description>
</method>
<method name="animation_node_set_animation">
@@ -55,7 +57,7 @@
<argument index="1" name="animation" type="Animation">
</argument>
<description>
- Set the animation for an animation node.
+ Binds a new animation from the [member master_player] to the [code]AnimationTreePlayer[/code]'s animation node with name [code]id[/code].
</description>
</method>
<method name="animation_node_set_filter_path">
@@ -68,6 +70,7 @@
<argument index="2" name="enable" type="bool">
</argument>
<description>
+ If [code]enable[/code] is [code]true[/code], the animation node with ID [code]id[/code] turns off the track modifying the property at [code]path[/code]. The modified node's children continue to animate.
</description>
</method>
<method name="animation_node_set_master_animation">
@@ -78,6 +81,7 @@
<argument index="1" name="source" type="String">
</argument>
<description>
+ Binds the animation named [code]source[/code] from [member master_player] to the animation node [code]id[/code]. Recalculates caches.
</description>
</method>
<method name="are_nodes_connected" qualifiers="const">
@@ -123,6 +127,7 @@
<argument index="2" name="enable" type="bool">
</argument>
<description>
+ If [code]enable[/code] is [code]true[/code], the blend2 node with ID [code]id[/code] turns off the track modifying the property at [code]path[/code]. The modified node's children continue to animate.
</description>
</method>
<method name="blend3_node_get_amount" qualifiers="const">
@@ -189,18 +194,6 @@
Disconnects nodes connected to [code]id[/code] at the specified input slot.
</description>
</method>
- <method name="get_base_path" qualifiers="const">
- <return type="NodePath">
- </return>
- <description>
- </description>
- </method>
- <method name="get_master_player" qualifiers="const">
- <return type="NodePath">
- </return>
- <description>
- </description>
- </method>
<method name="get_node_list">
<return type="PoolStringArray">
</return>
@@ -208,13 +201,6 @@
Returns a PoolStringArray containing the name of all nodes.
</description>
</method>
- <method name="is_active" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- Returns whether this AnimationTreePlayer is active.
- </description>
- </method>
<method name="mix_node_get_amount" qualifiers="const">
<return type="float">
</return>
@@ -423,6 +409,7 @@
<argument index="2" name="enable" type="bool">
</argument>
<description>
+ If [code]enable[/code] is [code]true[/code], the oneshot node with ID [code]id[/code] turns off the track modifying the property at [code]path[/code]. The modified node's children continue to animate.
</description>
</method>
<method name="oneshot_node_start">
@@ -440,13 +427,14 @@
<argument index="0" name="id" type="String">
</argument>
<description>
- Stops a OneShot node given its name.
+ Stops the OneShot node with name [code]id[/code].
</description>
</method>
<method name="recompute_caches">
<return type="void">
</return>
<description>
+ Manually recalculates the cache of track information generated from animation nodes. Needed when external sources modify the animation nodes' state.
</description>
</method>
<method name="remove_node">
@@ -455,6 +443,7 @@
<argument index="0" name="id" type="String">
</argument>
<description>
+ Removes the animation node with name [code]id[/code].
</description>
</method>
<method name="reset">
@@ -464,39 +453,13 @@
Resets this AnimationTreePlayer.
</description>
</method>
- <method name="set_active">
- <return type="void">
- </return>
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- Sets whether this AnimationTreePlayer is active. AnimationTreePlayer will start processing if set to active.
- </description>
- </method>
- <method name="set_base_path">
- <return type="void">
- </return>
- <argument index="0" name="path" type="NodePath">
- </argument>
- <description>
- Sets base path of this AnimationTreePlayer.
- </description>
- </method>
- <method name="set_master_player">
- <return type="void">
- </return>
- <argument index="0" name="nodepath" type="NodePath">
- </argument>
- <description>
- </description>
- </method>
<method name="timescale_node_get_scale" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="id" type="String">
</argument>
<description>
- Returns time scale value of a TimeScale node given its name.
+ Returns time scale value of the TimeScale node with name [code]id[/code].
</description>
</method>
<method name="timescale_node_set_scale">
@@ -507,7 +470,7 @@
<argument index="1" name="scale" type="float">
</argument>
<description>
- Sets time scale value of a TimeScale node given its name and value.
+ Sets the time scale of the TimeScale node with name [code]id[/code] to [code]scale[/code].
</description>
</method>
<method name="timeseek_node_seek">
@@ -518,7 +481,7 @@
<argument index="1" name="seconds" type="float">
</argument>
<description>
- Sets time seek value of a TimeSeek node given its name and value.
+ Sets the time seek value of the TimeSeek node with name [code]id[/code] to [code]seconds[/code]
</description>
</method>
<method name="transition_node_delete_input">
@@ -529,6 +492,7 @@
<argument index="1" name="input_idx" type="int">
</argument>
<description>
+ Deletes the input at [code]input_idx[/code] for the transition node with name [code]id[/code].
</description>
</method>
<method name="transition_node_get_current" qualifiers="const">
@@ -537,6 +501,7 @@
<argument index="0" name="id" type="String">
</argument>
<description>
+ Returns the index of the currently evaluated input for the transition node with name [code]id[/code].
</description>
</method>
<method name="transition_node_get_input_count" qualifiers="const">
@@ -545,6 +510,7 @@
<argument index="0" name="id" type="String">
</argument>
<description>
+ Returns the number of inputs for the transition node with name [code]id[/code].
</description>
</method>
<method name="transition_node_get_xfade_time" qualifiers="const">
@@ -553,6 +519,7 @@
<argument index="0" name="id" type="String">
</argument>
<description>
+ Returns the cross fade time for the transition node with name [code]id[/code].
</description>
</method>
<method name="transition_node_has_input_auto_advance" qualifiers="const">
@@ -563,6 +530,7 @@
<argument index="1" name="input_idx" type="int">
</argument>
<description>
+ Returns [code]true[/code] if the input at [code]input_idx[/code] on transition node with name [code]id[/code] is set to automatically advance to the next input upon completion.
</description>
</method>
<method name="transition_node_set_current">
@@ -573,6 +541,7 @@
<argument index="1" name="input_idx" type="int">
</argument>
<description>
+ The transition node with name [code]id[/code] sets its current input at [code]input_idx[/code].
</description>
</method>
<method name="transition_node_set_input_auto_advance">
@@ -585,6 +554,7 @@
<argument index="2" name="enable" type="bool">
</argument>
<description>
+ The transition node with name [code]id[/code] advances to its next input automatically when the input at [code]input_idx[/code] completes.
</description>
</method>
<method name="transition_node_set_input_count">
@@ -595,6 +565,7 @@
<argument index="1" name="count" type="int">
</argument>
<description>
+ Resizes the number of inputs available for the transition node with name [code]id[/code].
</description>
</method>
<method name="transition_node_set_xfade_time">
@@ -605,11 +576,22 @@
<argument index="1" name="time_sec" type="float">
</argument>
<description>
+ The transition node with name [code]id[/code] sets its cross fade time to [code]time_sec[/code].
</description>
</method>
</methods>
<members>
+ <member name="active" type="bool" setter="set_active" getter="is_active">
+ If [code]true[/code] the [code]AnimationTreePlayer[/code] is able to play animations. Default value: [code]false[/code].
+ </member>
+ <member name="base_path" type="NodePath" setter="set_base_path" getter="get_base_path">
+ The node from which to relatively access other nodes. Default value: [code]".."[/code].
+ </member>
+ <member name="master_player" type="NodePath" setter="set_master_player" getter="get_master_player">
+ The path to the [AnimationPlayer] from which this [code]AnimationTreePlayer[/code] binds animations to animation nodes.
+ </member>
<member name="playback_process_mode" type="int" setter="set_animation_process_mode" getter="get_animation_process_mode" enum="AnimationTreePlayer.AnimationProcessMode">
+ The thread in which to update animations. Default value: [enum ANIMATION_PROCESS_IDLE].
</member>
</members>
<constants>
@@ -644,8 +626,10 @@
Transition node.
</constant>
<constant name="ANIMATION_PROCESS_PHYSICS" value="0" enum="AnimationProcessMode">
+ Process animation during the physics process. This is especially useful when animating physics bodies.
</constant>
<constant name="ANIMATION_PROCESS_IDLE" value="1" enum="AnimationProcessMode">
+ Process animation during the idle process.
</constant>
</constants>
</class>
diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml
index a7f9a6e09c..9445a1732e 100644
--- a/doc/classes/Array.xml
+++ b/doc/classes/Array.xml
@@ -284,6 +284,16 @@
</argument>
<description>
Sort the array using a custom method and return reference to the array. The arguments are an object that holds the method and the name of such method. The custom method receives two arguments (a pair of elements from the array) and must return true if the first argument is less than the second, and return false otherwise. Note: you cannot randomize the return value as the heapsort algorithm expects a deterministic result. Doing so will result in unexpected behavior.
+ [codeblock]
+ class MyCustomSorter:
+ static func sort(a, b):
+ if a[0] &lt; b[0]:
+ return true
+ return false
+
+ var my_items = [[5, "Potato"], [9, "Rice"], [4, "Tomato"]]
+ my_items.sort_custom(MyCustomSorter, "sort")
+ [/codeblock]
</description>
</method>
</methods>
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index 4a567981e6..cf0b482b07 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -88,6 +88,34 @@
Draw a line from a 2D point to another, with a given color and width. It can be optionally antialiased.
</description>
</method>
+ <method name="draw_multiline">
+ <return type="void">
+ </return>
+ <argument index="0" name="points" type="PoolVector2Array">
+ </argument>
+ <argument index="1" name="color" type="Color">
+ </argument>
+ <argument index="2" name="width" type="float" default="1.0">
+ </argument>
+ <argument index="3" name="antialiased" type="bool" default="false">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="draw_multiline_colors">
+ <return type="void">
+ </return>
+ <argument index="0" name="points" type="PoolVector2Array">
+ </argument>
+ <argument index="1" name="colors" type="PoolColorArray">
+ </argument>
+ <argument index="2" name="width" type="float" default="1.0">
+ </argument>
+ <argument index="3" name="antialiased" type="bool" default="false">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="draw_polygon">
<return type="void">
</return>
diff --git a/doc/classes/ConcavePolygonShape2D.xml b/doc/classes/ConcavePolygonShape2D.xml
index 1910b1d62d..1d2aabd6ea 100644
--- a/doc/classes/ConcavePolygonShape2D.xml
+++ b/doc/classes/ConcavePolygonShape2D.xml
@@ -15,6 +15,7 @@
</methods>
<members>
<member name="segments" type="PoolVector2Array" setter="set_segments" getter="get_segments">
+ The array of points that make up the [code]ConcavePolygonShape2D[/code]'s line segments.
</member>
</members>
<constants>
diff --git a/doc/classes/CubeMap.xml b/doc/classes/CubeMap.xml
index a7857dba78..30022efd38 100644
--- a/doc/classes/CubeMap.xml
+++ b/doc/classes/CubeMap.xml
@@ -4,7 +4,7 @@
A CubeMap is a 6 sided 3D texture.
</brief_description>
<description>
- A CubeMap is a 6 sided 3D texture typically used for faking reflections. It can be used to make an object look as if it's reflecting its surroundings. This usually delivers much better performance than other reflection methods.
+ A 6-sided 3D texture typically used for faking reflections. It can be used to make an object look as if it's reflecting its surroundings. This usually delivers much better performance than other reflection methods.
</description>
<tutorials>
</tutorials>
@@ -15,13 +15,14 @@
<return type="int">
</return>
<description>
+ Returns the render flags for the [code]CubeMap[/code]. See the [code]FLAG_*[/code] constants for details.
</description>
</method>
<method name="get_height" qualifiers="const">
<return type="int">
</return>
<description>
- Returns the CubeMap's height.
+ Returns the [code]CubeMap[/code]'s height.
</description>
</method>
<method name="get_side" qualifiers="const">
@@ -30,14 +31,14 @@
<argument index="0" name="side" type="int" enum="CubeMap.Side">
</argument>
<description>
- Returns an [Image] for a side of the CubeMap using one of the [code]SIDE_*[/code] constants or an integer 0-5.
+ Returns an [Image] for a side of the [code]CubeMap[/code] using one of the [code]SIDE_*[/code] constants or an integer 0-5.
</description>
</method>
<method name="get_width" qualifiers="const">
<return type="int">
</return>
<description>
- Returns the CubeMap's width.
+ Returns the [code]CubeMap[/code]'s width.
</description>
</method>
<method name="set_flags">
@@ -46,6 +47,7 @@
<argument index="0" name="flags" type="int">
</argument>
<description>
+ Returns the render flags for the [code]CubeMap[/code]. See the [code]FLAG_*[/code] constants for details.
</description>
</method>
<method name="set_side">
@@ -56,44 +58,57 @@
<argument index="1" name="image" type="Image">
</argument>
<description>
- Sets an [Image] for a side of the CubeMap using one of the [code]SIDE_*[/code] constants or an integer 0-5.
+ Sets an [Image] for a side of the [code]CubeMap[/code] using one of the [code]SIDE_*[/code] constants or an integer 0-5.
</description>
</method>
</methods>
<members>
<member name="lossy_storage_quality" type="float" setter="set_lossy_storage_quality" getter="get_lossy_storage_quality">
- The lossy storage quality of the CubeMap if the storage mode is set to STORAGE_COMPRESS_LOSSY.
+ The lossy storage quality of the [code]CubeMap[/code] if the storage mode is set to STORAGE_COMPRESS_LOSSY.
</member>
<member name="storage_mode" type="int" setter="set_storage" getter="get_storage" enum="CubeMap.Storage">
- The CubeMap's storage mode. See [code]STORAGE_*[/code] constants.
+ The [code]CubeMap[/code]'s storage mode. See [code]STORAGE_*[/code] constants.
</member>
</members>
<constants>
<constant name="STORAGE_RAW" value="0" enum="Storage">
+ Store the [code]CubeMap[/code] without any compression.
</constant>
<constant name="STORAGE_COMPRESS_LOSSY" value="1" enum="Storage">
+ Store the [code]CubeMap[/code] with strong compression that reduces image quality.
</constant>
<constant name="STORAGE_COMPRESS_LOSSLESS" value="2" enum="Storage">
+ Store the [code]CubeMap[/code] with moderate compression that doesn't reduce image quality.
</constant>
<constant name="SIDE_LEFT" value="0" enum="Side">
+ Identifier for the left face of the [code]CubeMap[/code].
</constant>
<constant name="SIDE_RIGHT" value="1" enum="Side">
+ Identifier for the right face of the [code]CubeMap[/code].
</constant>
<constant name="SIDE_BOTTOM" value="2" enum="Side">
+ Identifier for the bottom face of the [code]CubeMap[/code].
</constant>
<constant name="SIDE_TOP" value="3" enum="Side">
+ Identifier for the top face of the [code]CubeMap[/code].
</constant>
<constant name="SIDE_FRONT" value="4" enum="Side">
+ Identifier for the front face of the [code]CubeMap[/code].
</constant>
<constant name="SIDE_BACK" value="5" enum="Side">
+ Identifier for the back face of the [code]CubeMap[/code].
</constant>
<constant name="FLAG_MIPMAPS" value="1" enum="Flags">
+ Generate mipmaps, to enable smooth zooming out of the texture.
</constant>
<constant name="FLAG_REPEAT" value="2" enum="Flags">
+ Repeat (instead of clamp to edge).
</constant>
<constant name="FLAG_FILTER" value="4" enum="Flags">
+ Turn on magnifying filter, to enable smooth zooming in of the texture.
</constant>
<constant name="FLAGS_DEFAULT" value="7" enum="Flags">
+ Default flags. Generate mipmaps, repeat, and filter are enabled.
</constant>
</constants>
</class>
diff --git a/doc/classes/EditorFileSystem.xml b/doc/classes/EditorFileSystem.xml
index f577a4676f..54b3accb19 100644
--- a/doc/classes/EditorFileSystem.xml
+++ b/doc/classes/EditorFileSystem.xml
@@ -33,6 +33,7 @@
<argument index="0" name="path" type="String">
</argument>
<description>
+ Returns a view into the filesystem at [code]path[/code].
</description>
</method>
<method name="get_scanning_progress" qualifiers="const">
@@ -83,6 +84,7 @@
<argument index="0" name="resources" type="PoolStringArray">
</argument>
<description>
+ Remitted if a resource is reimported.
</description>
</signal>
<signal name="sources_changed">
diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml
index edd1f721b5..ada0ee56a8 100644
--- a/doc/classes/EditorPlugin.xml
+++ b/doc/classes/EditorPlugin.xml
@@ -82,6 +82,14 @@
<description>
</description>
</method>
+ <method name="add_scene_import_plugin">
+ <return type="void">
+ </return>
+ <argument index="0" name="scene_importer" type="EditorSceneImporter">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="add_tool_submenu_item">
<return type="void">
</return>
@@ -176,6 +184,12 @@
<description>
</description>
</method>
+ <method name="get_plugin_icon" qualifiers="virtual">
+ <return type="Object">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_plugin_name" qualifiers="virtual">
<return type="String">
</return>
@@ -295,6 +309,14 @@
<description>
</description>
</method>
+ <method name="remove_scene_import_plugin">
+ <return type="void">
+ </return>
+ <argument index="0" name="scene_importer" type="EditorSceneImporter">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="save_external_data" qualifiers="virtual">
<return type="void">
</return>
diff --git a/doc/classes/EditorResourceConversionPlugin.xml b/doc/classes/EditorResourceConversionPlugin.xml
index b2bbe69061..8d6aa3a605 100644
--- a/doc/classes/EditorResourceConversionPlugin.xml
+++ b/doc/classes/EditorResourceConversionPlugin.xml
@@ -18,7 +18,7 @@
</description>
</method>
<method name="_converts_to" qualifiers="virtual">
- <return type="bool">
+ <return type="String">
</return>
<description>
</description>
diff --git a/doc/classes/EditorSceneImporter.xml b/doc/classes/EditorSceneImporter.xml
new file mode 100644
index 0000000000..69fe4050f4
--- /dev/null
+++ b/doc/classes/EditorSceneImporter.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="EditorSceneImporter" inherits="Reference" category="Core" version="3.0-beta">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ <method name="_get_extensions" qualifiers="virtual">
+ <return type="Array">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="_get_import_flags" qualifiers="virtual">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="_import_animation" qualifiers="virtual">
+ <return type="Animation">
+ </return>
+ <argument index="0" name="path" type="String">
+ </argument>
+ <argument index="1" name="flags" type="int">
+ </argument>
+ <argument index="2" name="bake_fps" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="_import_scene" qualifiers="virtual">
+ <return type="Node">
+ </return>
+ <argument index="0" name="path" type="String">
+ </argument>
+ <argument index="1" name="flags" type="int">
+ </argument>
+ <argument index="2" name="bake_fps" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="import_animation_from_other_importer">
+ <return type="Animation">
+ </return>
+ <argument index="0" name="path" type="String">
+ </argument>
+ <argument index="1" name="flags" type="int">
+ </argument>
+ <argument index="2" name="bake_fps" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="import_scene_from_other_importer">
+ <return type="Node">
+ </return>
+ <argument index="0" name="path" type="String">
+ </argument>
+ <argument index="1" name="flags" type="int">
+ </argument>
+ <argument index="2" name="bake_fps" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <constants>
+ <constant name="IMPORT_SCENE" value="1">
+ </constant>
+ <constant name="IMPORT_ANIMATION" value="2">
+ </constant>
+ <constant name="IMPORT_ANIMATION_DETECT_LOOP" value="4">
+ </constant>
+ <constant name="IMPORT_ANIMATION_OPTIMIZE" value="8">
+ </constant>
+ <constant name="IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS" value="16">
+ </constant>
+ <constant name="IMPORT_ANIMATION_KEEP_VALUE_TRACKS" value="32">
+ </constant>
+ <constant name="IMPORT_GENERATE_TANGENT_ARRAYS" value="256">
+ </constant>
+ <constant name="IMPORT_FAIL_ON_MISSING_DEPENDENCIES" value="512">
+ </constant>
+ <constant name="IMPORT_MATERIALS_IN_INSTANCES" value="1024">
+ </constant>
+ <constant name="IMPORT_USE_COMPRESSION" value="2048">
+ </constant>
+ </constants>
+</class>
diff --git a/doc/classes/FileDialog.xml b/doc/classes/FileDialog.xml
index 8057e95d44..3387b4a2ed 100644
--- a/doc/classes/FileDialog.xml
+++ b/doc/classes/FileDialog.xml
@@ -103,6 +103,9 @@
</member>
<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="FileDialog.Mode">
</member>
+ <member name="mode_overrides_title" type="bool" setter="set_mode_overrides_title" getter="is_mode_overriding_title">
+ If [code]true[/code], changing the [code]mode[/code] property will set the window title accordingly (e. g. setting mode to [code]MODE_OPEN_FILE[/code] will change the window title to "Open a File").
+ </member>
<member name="show_hidden_files" type="bool" setter="set_show_hidden_files" getter="is_showing_hidden_files">
</member>
</members>
diff --git a/doc/classes/HTTPClient.xml b/doc/classes/HTTPClient.xml
index b1526b64c5..b90c49b5c0 100644
--- a/doc/classes/HTTPClient.xml
+++ b/doc/classes/HTTPClient.xml
@@ -4,8 +4,10 @@
Hyper-text transfer protocol client.
</brief_description>
<description>
- Hyper-text transfer protocol client. Supports SSL and SSL server certificate verification.
- Can be reused to connect to different hosts and make many requests.
+ Hyper-text transfer protocol client (sometimes called "User Agent"). Used to make HTTP requests to download web content, upload files and other data or to communicate with various services, among other use cases.
+ Note that this client only needs to connect to a host once (see [method connect_to_host]) to send multiple requests. Because of this, methods that take URLs usually take just the part after the host instead of the full URL, as the client is already connected to a host. See [method request] for a full example and to get started.
+ A [code]HTTPClient[/code] should be reused between multiple requests or to connect to different hosts instead of creating one client per request. Supports SSL and SSL server certificate verification. HTTP status codes in the 2xx range indicate success, 3xx redirection (i.e. "try again, but over here"), 4xx something was wrong with the request, and 5xx something went wrong on the server's side.
+ For more information on HTTP, see https://developer.mozilla.org/en-US/docs/Web/HTTP (or read RFC 2616 to get it straight from the source: https://tools.ietf.org/html/rfc2616).
</description>
<tutorials>
</tutorials>
@@ -16,7 +18,7 @@
<return type="void">
</return>
<description>
- Cloces the current connection, allows for reusal of [code]HTTPClient[/code].
+ Closes the current connection, allowing reuse of this [code]HTTPClient[/code].
</description>
</method>
<method name="connect_to_host">
@@ -33,35 +35,35 @@
<description>
Connect to a host. This needs to be done before any requests are sent.
The host should not have http:// prepended but will strip the protocol identifier if provided.
- verify_host will check the SSL identity of the host if set to true.
+ [code]verify_host[/code] will check the SSL identity of the host if set to [code]true[/code].
</description>
</method>
<method name="get_connection" qualifiers="const">
<return type="StreamPeer">
</return>
<description>
- Return current connection.
+ Returns the current connection.
</description>
</method>
<method name="get_response_body_length" qualifiers="const">
<return type="int">
</return>
<description>
- Return the response's body length.
+ Returns the response's body length.
</description>
</method>
<method name="get_response_code" qualifiers="const">
<return type="int">
</return>
<description>
- Return the HTTP status code of the response.
+ Returns the response's HTTP status code.
</description>
</method>
<method name="get_response_headers">
<return type="PoolStringArray">
</return>
<description>
- Return the response headers.
+ Returns the response headers.
</description>
</method>
<method name="get_response_headers_as_dictionary">
@@ -84,21 +86,21 @@
<return type="bool">
</return>
<description>
- Return whether this [code]HTTPClient[/code] has a response available.
+ If [code]true[/code] this [code]HTTPClient[/code] has a response available.
</description>
</method>
<method name="is_blocking_mode_enabled" qualifiers="const">
<return type="bool">
</return>
<description>
- Return whether blocking mode is enabled.
+ If [code]true[/code] blocking mode is enabled.
</description>
</method>
<method name="is_response_chunked" qualifiers="const">
<return type="bool">
</return>
<description>
- Return whether this [code]HTTPClient[/code] has a response that is chunked.
+ If [code]true[/code] this [code]HTTPClient[/code] has a response that is chunked.
</description>
</method>
<method name="poll">
@@ -141,8 +143,8 @@
<argument index="3" name="body" type="String" default="&quot;&quot;">
</argument>
<description>
- Sends a request to the connected host. The url is what is normally behind the hostname, i.e. in [code]http://somehost.com/index.php[/code], url would be "index.php".
- Headers are HTTP request headers.
+ Sends a request to the connected host. The URL parameter is just the part after the host, so for [code]http://somehost.com/index.php[/code], it is [code]index.php[/code].
+ Headers are HTTP request headers. For available HTTP methods, see [code]METHOD_*[/code].
To create a POST request with query strings to push to the server, do:
[codeblock]
var fields = {"username" : "user", "password" : "pass"}
@@ -164,9 +166,9 @@
<argument index="3" name="body" type="PoolByteArray">
</argument>
<description>
- Sends a raw request to the connected host. The url is what is normally behind the hostname, i.e. in [code]http://somehost.com/index.php[/code], url would be "index.php".
- Headers are HTTP request headers.
- Sends body raw, as a byte array, does not encode it in any way.
+ Sends a raw request to the connected host. The URL parameter is just the part after the host, so for [code]http://somehost.com/index.php[/code], it is [code]index.php[/code].
+ Headers are HTTP request headers. For available HTTP methods, see [code]METHOD_*[/code].
+ Sends the body data raw, as a byte array and does not encode it in any way.
</description>
</method>
<method name="set_blocking_mode">
@@ -184,7 +186,7 @@
<argument index="0" name="connection" type="StreamPeer">
</argument>
<description>
- Set connection to use, for this client.
+ Sets connection to use for this client.
</description>
</method>
<method name="set_read_chunk_size">
@@ -199,140 +201,208 @@
</methods>
<constants>
<constant name="METHOD_GET" value="0" enum="Method">
+ HTTP GET method. The GET method requests a representation of the specified resource. Requests using GET should only retrieve data.
</constant>
<constant name="METHOD_HEAD" value="1" enum="Method">
+ HTTP HEAD method. The HEAD method asks for a response identical to that of a GET request, but without the response body. This is useful to request metadata like HTTP headers or to check if a resource exists.
</constant>
<constant name="METHOD_POST" value="2" enum="Method">
+ HTTP POST method. The POST method is used to submit an entity to the specified resource, often causing a change in state or side effects on the server. This is often used for forms and submitting data or uploading files.
</constant>
<constant name="METHOD_PUT" value="3" enum="Method">
+ HTTP PUT method. The PUT method asks to replace all current representations of the target resource with the request payload. (You can think of [code]POST[/code] as "create or update" and [code]PUT[/code] as "update", although many services tend to not make a clear distinction or change their meaning).
</constant>
<constant name="METHOD_DELETE" value="4" enum="Method">
+ HTTP DELETE method. The DELETE method requests to delete the specified resource.
</constant>
<constant name="METHOD_OPTIONS" value="5" enum="Method">
+ HTTP OPTIONS method. The OPTIONS method asks for a description of the communication options for the target resource. Rarely used.
</constant>
<constant name="METHOD_TRACE" value="6" enum="Method">
+ HTTP TRACE method. The TRACE method performs a message loop-back test along the path to the target resource. Returns the entire HTTP request received in the response body. Rarely used.
</constant>
<constant name="METHOD_CONNECT" value="7" enum="Method">
+ HTTP CONNECT method. The CONNECT method establishes a tunnel to the server identified by the target resource. Rarely used.
</constant>
<constant name="METHOD_MAX" value="8" enum="Method">
+ Marker for end of [code]METHOD_*[/code] enum. Not used.
</constant>
<constant name="STATUS_DISCONNECTED" value="0" enum="Status">
+ Status: Disconnected from the server.
</constant>
<constant name="STATUS_RESOLVING" value="1" enum="Status">
+ Status: Currently resolving the hostname for the given URL into an IP.
</constant>
<constant name="STATUS_CANT_RESOLVE" value="2" enum="Status">
+ Status: DNS failure: Can't resolve the hostname for the given URL.
</constant>
<constant name="STATUS_CONNECTING" value="3" enum="Status">
+ Status: Currently connecting to server.
</constant>
<constant name="STATUS_CANT_CONNECT" value="4" enum="Status">
+ Status: Can't connect to the server.
</constant>
<constant name="STATUS_CONNECTED" value="5" enum="Status">
+ Status: Connection established.
</constant>
<constant name="STATUS_REQUESTING" value="6" enum="Status">
+ Status: Currently sending request.
</constant>
<constant name="STATUS_BODY" value="7" enum="Status">
+ Status: HTTP body received.
</constant>
<constant name="STATUS_CONNECTION_ERROR" value="8" enum="Status">
+ Status: Error in HTTP connection.
</constant>
<constant name="STATUS_SSL_HANDSHAKE_ERROR" value="9" enum="Status">
+ Status: Error in SSL handshake.
</constant>
<constant name="RESPONSE_CONTINUE" value="100" enum="ResponseCode">
+ HTTP status code [code]100 Continue[/code]. Interim response that indicates everything so far is OK and that the client should continue with the request (or ignore this status if already finished).
</constant>
<constant name="RESPONSE_SWITCHING_PROTOCOLS" value="101" enum="ResponseCode">
+ HTTP status code [code]101 Switching Protocol[/code]. Sent in response to an [code]Upgrade[/code] request header by the client. Indicates the protocol the server is switching to.
</constant>
<constant name="RESPONSE_PROCESSING" value="102" enum="ResponseCode">
+ HTTP status code [code]102 Processing[/code] (WebDAV). Indicates that the server has received and is processing the request, but no response is available yet.
</constant>
<constant name="RESPONSE_OK" value="200" enum="ResponseCode">
+ HTTP status code [code]200 OK[/code]. The request has succeeded. Default response for successful requests. Meaning varies depending on the request. GET: The resource has been fetched and is transmitted in the message body. HEAD: The entity headers are in the message body. POST: The resource describing the result of the action is transmitted in the message body. TRACE: The message body contains the request message as received by the server.
</constant>
<constant name="RESPONSE_CREATED" value="201" enum="ResponseCode">
+ HTTP status code [code]201 Created[/code]. The request has succeeded and a new resource has been created as a result of it. This is typically the response sent after a PUT request.
</constant>
<constant name="RESPONSE_ACCEPTED" value="202" enum="ResponseCode">
+ HTTP status code [code]202 Accepted[/code]. The request has been received but not yet acted upon. It is non-committal, meaning that there is no way in HTTP to later send an asynchronous response indicating the outcome of processing the request. It is intended for cases where another process or server handles the request, or for batch processing.
</constant>
<constant name="RESPONSE_NON_AUTHORITATIVE_INFORMATION" value="203" enum="ResponseCode">
+ HTTP status code [code]203 Non-Authoritative Information[/code]. This response code means returned meta-information set is not exact set as available from the origin server, but collected from a local or a third party copy. Except this condition, 200 OK response should be preferred instead of this response.
</constant>
<constant name="RESPONSE_NO_CONTENT" value="204" enum="ResponseCode">
+ HTTP status code [code]204 No Content[/code]. There is no content to send for this request, but the headers may be useful. The user-agent may update its cached headers for this resource with the new ones.
</constant>
<constant name="RESPONSE_RESET_CONTENT" value="205" enum="ResponseCode">
+ HTTP status code [code]205 Reset Content[/code]. The server has fulfilled the request and desires that the client resets the "document view" that caused the request to be sent to its original state as received from the origin server.
</constant>
<constant name="RESPONSE_PARTIAL_CONTENT" value="206" enum="ResponseCode">
+ HTTP status code [code]206 Partial Content[/code]. This response code is used because of a range header sent by the client to separate download into multiple streams.
</constant>
<constant name="RESPONSE_MULTI_STATUS" value="207" enum="ResponseCode">
+ HTTP status code [code]207 Multi-Status[/code] (WebDAV). A Multi-Status response conveys information about multiple resources in situations where multiple status codes might be appropriate.
</constant>
<constant name="RESPONSE_IM_USED" value="226" enum="ResponseCode">
+ HTTP status code [code]226 IM Used[/code] (WebDAV). The server has fulfilled a GET request for the resource, and the response is a representation of the result of one or more instance-manipulations applied to the current instance.
</constant>
<constant name="RESPONSE_MULTIPLE_CHOICES" value="300" enum="ResponseCode">
+ HTTP status code [code]300 Multiple Choice[/code]. The request has more than one possible responses and there is no standardized way to choose one of the responses. User-agent or user should choose one of them.
</constant>
<constant name="RESPONSE_MOVED_PERMANENTLY" value="301" enum="ResponseCode">
+ HTTP status code [code]301 Moved Permanently[/code]. Redirection. This response code means the URI of requested resource has been changed. The new URI is usually included in the response.
</constant>
<constant name="RESPONSE_FOUND" value="302" enum="ResponseCode">
+ HTTP status code [code]302 Found[/code]. Temporary redirection. This response code means the URI of requested resource has been changed temporarily. New changes in the URI might be made in the future. Therefore, this same URI should be used by the client in future requests.
</constant>
<constant name="RESPONSE_SEE_OTHER" value="303" enum="ResponseCode">
+ HTTP status code [code]303 See Other[/code]. The server is redirecting the user agent to a different resource, as indicated by a URI in the Location header field, which is intended to provide an indirect response to the original request.
</constant>
<constant name="RESPONSE_NOT_MODIFIED" value="304" enum="ResponseCode">
+ HTTP status code [code]304 Not Modified[/code]. A conditional GET or HEAD request has been received and would have resulted in a 200 OK response if it were not for the fact that the condition evaluated to false.
</constant>
<constant name="RESPONSE_USE_PROXY" value="305" enum="ResponseCode">
+ HTTP status code [code]305 Use Proxy[/code]. Deprecated. Do not use.
</constant>
<constant name="RESPONSE_TEMPORARY_REDIRECT" value="307" enum="ResponseCode">
+ HTTP status code [code]307 Temporary Redirect[/code]. The target resource resides temporarily under a different URI and the user agent MUST NOT change the request method if it performs an automatic redirection to that URI.
</constant>
<constant name="RESPONSE_BAD_REQUEST" value="400" enum="ResponseCode">
+ HTTP status code [code]400 Bad Request[/code]. The request was invalid. The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, invalid request contents, or deceptive request routing).
</constant>
<constant name="RESPONSE_UNAUTHORIZED" value="401" enum="ResponseCode">
+ HTTP status code [code]401 Unauthorized[/code]. Credentials required. The request has not been applied because it lacks valid authentication credentials for the target resource.
</constant>
<constant name="RESPONSE_PAYMENT_REQUIRED" value="402" enum="ResponseCode">
+ HTTP status code [code]402 Payment Required[/code]. This response code is reserved for future use. Initial aim for creating this code was using it for digital payment systems, however this is not currently used.
</constant>
<constant name="RESPONSE_FORBIDDEN" value="403" enum="ResponseCode">
+ HTTP status code [code]403 Forbidden[/code]. The client does not have access rights to the content, i.e. they are unauthorized, so server is rejecting to give proper response. Unlike [code]401[/code], the client's identity is known to the server.
</constant>
<constant name="RESPONSE_NOT_FOUND" value="404" enum="ResponseCode">
+ HTTP status code [code]404 Not Found[/code]. The server can not find requested resource. Either the URL is not recognized or the endpoint is valid but the resource itself does not exist. May also be sent instead of 403 to hide existence of a resource if the client is not authorized.
</constant>
<constant name="RESPONSE_METHOD_NOT_ALLOWED" value="405" enum="ResponseCode">
+ HTTP status code [code]405 Method Not Allowed[/code]. The request's HTTP method is known by the server but has been disabled and cannot be used. For example, an API may forbid DELETE-ing a resource. The two mandatory methods, GET and HEAD, must never be disabled and should not return this error code.
</constant>
<constant name="RESPONSE_NOT_ACCEPTABLE" value="406" enum="ResponseCode">
+ HTTP status code [code]406 Not Acceptable[/code]. The target resource does not have a current representation that would be acceptable to the user agent, according to the proactive negotiation header fields received in the request. Used when negotiation content.
</constant>
<constant name="RESPONSE_PROXY_AUTHENTICATION_REQUIRED" value="407" enum="ResponseCode">
+ HTTP status code [code]407 Proxy Authentication Required[/code]. Similar to 401 Unauthorized, but it indicates that the client needs to authenticate itself in order to use a proxy.
</constant>
<constant name="RESPONSE_REQUEST_TIMEOUT" value="408" enum="ResponseCode">
+ HTTP status code [code]408 Request Timeout[/code]. The server did not receive a complete request message within the time that it was prepared to wait.
</constant>
<constant name="RESPONSE_CONFLICT" value="409" enum="ResponseCode">
+ HTTP status code [code]409 Conflict[/code]. The request could not be completed due to a conflict with the current state of the target resource. This code is used in situations where the user might be able to resolve the conflict and resubmit the request.
</constant>
<constant name="RESPONSE_GONE" value="410" enum="ResponseCode">
+ HTTP status code [code]410 Gone[/code]. The target resource is no longer available at the origin server and this condition is likely permanent.
</constant>
<constant name="RESPONSE_LENGTH_REQUIRED" value="411" enum="ResponseCode">
+ HTTP status code [code]411 Length Required[/code]. The server refuses to accept the request without a defined Content-Length header.
</constant>
<constant name="RESPONSE_PRECONDITION_FAILED" value="412" enum="ResponseCode">
+ HTTP status code [code]412 Precondition Failed[/code]. One or more conditions given in the request header fields evaluated to false when tested on the server.
</constant>
<constant name="RESPONSE_REQUEST_ENTITY_TOO_LARGE" value="413" enum="ResponseCode">
+ HTTP status code [code]413 Entity Too Large[/code]. The server is refusing to process a request because the request payload is larger than the server is willing or able to process.
</constant>
<constant name="RESPONSE_REQUEST_URI_TOO_LONG" value="414" enum="ResponseCode">
+ HTTP status code [code]414 Request-URI Too Long[/code]. The server is refusing to service the request because the request-target is longer than the server is willing to interpret.
</constant>
<constant name="RESPONSE_UNSUPPORTED_MEDIA_TYPE" value="415" enum="ResponseCode">
+ HTTP status code [code]415 Unsupported Media Type[/code]. The origin server is refusing to service the request because the payload is in a format not supported by this method on the target resource.
</constant>
<constant name="RESPONSE_REQUESTED_RANGE_NOT_SATISFIABLE" value="416" enum="ResponseCode">
+ HTTP status code [code]416 Requested Range Not Satisfiable[/code]. None of the ranges in the request's Range header field overlap the current extent of the selected resource or the set of ranges requested has been rejected due to invalid ranges or an excessive request of small or overlapping ranges.
</constant>
<constant name="RESPONSE_EXPECTATION_FAILED" value="417" enum="ResponseCode">
+ HTTP status code [code]417 Expectation Failed[/code]. The expectation given in the request's Expect header field could not be met by at least one of the inbound servers.
</constant>
<constant name="RESPONSE_UNPROCESSABLE_ENTITY" value="422" enum="ResponseCode">
+ HTTP status code [code]422 Unprocessable Entity[/code] (WebDAV). The server understands the content type of the request entity (hence a 415 Unsupported Media Type status code is inappropriate), and the syntax of the request entity is correct (thus a 400 Bad Request status code is inappropriate) but was unable to process the contained instructions.
</constant>
<constant name="RESPONSE_LOCKED" value="423" enum="ResponseCode">
+ HTTP status code [code]423 Locked[/code] (WebDAV). The source or destination resource of a method is locked.
</constant>
<constant name="RESPONSE_FAILED_DEPENDENCY" value="424" enum="ResponseCode">
+ HTTP status code [code]424 Failed Dependency[/code] (WebDAV). The method could not be performed on the resource because the requested action depended on another action and that action failed.
</constant>
<constant name="RESPONSE_UPGRADE_REQUIRED" value="426" enum="ResponseCode">
+ HTTP status code [code]426 Upgrade Required[/code]. The server refuses to perform the request using the current protocol but might be willing to do so after the client upgrades to a different protocol.
</constant>
<constant name="RESPONSE_INTERNAL_SERVER_ERROR" value="500" enum="ResponseCode">
+ HTTP status code [code]500 Internal Server Error[/code]. The server encountered an unexpected condition that prevented it from fulfilling the request.
</constant>
<constant name="RESPONSE_NOT_IMPLEMENTED" value="501" enum="ResponseCode">
+ HTTP status code [code]501 Not Implemented[/code]. The server does not support the functionality required to fulfill the request.
</constant>
<constant name="RESPONSE_BAD_GATEWAY" value="502" enum="ResponseCode">
+ HTTP status code [code]502 Bad Gateway[/code]. The server, while acting as a gateway or proxy, received an invalid response from an inbound server it accessed while attempting to fulfill the request. Usually returned by load balancers or proxies.
</constant>
<constant name="RESPONSE_SERVICE_UNAVAILABLE" value="503" enum="ResponseCode">
+ HTTP status code [code]503 Service Unavailable[/code]. The server is currently unable to handle the request due to a temporary overload or scheduled maintenance, which will likely be alleviated after some delay. Try again later.
</constant>
<constant name="RESPONSE_GATEWAY_TIMEOUT" value="504" enum="ResponseCode">
+ HTTP status code [code]504 Gateway Timeout[/code]. The server, while acting as a gateway or proxy, did not receive a timely response from an upstream server it needed to access in order to complete the request. Usually returned by load balancers or proxies.
</constant>
<constant name="RESPONSE_HTTP_VERSION_NOT_SUPPORTED" value="505" enum="ResponseCode">
+ HTTP status code [code]505 HTTP Version Not Supported[/code]. The server does not support, or refuses to support, the major version of HTTP that was used in the request message.
</constant>
<constant name="RESPONSE_INSUFFICIENT_STORAGE" value="507" enum="ResponseCode">
+ HTTP status code [code]507 Insufficient Storage[/code]. The method could not be performed on the resource because the server is unable to store the representation needed to successfully complete the request.
</constant>
<constant name="RESPONSE_NOT_EXTENDED" value="510" enum="ResponseCode">
+ HTTP status code [code]510 Not Extended[/code]. The policy for accessing the resource has not been met in the request. The server should send back all the information necessary for the client to issue an extended request.
</constant>
</constants>
</class>
diff --git a/doc/classes/HTTPRequest.xml b/doc/classes/HTTPRequest.xml
index 7c37479295..985198c76f 100644
--- a/doc/classes/HTTPRequest.xml
+++ b/doc/classes/HTTPRequest.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="HTTPRequest" inherits="Node" category="Core" version="3.0-beta">
<brief_description>
- A Node with the ability to send HTTP requests.
+ A node with the ability to send HTTP requests.
</brief_description>
<description>
- A Node with the ability to send HTTP requests. Uses a [HTTPClient] internally, supports HTTPS.
- Can be used to make HTTP requests or download files via HTTP.
+ A node with the ability to send HTTP requests. Uses [HTTPClient] internally.
+ Can be used to make HTTP requests, i.e. download or upload files or web content via HTTP.
</description>
<tutorials>
</tutorials>
@@ -16,35 +16,35 @@
<return type="void">
</return>
<description>
- Cancel the current request.
+ Cancels the current request.
</description>
</method>
<method name="get_body_size" qualifiers="const">
<return type="int">
</return>
<description>
- Return the response body length.
+ Returns the response body length.
</description>
</method>
<method name="get_download_file" qualifiers="const">
<return type="String">
</return>
<description>
- Return the file this request will download into.
+ Returns the file this request will download into.
</description>
</method>
<method name="get_downloaded_bytes" qualifiers="const">
<return type="int">
</return>
<description>
- Return the amount of bytes this HTTPRequest downloaded.
+ Returns the amount of bytes this HTTPRequest downloaded.
</description>
</method>
<method name="get_http_client_status" qualifiers="const">
<return type="int" enum="HTTPClient.Status">
</return>
<description>
- Return the current status of the underlying [HTTPClient].
+ Returns the current status of the underlying [HTTPClient]. See [code]STATUS_*[/code] enum on [HTTPClient].
</description>
</method>
<method name="request">
@@ -69,16 +69,19 @@
<argument index="0" name="path" type="String">
</argument>
<description>
- Set the file to download into. Outputs the response body into the file.
+ Sets the file to download into. Outputs the response body into the file if set.
</description>
</method>
</methods>
<members>
<member name="body_size_limit" type="int" setter="set_body_size_limit" getter="get_body_size_limit">
+ Maximum allowed size for response bodies.
</member>
<member name="max_redirects" type="int" setter="set_max_redirects" getter="get_max_redirects">
+ Maximum number of allowed redirects.
</member>
<member name="use_threads" type="bool" setter="set_use_threads" getter="is_using_threads">
+ If [code]true[/code] multithreading is used to improve performance.
</member>
</members>
<signals>
@@ -121,7 +124,7 @@
Request exceeded its maximum size limit, see [method set_body_size_limit].
</constant>
<constant name="RESULT_REQUEST_FAILED" value="8" enum="Result">
- Request failed. (unused)
+ Request failed. (Unused)
</constant>
<constant name="RESULT_DOWNLOAD_FILE_CANT_OPEN" value="9" enum="Result">
HTTPRequest couldn't open the download file.
diff --git a/doc/classes/IP.xml b/doc/classes/IP.xml
index 09734e746c..cd669e3de1 100644
--- a/doc/classes/IP.xml
+++ b/doc/classes/IP.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="IP" inherits="Object" category="Core" version="3.0-beta">
<brief_description>
- IP Protocol support functions.
+ Internet protocol (IP) support functions like DNS resolution.
</brief_description>
<description>
- IP contains support functions for the IPv4 protocol. TCP/IP support is in different classes (see [StreamPeerTCP] and [TCP_Server]). IP provides hostname resolution support, both blocking and threaded.
+ IP contains support functions for the Internet Protocol (IP). TCP/IP support is in different classes (see [StreamPeerTCP] and [TCP_Server]). IP provides DNS hostname resolution support, both blocking and threaded.
</description>
<tutorials>
</tutorials>
@@ -79,24 +79,34 @@
</methods>
<constants>
<constant name="RESOLVER_STATUS_NONE" value="0" enum="ResolverStatus">
+ DNS hostname resolver status: No status.
</constant>
<constant name="RESOLVER_STATUS_WAITING" value="1" enum="ResolverStatus">
+ DNS hostname resolver status: Waiting.
</constant>
<constant name="RESOLVER_STATUS_DONE" value="2" enum="ResolverStatus">
+ DNS hostname resolver status: Done.
</constant>
<constant name="RESOLVER_STATUS_ERROR" value="3" enum="ResolverStatus">
+ DNS hostname resolver status: Error.
</constant>
<constant name="RESOLVER_MAX_QUERIES" value="32">
+ Maximum number of concurrent DNS resolver queries allowed, [code]RESOLVER_INVALID_ID[/code] is returned if exceeded.
</constant>
<constant name="RESOLVER_INVALID_ID" value="-1">
+ Invalid ID constant. Returned if [code]RESOLVER_MAX_QUERIES[/code] is exceeded.
</constant>
<constant name="TYPE_NONE" value="0" enum="Type">
+ Address type: None.
</constant>
<constant name="TYPE_IPV4" value="1" enum="Type">
+ Address type: Internet protocol version 4 (IPv4).
</constant>
<constant name="TYPE_IPV6" value="2" enum="Type">
+ Address type: Internet protocol version 6 (IPv6).
</constant>
<constant name="TYPE_ANY" value="3" enum="Type">
+ Address type: Any.
</constant>
</constants>
</class>
diff --git a/doc/classes/IP_Unix.xml b/doc/classes/IP_Unix.xml
index 28e8a3804b..1d376c7233 100644
--- a/doc/classes/IP_Unix.xml
+++ b/doc/classes/IP_Unix.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="IP_Unix" inherits="IP" category="Core" version="3.0-beta">
<brief_description>
+ Unix IP support. See [IP].
</brief_description>
<description>
+ Unix-specific implementation of IP support functions. See [IP].
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/KinematicBody.xml b/doc/classes/KinematicBody.xml
index c5204fd0bf..d1dc236d40 100644
--- a/doc/classes/KinematicBody.xml
+++ b/doc/classes/KinematicBody.xml
@@ -102,6 +102,18 @@
</method>
</methods>
<members>
+ <member name="axis_lock_angular_x" type="bool" setter="set_axis_lock" getter="get_axis_lock">
+ </member>
+ <member name="axis_lock_angular_y" type="bool" setter="set_axis_lock" getter="get_axis_lock">
+ </member>
+ <member name="axis_lock_angular_z" type="bool" setter="set_axis_lock" getter="get_axis_lock">
+ </member>
+ <member name="axis_lock_linear_x" type="bool" setter="set_axis_lock" getter="get_axis_lock">
+ </member>
+ <member name="axis_lock_linear_y" type="bool" setter="set_axis_lock" getter="get_axis_lock">
+ </member>
+ <member name="axis_lock_linear_z" type="bool" setter="set_axis_lock" getter="get_axis_lock">
+ </member>
<member name="collision/safe_margin" type="float" setter="set_safe_margin" getter="get_safe_margin">
If the body is at least this close to another body, this body will consider them to be colliding.
</member>
diff --git a/doc/classes/Mesh.xml b/doc/classes/Mesh.xml
index c681886546..465b68171e 100644
--- a/doc/classes/Mesh.xml
+++ b/doc/classes/Mesh.xml
@@ -49,6 +49,10 @@
</description>
</method>
</methods>
+ <members>
+ <member name="lightmap_size_hint" type="Vector2" setter="set_lightmap_size_hint" getter="get_lightmap_size_hint">
+ </member>
+ </members>
<constants>
<constant name="PRIMITIVE_POINTS" value="0" enum="PrimitiveType">
Render array as points (one vertex equals one point).
diff --git a/doc/classes/MeshInstance.xml b/doc/classes/MeshInstance.xml
index f754341fef..9273e87430 100644
--- a/doc/classes/MeshInstance.xml
+++ b/doc/classes/MeshInstance.xml
@@ -4,7 +4,7 @@
Node that instances meshes into a scenario.
</brief_description>
<description>
- MeshInstance is a [Node] that takes a [Mesh] resource and adds it to the current scenario by creating an instance of it. This is the class most often used to get 3D geometry rendered and can be used to instance a single [Mesh] in many places. This allows to reuse geometry and save on resources. When a [Mesh] has to be instanced more than thousands of times at close proximity, consider using a [MultiMesh] in a [MultiMeshInstance] instead.
+ MeshInstance is a node that takes a [Mesh] resource and adds it to the current scenario by creating an instance of it. This is the class most often used to get 3D geometry rendered and can be used to instance a single [Mesh] in many places. This allows to reuse geometry and save on resources. When a [Mesh] has to be instanced more than thousands of times at close proximity, consider using a [MultiMesh] in a [MultiMeshInstance] instead.
</description>
<tutorials>
</tutorials>
@@ -15,20 +15,21 @@
<return type="void">
</return>
<description>
- This helper creates a [StaticBody] child [Node] with a [ConvexPolygonShape] [CollisionShape] calculated from the mesh geometry. It's mainly used for testing.
+ This helper creates a [StaticBody] child node with a [ConvexPolygonShape] collision shape calculated from the mesh geometry. It's mainly used for testing.
</description>
</method>
<method name="create_debug_tangents">
<return type="void">
</return>
<description>
+ This helper creates a [MeshInstance] child node with gizmos at every vertex calculated from the mesh geometry. It's mainly used for testing.
</description>
</method>
<method name="create_trimesh_collision">
<return type="void">
</return>
<description>
- This helper creates a [StaticBody] child [Node] with a [ConcavePolygonShape] [CollisionShape] calculated from the mesh geometry. It's mainly used for testing.
+ This helper creates a [StaticBody] child node with a [ConcavePolygonShape] collision shape calculated from the mesh geometry. It's mainly used for testing.
</description>
</method>
<method name="get_surface_material" qualifiers="const">
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index e2198c3e15..78591e2bf8 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -498,7 +498,7 @@
<return type="void">
</return>
<description>
- Removes a node and set all its children as children of the parent node (if exists). All even subscriptions that pass by the removed node will be unsubscribed.
+ Removes a node and set all its children as children of the parent node (if exists). All event subscriptions that pass by the removed node will be unsubscribed.
</description>
</method>
<method name="remove_child">
diff --git a/doc/classes/PhysicsServer.xml b/doc/classes/PhysicsServer.xml
index eb7c735277..534449a94b 100644
--- a/doc/classes/PhysicsServer.xml
+++ b/doc/classes/PhysicsServer.xml
@@ -351,15 +351,6 @@
Creates a physics body. The first parameter can be any value from constants BODY_MODE*, for the type of body created. Additionally, the body can be created in sleeping state to save processing time.
</description>
</method>
- <method name="body_get_axis_lock" qualifiers="const">
- <return type="int" enum="PhysicsServer.BodyAxisLock">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- Gets the information, which Axis is locked if any. The can be any calue from the constants BODY_AXIS_LOCK*
- </description>
- </method>
<method name="body_get_collision_layer" qualifiers="const">
<return type="int">
</return>
@@ -485,6 +476,16 @@
Returns a body state.
</description>
</method>
+ <method name="body_is_axis_locked" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="body" type="RID">
+ </argument>
+ <argument index="1" name="axis" type="int" enum="PhysicsServer.BodyAxis">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="body_is_continuous_collision_detection_enabled" qualifiers="const">
<return type="bool">
</return>
@@ -540,10 +541,11 @@
</return>
<argument index="0" name="body" type="RID">
</argument>
- <argument index="1" name="axis" type="int" enum="PhysicsServer.BodyAxisLock">
+ <argument index="1" name="axis" type="int" enum="PhysicsServer.BodyAxis">
+ </argument>
+ <argument index="2" name="lock" type="bool">
</argument>
<description>
- Locks velocity along one axis to 0 and only allows rotation along this axis, can also be set to disabled which disables this functionality.
</description>
</method>
<method name="body_set_axis_velocity">
@@ -1519,17 +1521,17 @@
<constant name="SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS" value="7" enum="SpaceParameter">
Constant to set/get the default solver bias for all physics constraints. A solver bias is a factor controlling how much two objects "rebound", after violating a constraint, to avoid leaving them in that state because of numerical imprecision.
</constant>
- <constant name="BODY_AXIS_LOCK_DISABLED" value="0" enum="BodyAxisLock">
- The [Body] can rotate and move freely.
+ <constant name="BODY_AXIS_LINEAR_X" value="1" enum="BodyAxis">
+ </constant>
+ <constant name="BODY_AXIS_LINEAR_Y" value="2" enum="BodyAxis">
+ </constant>
+ <constant name="BODY_AXIS_LINEAR_Z" value="4" enum="BodyAxis">
</constant>
- <constant name="BODY_AXIS_LOCK_X" value="1" enum="BodyAxisLock">
- The [Body] cannot move across x axis can only rotate across x axis.
+ <constant name="BODY_AXIS_ANGULAR_X" value="8" enum="BodyAxis">
</constant>
- <constant name="BODY_AXIS_LOCK_Y" value="2" enum="BodyAxisLock">
- The [Body] cannot move across y axis can only rotate across y axis.
+ <constant name="BODY_AXIS_ANGULAR_Y" value="16" enum="BodyAxis">
</constant>
- <constant name="BODY_AXIS_LOCK_Z" value="3" enum="BodyAxisLock">
- The [Body] cannot move across z axis can only rotate across z axis.
+ <constant name="BODY_AXIS_ANGULAR_Z" value="32" enum="BodyAxis">
</constant>
</constants>
</class>
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index 7071d64f2e..42ed57e4af 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -233,6 +233,12 @@
<description>
</description>
</method>
+ <method name="is_hide_on_state_item_selection" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="is_item_checkable" qualifiers="const">
<return type="bool">
</return>
@@ -278,6 +284,14 @@
Removes the item at index "idx" from the menu. Note that the indexes of items after the removed item are going to be shifted by one.
</description>
</method>
+ <method name="set_hide_on_state_item_selection">
+ <return type="void">
+ </return>
+ <argument index="0" name="enable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_item_accelerator">
<return type="void">
</return>
@@ -377,6 +391,16 @@
<description>
</description>
</method>
+ <method name="set_item_statable">
+ <return type="void">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <argument index="1" name="state" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_item_submenu">
<return type="void">
</return>
@@ -417,6 +441,14 @@
<description>
</description>
</method>
+ <method name="toggle_item_statable">
+ <return type="void">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<members>
<member name="hide_on_checkable_item_selection" type="bool" setter="set_hide_on_checkable_item_selection" getter="is_hide_on_checkable_item_selection">
diff --git a/doc/classes/Rect2.xml b/doc/classes/Rect2.xml
index 1bd2e812e6..4fc9e5bd71 100644
--- a/doc/classes/Rect2.xml
+++ b/doc/classes/Rect2.xml
@@ -37,6 +37,12 @@
Constructs a [code]Rect2[/code] by x, y, width, and height.
</description>
</method>
+ <method name="abs">
+ <return type="Rect2">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="clip">
<return type="Rect2">
</return>
diff --git a/doc/classes/RigidBody.xml b/doc/classes/RigidBody.xml
index cfcd0258e7..3c54f29c15 100644
--- a/doc/classes/RigidBody.xml
+++ b/doc/classes/RigidBody.xml
@@ -59,8 +59,17 @@
<member name="angular_velocity" type="Vector3" setter="set_angular_velocity" getter="get_angular_velocity">
RigidBody's rotational velocity.
</member>
- <member name="axis_lock" type="int" setter="set_axis_lock" getter="get_axis_lock" enum="RigidBody.AxisLock">
- Locks the rotational forces to a particular axis, preventing rotations on other axes.
+ <member name="axis_lock_angular_x" type="bool" setter="set_axis_lock" getter="get_axis_lock">
+ </member>
+ <member name="axis_lock_angular_y" type="bool" setter="set_axis_lock" getter="get_axis_lock">
+ </member>
+ <member name="axis_lock_angular_z" type="bool" setter="set_axis_lock" getter="get_axis_lock">
+ </member>
+ <member name="axis_lock_linear_x" type="bool" setter="set_axis_lock" getter="get_axis_lock">
+ </member>
+ <member name="axis_lock_linear_y" type="bool" setter="set_axis_lock" getter="get_axis_lock">
+ </member>
+ <member name="axis_lock_linear_z" type="bool" setter="set_axis_lock" getter="get_axis_lock">
</member>
<member name="bounce" type="float" setter="set_bounce" getter="get_bounce">
RigidBody's bounciness.
@@ -168,13 +177,5 @@
<constant name="MODE_KINEMATIC" value="3" enum="Mode">
Kinematic body. The body behaves like a [KinematicBody], and can only move by user code.
</constant>
- <constant name="AXIS_LOCK_DISABLED" value="0" enum="AxisLock">
- </constant>
- <constant name="AXIS_LOCK_X" value="1" enum="AxisLock">
- </constant>
- <constant name="AXIS_LOCK_Y" value="2" enum="AxisLock">
- </constant>
- <constant name="AXIS_LOCK_Z" value="3" enum="AxisLock">
- </constant>
</constants>
</class>
diff --git a/doc/classes/SurfaceTool.xml b/doc/classes/SurfaceTool.xml
index 22099a930c..0916d0b928 100644
--- a/doc/classes/SurfaceTool.xml
+++ b/doc/classes/SurfaceTool.xml
@@ -170,6 +170,8 @@
</return>
<argument index="0" name="existing" type="ArrayMesh" default="null">
</argument>
+ <argument index="1" name="flags" type="int" default="97792">
+ </argument>
<description>
Returns a constructed [ArrayMesh] from current information passed in. If an existing [ArrayMesh] is passed in as an argument, will add an extra surface to the existing [ArrayMesh].
</description>
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index df48ba3e23..da30c4c7bd 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -305,6 +305,15 @@
Enable text wrapping when it goes beyond he edge of what is visible.
</description>
</method>
+ <method name="toggle_fold_line">
+ <return type="void">
+ </return>
+ <argument index="0" name="line" type="int">
+ </argument>
+ <description>
+ Toggle the folding of the code block at the given line.
+ </description>
+ </method>
<method name="undo">
<return type="void">
</return>
@@ -428,6 +437,8 @@
</theme_item>
<theme_item name="caret_color" type="Color">
</theme_item>
+ <theme_item name="code_folding_color" type="Color">
+ </theme_item>
<theme_item name="completion" type="StyleBox">
</theme_item>
<theme_item name="completion_background_color" type="Color">
diff --git a/doc/classes/Texture.xml b/doc/classes/Texture.xml
index 855a8f12de..bf27bc4768 100644
--- a/doc/classes/Texture.xml
+++ b/doc/classes/Texture.xml
@@ -117,22 +117,26 @@
</methods>
<constants>
<constant name="FLAG_MIPMAPS" value="1" enum="Flags">
- Generate mipmaps, to enable smooth zooming out of the texture.
+ Generate mipmaps, which are smaller versions of the same texture to use when zoomed out, keeping the aspect ratio.
</constant>
<constant name="FLAG_REPEAT" value="2" enum="Flags">
- Repeat (instead of clamp to edge).
+ Repeats texture (instead of clamp to edge).
</constant>
<constant name="FLAG_FILTER" value="4" enum="Flags">
- Turn on magnifying filter, to enable smooth zooming in of the texture.
+ Magnifying filter, to enable smooth zooming in of the texture.
</constant>
<constant name="FLAGS_DEFAULT" value="7" enum="Flags">
Default flags. Generate mipmaps, repeat, and filter are enabled.
</constant>
<constant name="FLAG_ANISOTROPIC_FILTER" value="8" enum="Flags">
+ Anisotropic mipmap filtering. Generates smaller versions of the same texture with different aspect ratios.
+ More effective on planes often shown going to the horrizon as those textures (Walls or Ground for example) get squashed in the viewport to different aspect ratios and regular mipmaps keep the aspect ratio so they don't optimize storage that well in those cases.
</constant>
<constant name="FLAG_CONVERT_TO_LINEAR" value="16" enum="Flags">
+ Converts texture to SRGB color space.
</constant>
<constant name="FLAG_MIRRORED_REPEAT" value="32" enum="Flags">
+ Repeats texture with alternate sections mirrored.
</constant>
<constant name="FLAG_VIDEO_SURFACE" value="4096" enum="Flags">
Texture is a video surface.
diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml
index e58ab3dd25..72cd56dc55 100644
--- a/doc/classes/TileMap.xml
+++ b/doc/classes/TileMap.xml
@@ -38,20 +38,6 @@
Return the tile index of the cell referenced by a Vector2.
</description>
</method>
- <method name="get_center_x" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- Return true if tiles are to be centered in x coordinate (by default this is false and they are drawn from upper left cell corner).
- </description>
- </method>
- <method name="get_center_y" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- Return true if tiles are to be centered in y coordinate (by default this is false and they are drawn from upper left cell corner).
- </description>
- </method>
<method name="get_collision_layer_bit" qualifiers="const">
<return type="bool">
</return>
@@ -176,24 +162,6 @@
Optionally, the tile can also be flipped over the X and Y axes or transposed.
</description>
</method>
- <method name="set_center_x">
- <return type="void">
- </return>
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- Set tiles to be centered in x coordinate. (by default this is false and they are drawn from upper left cell corner).
- </description>
- </method>
- <method name="set_center_y">
- <return type="void">
- </return>
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- Set tiles to be centered in y coordinate. (by default this is false and they are drawn from upper left cell corner).
- </description>
- </method>
<method name="set_collision_layer_bit">
<return type="void">
</return>
diff --git a/doc/classes/TileSet.xml b/doc/classes/TileSet.xml
index 6a147a9646..3dbf172c5a 100644
--- a/doc/classes/TileSet.xml
+++ b/doc/classes/TileSet.xml
@@ -13,7 +13,7 @@
</demos>
<methods>
<method name="_forward_subtile_selection" qualifiers="virtual">
- <return type="void">
+ <return type="Vector2">
</return>
<argument index="0" name="autotile_id" type="int">
</argument>
@@ -27,7 +27,7 @@
</description>
</method>
<method name="_is_tile_bound" qualifiers="virtual">
- <return type="void">
+ <return type="bool">
</return>
<argument index="0" name="drawn_id" type="int">
</argument>
diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml
index 479c0606f2..1a9dc3a669 100644
--- a/doc/classes/VisualServer.xml
+++ b/doc/classes/VisualServer.xml
@@ -24,6 +24,7 @@
<argument index="3" name="bottom" type="RID">
</argument>
<description>
+ Sets images to be rendered in the window margin.
</description>
</method>
<method name="black_bars_set_margins">
@@ -38,12 +39,14 @@
<argument index="3" name="bottom" type="int">
</argument>
<description>
+ Sets margin size, where black bars (or images, if [method black_bars_set_images] was used) are rendered.
</description>
</method>
<method name="canvas_create">
<return type="RID">
</return>
<description>
+ Creates a canvas and returns the assigned [RID].
</description>
</method>
<method name="canvas_item_add_circle">
@@ -58,6 +61,7 @@
<argument index="3" name="color" type="Color">
</argument>
<description>
+ Adds a circle command to the [CanvasItem]'s draw commands.
</description>
</method>
<method name="canvas_item_add_clip_ignore">
@@ -68,6 +72,7 @@
<argument index="1" name="ignore" type="bool">
</argument>
<description>
+ If ignore is [code]true[/code], the VisualServer does not perform clipping.
</description>
</method>
<method name="canvas_item_add_line">
@@ -86,6 +91,7 @@
<argument index="5" name="antialiased" type="bool" default="false">
</argument>
<description>
+ Adds a line command to the [CanvasItem]'s draw commands.
</description>
</method>
<method name="canvas_item_add_mesh">
@@ -98,6 +104,7 @@
<argument index="2" name="skeleton" type="RID">
</argument>
<description>
+ Adds a [Mesh] to the [CanvasItem]'s draw commands. Only affects its aabb at the moment.
</description>
</method>
<method name="canvas_item_add_multimesh">
@@ -110,6 +117,7 @@
<argument index="2" name="skeleton" type="RID">
</argument>
<description>
+ Adds a [MultiMesh] to the [CanvasItem]'s draw commands. Only affects its aabb at the moment.
</description>
</method>
<method name="canvas_item_add_nine_patch">
@@ -138,6 +146,8 @@
<argument index="10" name="normal_map" type="RID">
</argument>
<description>
+ Adds a nine patch image to the [CanvasItem]'s draw commands.
+ See [NinePatchRect] for more explanation.
</description>
</method>
<method name="canvas_item_add_particles">
@@ -156,6 +166,7 @@
<argument index="5" name="v_frames" type="int">
</argument>
<description>
+ Adds a particles system to the [CanvasItem]'s draw commands.
</description>
</method>
<method name="canvas_item_add_polygon">
@@ -176,6 +187,7 @@
<argument index="6" name="antialiased" type="bool" default="false">
</argument>
<description>
+ Adds a polygon to the [CanvasItem]'s draw commands.
</description>
</method>
<method name="canvas_item_add_polyline">
@@ -192,6 +204,7 @@
<argument index="4" name="antialiased" type="bool" default="false">
</argument>
<description>
+ Adds a polyline, which is a line from mutliple points with a width, to the [CanvasItem]'s draw commands.
</description>
</method>
<method name="canvas_item_add_primitive">
@@ -212,6 +225,7 @@
<argument index="6" name="normal_map" type="RID">
</argument>
<description>
+ Adds a primitive to the [CanvasItem]'s draw commands.
</description>
</method>
<method name="canvas_item_add_rect">
@@ -224,6 +238,7 @@
<argument index="2" name="color" type="Color">
</argument>
<description>
+ Adds a rectangle to the [CanvasItem]'s draw commands.
</description>
</method>
<method name="canvas_item_add_set_transform">
@@ -234,6 +249,8 @@
<argument index="1" name="transform" type="Transform2D">
</argument>
<description>
+ Adds a [Transform2D] command to the [CanvasItem]'s draw commands.
+ This sets the extra_matrix uniform when executed. This affects the later command's of the canvas item.
</description>
</method>
<method name="canvas_item_add_texture_rect">
@@ -254,6 +271,7 @@
<argument index="6" name="normal_map" type="RID">
</argument>
<description>
+ Adds a textured rect to the [CanvasItem]'s draw commands.
</description>
</method>
<method name="canvas_item_add_texture_rect_region">
@@ -276,6 +294,7 @@
<argument index="7" name="clip_uv" type="bool" default="true">
</argument>
<description>
+ Adds a texture rect with region setting to the [CanvasItem]'s draw commands.
</description>
</method>
<method name="canvas_item_add_triangle_array">
@@ -298,6 +317,7 @@
<argument index="7" name="normal_map" type="RID">
</argument>
<description>
+ Adds a triangle array to the [CanvasItem]'s draw commands.
</description>
</method>
<method name="canvas_item_clear">
@@ -306,12 +326,14 @@
<argument index="0" name="item" type="RID">
</argument>
<description>
+ Clears the [CanvasItem] and removes all commands in it.
</description>
</method>
<method name="canvas_item_create">
<return type="RID">
</return>
<description>
+ Creates a new [CanvasItem] and returns its [RID].
</description>
</method>
<method name="canvas_item_set_clip">
@@ -322,6 +344,7 @@
<argument index="1" name="clip" type="bool">
</argument>
<description>
+ Sets clipping for the [CanvasItem].
</description>
</method>
<method name="canvas_item_set_copy_to_backbuffer">
@@ -334,6 +357,7 @@
<argument index="2" name="rect" type="Rect2">
</argument>
<description>
+ Sets the [CanvasItem] to copy a rect to the backbuffer.
</description>
</method>
<method name="canvas_item_set_custom_rect">
@@ -346,6 +370,7 @@
<argument index="2" name="rect" type="Rect2" default="Rect2( 0, 0, 0, 0 )">
</argument>
<description>
+ Defines a custom drawing rectangle for the [CanvasItem].
</description>
</method>
<method name="canvas_item_set_distance_field_mode">
@@ -366,6 +391,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ Sets [CanvasItem] to be drawn behind its parent.
</description>
</method>
<method name="canvas_item_set_draw_index">
@@ -376,6 +402,7 @@
<argument index="1" name="index" type="int">
</argument>
<description>
+ Sets the index for the [CanvasItem].
</description>
</method>
<method name="canvas_item_set_light_mask">
@@ -386,6 +413,7 @@
<argument index="1" name="mask" type="int">
</argument>
<description>
+ The light mask. See [LightOccluder2D] for more information on light masks.
</description>
</method>
<method name="canvas_item_set_material">
@@ -396,6 +424,7 @@
<argument index="1" name="material" type="RID">
</argument>
<description>
+ Sets a new material to the [CanvasItem].
</description>
</method>
<method name="canvas_item_set_modulate">
@@ -406,6 +435,7 @@
<argument index="1" name="color" type="Color">
</argument>
<description>
+ Sets the color that modulates the [CanvasItem] and its children.
</description>
</method>
<method name="canvas_item_set_parent">
@@ -416,6 +446,7 @@
<argument index="1" name="parent" type="RID">
</argument>
<description>
+ Sets the parent for the [CanvasItem].
</description>
</method>
<method name="canvas_item_set_self_modulate">
@@ -426,6 +457,7 @@
<argument index="1" name="color" type="Color">
</argument>
<description>
+ Sets the color that modulates the [CanvasItem] without children.
</description>
</method>
<method name="canvas_item_set_sort_children_by_y">
@@ -436,6 +468,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ Sets if [CanvasItem]'s children should be sorted by y-position.
</description>
</method>
<method name="canvas_item_set_transform">
@@ -446,6 +479,7 @@
<argument index="1" name="transform" type="Transform2D">
</argument>
<description>
+ Sets the [CanvasItem]'s [Transform2D].
</description>
</method>
<method name="canvas_item_set_use_parent_material">
@@ -456,6 +490,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ Sets if the [CanvasItem] uses its parent's material.
</description>
</method>
<method name="canvas_item_set_visible">
@@ -466,6 +501,7 @@
<argument index="1" name="visible" type="bool">
</argument>
<description>
+ Sets if the canvas item (including its children) is visible.
</description>
</method>
<method name="canvas_item_set_z">
@@ -476,6 +512,7 @@
<argument index="1" name="z" type="int">
</argument>
<description>
+ Sets the [CanvasItem]'s z order position.
</description>
</method>
<method name="canvas_item_set_z_as_relative_to_parent">
@@ -486,6 +523,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ If this is enabled, the z-position of the parent will be added to the childrens z-position.
</description>
</method>
<method name="canvas_light_attach_to_canvas">
@@ -496,12 +534,14 @@
<argument index="1" name="canvas" type="RID">
</argument>
<description>
+ Attaches the canvas light to the canvas. Removes it from its previous canvas.
</description>
</method>
<method name="canvas_light_create">
<return type="RID">
</return>
<description>
+ Creates a canvas light.
</description>
</method>
<method name="canvas_light_occluder_attach_to_canvas">
@@ -512,12 +552,14 @@
<argument index="1" name="canvas" type="RID">
</argument>
<description>
+ Attaches a light occluder to the canvas. Removes it from its previous canvas.
</description>
</method>
<method name="canvas_light_occluder_create">
<return type="RID">
</return>
<description>
+ Creates a light occluder.
</description>
</method>
<method name="canvas_light_occluder_set_enabled">
@@ -528,6 +570,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ Enables or disables light occluder.
</description>
</method>
<method name="canvas_light_occluder_set_light_mask">
@@ -538,6 +581,7 @@
<argument index="1" name="mask" type="int">
</argument>
<description>
+ The light mask. See [LightOccluder2D] for more information on light masks
</description>
</method>
<method name="canvas_light_occluder_set_polygon">
@@ -548,6 +592,7 @@
<argument index="1" name="polygon" type="RID">
</argument>
<description>
+ Sets a light occluder's polygon.
</description>
</method>
<method name="canvas_light_occluder_set_transform">
@@ -558,6 +603,7 @@
<argument index="1" name="transform" type="Transform2D">
</argument>
<description>
+ Sets a light occluder's [Transform2D].
</description>
</method>
<method name="canvas_light_set_color">
@@ -568,6 +614,7 @@
<argument index="1" name="color" type="Color">
</argument>
<description>
+ Sets the color for a light.
</description>
</method>
<method name="canvas_light_set_enabled">
@@ -578,6 +625,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ Enables or disables a canvas light.
</description>
</method>
<method name="canvas_light_set_energy">
@@ -588,6 +636,7 @@
<argument index="1" name="energy" type="float">
</argument>
<description>
+ Sets a canvas light's energy.
</description>
</method>
<method name="canvas_light_set_height">
@@ -598,6 +647,7 @@
<argument index="1" name="height" type="float">
</argument>
<description>
+ Sets a canvas light's height.
</description>
</method>
<method name="canvas_light_set_item_cull_mask">
@@ -608,6 +658,7 @@
<argument index="1" name="mask" type="int">
</argument>
<description>
+ The light mask. See [LightOccluder2D] for more information on light masks
</description>
</method>
<method name="canvas_light_set_item_shadow_cull_mask">
@@ -618,6 +669,7 @@
<argument index="1" name="mask" type="int">
</argument>
<description>
+ The shadow mask. binary about wich layers this canvas light affects wich canvas item's shadows. See [LightOccluder2D] for more information on light masks.
</description>
</method>
<method name="canvas_light_set_layer_range">
@@ -630,6 +682,7 @@
<argument index="2" name="max_layer" type="int">
</argument>
<description>
+ The layer range that gets rendered with this light.
</description>
</method>
<method name="canvas_light_set_mode">
@@ -640,6 +693,7 @@
<argument index="1" name="mode" type="int" enum="VisualServer.CanvasLightMode">
</argument>
<description>
+ The mode of the light, see CANVAS_LIGHT_MODE_* constants.
</description>
</method>
<method name="canvas_light_set_scale">
@@ -660,6 +714,7 @@
<argument index="1" name="size" type="int">
</argument>
<description>
+ Sets the width of the shadow buffer, size gets scaled to the next power of two for this.
</description>
</method>
<method name="canvas_light_set_shadow_color">
@@ -670,6 +725,7 @@
<argument index="1" name="color" type="Color">
</argument>
<description>
+ Sets the color of the canvas light's shadow.
</description>
</method>
<method name="canvas_light_set_shadow_enabled">
@@ -680,6 +736,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ Enables or disables the canvas light's shadow.
</description>
</method>
<method name="canvas_light_set_shadow_filter">
@@ -690,6 +747,7 @@
<argument index="1" name="filter" type="int" enum="VisualServer.CanvasLightShadowFilter">
</argument>
<description>
+ Sets the canvas light's shadow's filter, see CANVAS_LIGHT_SHADOW_FILTER_* constants.
</description>
</method>
<method name="canvas_light_set_shadow_gradient_length">
@@ -700,6 +758,7 @@
<argument index="1" name="length" type="float">
</argument>
<description>
+ Sets the length of the shadow's gradient.
</description>
</method>
<method name="canvas_light_set_shadow_smooth">
@@ -710,6 +769,7 @@
<argument index="1" name="smooth" type="float">
</argument>
<description>
+ Smoothens the shadow. The lower, the more smooth.
</description>
</method>
<method name="canvas_light_set_texture">
@@ -740,6 +800,7 @@
<argument index="1" name="transform" type="Transform2D">
</argument>
<description>
+ Sets the canvas light's [Transform2D].
</description>
</method>
<method name="canvas_light_set_z_range">
@@ -758,6 +819,7 @@
<return type="RID">
</return>
<description>
+ Creates a new light occluder polygon.
</description>
</method>
<method name="canvas_occluder_polygon_set_cull_mode">
@@ -768,6 +830,7 @@
<argument index="1" name="mode" type="int" enum="VisualServer.CanvasOccluderPolygonCullMode">
</argument>
<description>
+ Sets an occluder polygons cull mode. See CANVAS_OCCLUDER_POLYGON_CULL_MODE_* constants.
</description>
</method>
<method name="canvas_occluder_polygon_set_shape">
@@ -780,6 +843,7 @@
<argument index="2" name="closed" type="bool">
</argument>
<description>
+ Sets the shape of the occluder polygon.
</description>
</method>
<method name="canvas_occluder_polygon_set_shape_as_lines">
@@ -790,6 +854,7 @@
<argument index="1" name="shape" type="PoolVector2Array">
</argument>
<description>
+ Sets the shape of the occluder polygon as lines.
</description>
</method>
<method name="canvas_set_item_mirroring">
@@ -802,6 +867,7 @@
<argument index="2" name="mirroring" type="Vector2">
</argument>
<description>
+ A copy of the canvas item will be drawn with a local offset of the mirroring [Vector2].
</description>
</method>
<method name="canvas_set_modulate">
@@ -812,6 +878,7 @@
<argument index="1" name="color" type="Color">
</argument>
<description>
+ Modulates all colors in the given canvas.
</description>
</method>
<method name="draw">
@@ -820,12 +887,14 @@
<argument index="0" name="swap_buffers" type="bool" default="true">
</argument>
<description>
+ Draws a frame.
</description>
</method>
<method name="finish">
<return type="void">
</return>
<description>
+ Removes buffers and clears testcubes.
</description>
</method>
<method name="force_draw">
@@ -834,12 +903,14 @@
<argument index="0" name="swap_buffers" type="bool" default="true">
</argument>
<description>
+ Draws a frame. Same as [method draw].
</description>
</method>
<method name="force_sync">
<return type="void">
</return>
<description>
+ Syncronizes threads.
</description>
</method>
<method name="free">
@@ -848,6 +919,7 @@
<argument index="0" name="rid" type="RID">
</argument>
<description>
+ Tries to free an object in the VisualServer.
</description>
</method>
<method name="get_render_info">
@@ -856,30 +928,35 @@
<argument index="0" name="info" type="int" enum="VisualServer.RenderInfo">
</argument>
<description>
+ Returns a certain information, see RENDER_INFO_* for options.
</description>
</method>
<method name="get_test_cube">
<return type="RID">
</return>
<description>
+ Returns the id of the test cube. Creates one if none exists.
</description>
</method>
<method name="get_test_texture">
<return type="RID">
</return>
<description>
+ Returns the id of the test texture. Creates one if none exists.
</description>
</method>
<method name="get_white_texture">
<return type="RID">
</return>
<description>
+ Returns the id of a white texture. Creates one if none exists.
</description>
</method>
<method name="has_changed" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if changes have been made to the VisualServer's data. [method draw] is usually called if this happens.
</description>
</method>
<method name="has_feature" qualifiers="const">
@@ -896,12 +973,14 @@
<argument index="0" name="feature" type="String">
</argument>
<description>
+ Returns true, if the OS supports a certain feature. Features might be s3tc, etc, etc2 and pvrtc,
</description>
</method>
<method name="init">
<return type="void">
</return>
<description>
+ Initializes the visual server.
</description>
</method>
<method name="make_sphere_mesh">
@@ -914,12 +993,14 @@
<argument index="2" name="radius" type="float">
</argument>
<description>
+ Returns a mesh of a sphere with the given amount of horizontal and vertical subdivisions.
</description>
</method>
<method name="material_create">
<return type="RID">
</return>
<description>
+ Returns an empty material.
</description>
</method>
<method name="material_get_param" qualifiers="const">
@@ -930,6 +1011,7 @@
<argument index="1" name="parameter" type="String">
</argument>
<description>
+ Returns the value of a certain material's parameter.
</description>
</method>
<method name="material_get_shader" qualifiers="const">
@@ -938,6 +1020,7 @@
<argument index="0" name="shader_material" type="RID">
</argument>
<description>
+ Returns the shader of a certain material's shader. Returns an empty RID if the material doesn't have a shader.
</description>
</method>
<method name="material_set_line_width">
@@ -948,6 +1031,7 @@
<argument index="1" name="width" type="float">
</argument>
<description>
+ Sets a materials line width.
</description>
</method>
<method name="material_set_next_pass">
@@ -958,6 +1042,7 @@
<argument index="1" name="next_material" type="RID">
</argument>
<description>
+ Sets an objects next material.
</description>
</method>
<method name="material_set_param">
@@ -970,6 +1055,7 @@
<argument index="2" name="value" type="Variant">
</argument>
<description>
+ Sets a materials parameter.
</description>
</method>
<method name="material_set_render_priority">
@@ -980,6 +1066,7 @@
<argument index="1" name="priority" type="int">
</argument>
<description>
+ Sets a material's render priority.
</description>
</method>
<method name="material_set_shader">
@@ -990,6 +1077,7 @@
<argument index="1" name="shader" type="RID">
</argument>
<description>
+ Sets a shader material's shader.
</description>
</method>
<method name="mesh_add_surface_from_arrays">
@@ -1006,6 +1094,7 @@
<argument index="4" name="compress_format" type="int" default="97792">
</argument>
<description>
+ Adds a surface generated from the Arrays to a mesh. See PRIMITIVE_TYPE_* constants for types.
</description>
</method>
<method name="mesh_clear">
@@ -1014,12 +1103,14 @@
<argument index="0" name="mesh" type="RID">
</argument>
<description>
+ Removes all surfaces from a mesh.
</description>
</method>
<method name="mesh_create">
<return type="RID">
</return>
<description>
+ Creates a new mesh.
</description>
</method>
<method name="mesh_get_blend_shape_count" qualifiers="const">
@@ -1028,6 +1119,7 @@
<argument index="0" name="mesh" type="RID">
</argument>
<description>
+ Returns a mesh's blend shape count.
</description>
</method>
<method name="mesh_get_blend_shape_mode" qualifiers="const">
@@ -1036,6 +1128,7 @@
<argument index="0" name="mesh" type="RID">
</argument>
<description>
+ Returns a mesh's blend shape mode.
</description>
</method>
<method name="mesh_get_custom_aabb" qualifiers="const">
@@ -1044,6 +1137,7 @@
<argument index="0" name="mesh" type="RID">
</argument>
<description>
+ Returns a mesh's custom aabb.
</description>
</method>
<method name="mesh_get_surface_count" qualifiers="const">
@@ -1052,6 +1146,7 @@
<argument index="0" name="mesh" type="RID">
</argument>
<description>
+ Returns a mesh's number of surfaces.
</description>
</method>
<method name="mesh_remove_surface">
@@ -1062,6 +1157,7 @@
<argument index="1" name="index" type="int">
</argument>
<description>
+ Removes a mesh's surface.
</description>
</method>
<method name="mesh_set_blend_shape_count">
@@ -1072,6 +1168,7 @@
<argument index="1" name="amount" type="int">
</argument>
<description>
+ Sets a mesh's blend shape count.
</description>
</method>
<method name="mesh_set_blend_shape_mode">
@@ -1082,6 +1179,7 @@
<argument index="1" name="mode" type="int" enum="VisualServer.BlendShapeMode">
</argument>
<description>
+ Sets a mesh's blend shape mode.
</description>
</method>
<method name="mesh_set_custom_aabb">
@@ -1092,6 +1190,7 @@
<argument index="1" name="aabb" type="AABB">
</argument>
<description>
+ Sets a mesh's custom aabb.
</description>
</method>
<method name="mesh_surface_get_aabb" qualifiers="const">
@@ -1102,6 +1201,7 @@
<argument index="1" name="surface" type="int">
</argument>
<description>
+ Returns a mesh's surface's aabb.
</description>
</method>
<method name="mesh_surface_get_array" qualifiers="const">
@@ -1112,6 +1212,7 @@
<argument index="1" name="surface" type="int">
</argument>
<description>
+ Returns a mesh's surface's vertex buffer.
</description>
</method>
<method name="mesh_surface_get_array_index_len" qualifiers="const">
@@ -1122,6 +1223,7 @@
<argument index="1" name="surface" type="int">
</argument>
<description>
+ Returns a mesh's surface's amount of indices.
</description>
</method>
<method name="mesh_surface_get_array_len" qualifiers="const">
@@ -1132,6 +1234,7 @@
<argument index="1" name="surface" type="int">
</argument>
<description>
+ Returns a mesh's surface's amount of vertices.
</description>
</method>
<method name="mesh_surface_get_arrays" qualifiers="const">
@@ -1142,6 +1245,7 @@
<argument index="1" name="surface" type="int">
</argument>
<description>
+ Returns a mesh's surface's buffer arrays.
</description>
</method>
<method name="mesh_surface_get_blend_shape_arrays" qualifiers="const">
@@ -1152,6 +1256,7 @@
<argument index="1" name="surface" type="int">
</argument>
<description>
+ Returns a mesh's surface's arrays for blend shapes
</description>
</method>
<method name="mesh_surface_get_format" qualifiers="const">
@@ -1162,6 +1267,7 @@
<argument index="1" name="surface" type="int">
</argument>
<description>
+ Returns the format of a mesh's surface.
</description>
</method>
<method name="mesh_surface_get_index_array" qualifiers="const">
@@ -1172,6 +1278,7 @@
<argument index="1" name="surface" type="int">
</argument>
<description>
+ Returns a mesh's surface's index buffer.
</description>
</method>
<method name="mesh_surface_get_material" qualifiers="const">
@@ -1182,6 +1289,7 @@
<argument index="1" name="surface" type="int">
</argument>
<description>
+ Returns a mesh's surface's material.
</description>
</method>
<method name="mesh_surface_get_primitive_type" qualifiers="const">
@@ -1192,6 +1300,7 @@
<argument index="1" name="surface" type="int">
</argument>
<description>
+ Returns the primitive type of a mesh's surface.
</description>
</method>
<method name="mesh_surface_get_skeleton_aabb" qualifiers="const">
@@ -1202,6 +1311,7 @@
<argument index="1" name="surface" type="int">
</argument>
<description>
+ Returns the aabb of a mesh's surface's skeleton.
</description>
</method>
<method name="mesh_surface_set_material">
@@ -1214,6 +1324,7 @@
<argument index="2" name="material" type="RID">
</argument>
<description>
+ Sets a mesh's surface's material.
</description>
</method>
<method name="request_frame_drawn_callback">
@@ -1240,6 +1351,7 @@
<argument index="2" name="scale" type="bool">
</argument>
<description>
+ Sets a boot image. The color defines the background color and if scale is [code]true[/code], the image will be scaled to fit the screen size.
</description>
</method>
<method name="set_debug_generate_wireframes">
@@ -1262,6 +1374,7 @@
<return type="RID">
</return>
<description>
+ Creates an empty shader.
</description>
</method>
<method name="shader_get_code" qualifiers="const">
@@ -1270,6 +1383,7 @@
<argument index="0" name="shader" type="RID">
</argument>
<description>
+ Returns a shader's code.
</description>
</method>
<method name="shader_get_default_texture_param" qualifiers="const">
@@ -1280,6 +1394,7 @@
<argument index="1" name="name" type="String">
</argument>
<description>
+ Returns a default texture from a shader searched by name.
</description>
</method>
<method name="shader_get_param_list" qualifiers="const">
@@ -1288,6 +1403,7 @@
<argument index="0" name="shader" type="RID">
</argument>
<description>
+ Returns the parameters of a shader.
</description>
</method>
<method name="shader_set_code">
@@ -1298,6 +1414,7 @@
<argument index="1" name="code" type="String">
</argument>
<description>
+ Sets a shader's code.
</description>
</method>
<method name="shader_set_default_texture_param">
@@ -1310,12 +1427,14 @@
<argument index="2" name="texture" type="RID">
</argument>
<description>
+ Sets a shader's default texture. Overwrites the texture given by name.
</description>
</method>
<method name="sky_create">
<return type="RID">
</return>
<description>
+ Creates an empty sky.
</description>
</method>
<method name="sky_set_texture">
@@ -1328,6 +1447,7 @@
<argument index="2" name="radiance_size" type="int">
</argument>
<description>
+ Sets a sky's texture.
</description>
</method>
<method name="sync">
@@ -1350,12 +1470,14 @@
<argument index="4" name="flags" type="int" default="7">
</argument>
<description>
+ Allocates space for a texture's image or video.
</description>
</method>
<method name="texture_create">
<return type="RID">
</return>
<description>
+ Creates an empty texture.
</description>
</method>
<method name="texture_create_from_image">
@@ -1366,12 +1488,14 @@
<argument index="1" name="flags" type="int" default="7">
</argument>
<description>
+ Creates a texture, allocates the space for an image, and fills in the image.
</description>
</method>
<method name="texture_debug_usage">
<return type="Array">
</return>
<description>
+ Returns a list of all the textures and their information.
</description>
</method>
<method name="texture_get_data" qualifiers="const">
@@ -1382,6 +1506,7 @@
<argument index="1" name="cube_side" type="int" enum="VisualServer.CubeMapSide" default="0">
</argument>
<description>
+ Returns a copy of a texture's image unless it's a CubeMap, in wich case it returns the [RID] of the image at one of the cubes sides.
</description>
</method>
<method name="texture_get_flags" qualifiers="const">
@@ -1390,6 +1515,7 @@
<argument index="0" name="texture" type="RID">
</argument>
<description>
+ Returns the flags of a texture.
</description>
</method>
<method name="texture_get_format" qualifiers="const">
@@ -1398,6 +1524,7 @@
<argument index="0" name="texture" type="RID">
</argument>
<description>
+ Returns the format of the texture's image.
</description>
</method>
<method name="texture_get_height" qualifiers="const">
@@ -1406,6 +1533,7 @@
<argument index="0" name="texture" type="RID">
</argument>
<description>
+ Returns the texture's height.
</description>
</method>
<method name="texture_get_path" qualifiers="const">
@@ -1414,6 +1542,7 @@
<argument index="0" name="texture" type="RID">
</argument>
<description>
+ Returns the texture's path.
</description>
</method>
<method name="texture_get_texid" qualifiers="const">
@@ -1422,6 +1551,7 @@
<argument index="0" name="texture" type="RID">
</argument>
<description>
+ Returns the opengl id of the texture's image.
</description>
</method>
<method name="texture_get_width" qualifiers="const">
@@ -1430,6 +1560,7 @@
<argument index="0" name="texture" type="RID">
</argument>
<description>
+ Returns the texture's width.
</description>
</method>
<method name="texture_set_data">
@@ -1442,6 +1573,7 @@
<argument index="2" name="cube_side" type="int" enum="VisualServer.CubeMapSide" default="0">
</argument>
<description>
+ Sets the texture's image data. If it's a CubeMap, it sets the image data at a cube side.
</description>
</method>
<method name="texture_set_flags">
@@ -1452,6 +1584,7 @@
<argument index="1" name="flags" type="int">
</argument>
<description>
+ Sets the texture's flags. See [enum TextureFlags] for options
</description>
</method>
<method name="texture_set_path">
@@ -1462,6 +1595,7 @@
<argument index="1" name="path" type="String">
</argument>
<description>
+ Sets the texture's path.
</description>
</method>
<method name="texture_set_shrink_all_x2_on_set_data">
@@ -1470,6 +1604,7 @@
<argument index="0" name="shrink" type="bool">
</argument>
<description>
+ If [code]true[/code], sets internal processes to shrink all image data to half the size.
</description>
</method>
<method name="texture_set_size_override">
@@ -1482,6 +1617,7 @@
<argument index="2" name="height" type="int">
</argument>
<description>
+ Overwrites the texture's width and height.
</description>
</method>
<method name="textures_keep_original">
@@ -1490,6 +1626,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code], the image will be stored in the texture's images array if overwritten.
</description>
</method>
<method name="viewport_attach_camera">
@@ -1500,6 +1637,7 @@
<argument index="1" name="camera" type="RID">
</argument>
<description>
+ Sets a viewport's camera.
</description>
</method>
<method name="viewport_attach_canvas">
@@ -1510,6 +1648,7 @@
<argument index="1" name="canvas" type="RID">
</argument>
<description>
+ Sets a viewport's canvas.
</description>
</method>
<method name="viewport_attach_to_screen">
@@ -1522,12 +1661,14 @@
<argument index="2" name="screen" type="int" default="0">
</argument>
<description>
+ Attaches a viewport to a screen.
</description>
</method>
<method name="viewport_create">
<return type="RID">
</return>
<description>
+ Creates an empty viewport.
</description>
</method>
<method name="viewport_detach">
@@ -1536,6 +1677,7 @@
<argument index="0" name="viewport" type="RID">
</argument>
<description>
+ Detaches the viewport from the screen.
</description>
</method>
<method name="viewport_get_render_info">
@@ -1546,6 +1688,7 @@
<argument index="1" name="info" type="int" enum="VisualServer.ViewportRenderInfo">
</argument>
<description>
+ Returns a viewport's render info. for options see VIEWPORT_RENDER_INFO* constants.
</description>
</method>
<method name="viewport_get_texture" qualifiers="const">
@@ -1554,6 +1697,7 @@
<argument index="0" name="viewport" type="RID">
</argument>
<description>
+ Returns the viewport's last rendered frame.
</description>
</method>
<method name="viewport_remove_canvas">
@@ -1564,6 +1708,7 @@
<argument index="1" name="canvas" type="RID">
</argument>
<description>
+ Detaches a viewport from a canvas and vice versa.
</description>
</method>
<method name="viewport_set_active">
@@ -1574,6 +1719,7 @@
<argument index="1" name="active" type="bool">
</argument>
<description>
+ If [code]true[/code], sets the viewport active, else sets it inactive.
</description>
</method>
<method name="viewport_set_canvas_layer">
@@ -1586,6 +1732,7 @@
<argument index="2" name="layer" type="int">
</argument>
<description>
+ Sets the renderlayer for a viewport's canvas.
</description>
</method>
<method name="viewport_set_canvas_transform">
@@ -1598,6 +1745,7 @@
<argument index="2" name="offset" type="Transform2D">
</argument>
<description>
+ Sets the transformation of a viewport's canvas.
</description>
</method>
<method name="viewport_set_clear_mode">
@@ -1608,6 +1756,7 @@
<argument index="1" name="clear_mode" type="int" enum="VisualServer.ViewportClearMode">
</argument>
<description>
+ Sets the clear mode of a viewport. See VIEWPORT_CLEAR_MODE_* constants for options.
</description>
</method>
<method name="viewport_set_debug_draw">
@@ -1618,6 +1767,7 @@
<argument index="1" name="draw" type="int" enum="VisualServer.ViewportDebugDraw">
</argument>
<description>
+ Sets the debug draw mode of a viewport. See VIEWPORT_DEBUG_DRAW_* constants for options.
</description>
</method>
<method name="viewport_set_disable_3d">
@@ -1628,6 +1778,7 @@
<argument index="1" name="disabled" type="bool">
</argument>
<description>
+ If [code]true[/code] a viewport's 3D rendering should be disabled.
</description>
</method>
<method name="viewport_set_disable_environment">
@@ -1638,6 +1789,7 @@
<argument index="1" name="disabled" type="bool">
</argument>
<description>
+ If [code]true[/code] rendering of a viewport's environment should be disabled.
</description>
</method>
<method name="viewport_set_global_canvas_transform">
@@ -1648,6 +1800,7 @@
<argument index="1" name="transform" type="Transform2D">
</argument>
<description>
+ Sets the viewport's global transformation matrix.
</description>
</method>
<method name="viewport_set_hdr">
@@ -1658,6 +1811,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ If [code]true[/code] the viewport should render to hdr.
</description>
</method>
<method name="viewport_set_hide_canvas">
@@ -1668,6 +1822,7 @@
<argument index="1" name="hidden" type="bool">
</argument>
<description>
+ If [code]true[/code] the viewport's canvas should not be rendered.
</description>
</method>
<method name="viewport_set_hide_scenario">
@@ -1688,6 +1843,7 @@
<argument index="1" name="msaa" type="int" enum="VisualServer.ViewportMSAA">
</argument>
<description>
+ Sets the anti-aliasing mode. see [enum ViewportMSAA] for options.
</description>
</method>
<method name="viewport_set_parent_viewport">
@@ -1698,6 +1854,7 @@
<argument index="1" name="parent_viewport" type="RID">
</argument>
<description>
+ Sets the viewport's parent to another viewport.
</description>
</method>
<method name="viewport_set_scenario">
@@ -1708,6 +1865,8 @@
<argument index="1" name="scenario" type="RID">
</argument>
<description>
+ Sets a viewport's scenario.
+ The scenario contains information about the [enum ScenarioDebugMode], environment information, reflection atlas etc.
</description>
</method>
<method name="viewport_set_shadow_atlas_quadrant_subdivision">
@@ -1720,6 +1879,7 @@
<argument index="2" name="subdivision" type="int">
</argument>
<description>
+ Sets the shadow atlas quadrant's subdivision.
</description>
</method>
<method name="viewport_set_shadow_atlas_size">
@@ -1730,6 +1890,7 @@
<argument index="1" name="size" type="int">
</argument>
<description>
+ Sets the size of the shadow atlas's images.
</description>
</method>
<method name="viewport_set_size">
@@ -1742,6 +1903,7 @@
<argument index="2" name="height" type="int">
</argument>
<description>
+ Sets the viewport's width and height.
</description>
</method>
<method name="viewport_set_transparent_background">
@@ -1752,6 +1914,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ If [code]true[/code] the viewport should render its background as transparent.
</description>
</method>
<method name="viewport_set_update_mode">
@@ -1762,6 +1925,7 @@
<argument index="1" name="update_mode" type="int" enum="VisualServer.ViewportUpdateMode">
</argument>
<description>
+ Sets when the viewport should be updated. See VIEWPORT_UPDATE_MODE_* constants for options.
</description>
</method>
<method name="viewport_set_usage">
@@ -1772,6 +1936,7 @@
<argument index="1" name="usage" type="int" enum="VisualServer.ViewportUsage">
</argument>
<description>
+ Sets what should be rendered in the viewport. See VIEWPORT_USAGE_* constants for options.
</description>
</method>
<method name="viewport_set_use_arvr">
@@ -1782,6 +1947,7 @@
<argument index="1" name="use_arvr" type="bool">
</argument>
<description>
+ If [code]true[/code] the viewport should use augmented or virtual reality technologies. See [ARVRInterface].
</description>
</method>
<method name="viewport_set_vflip">
@@ -1792,6 +1958,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ If [code]true[/code] the viewport's rendering should be flipped vertically.
</description>
</method>
</methods>
@@ -1803,160 +1970,232 @@
</signals>
<constants>
<constant name="NO_INDEX_ARRAY" value="-1">
+ Marks an error that shows that the index array is empty.
</constant>
<constant name="ARRAY_WEIGHTS_SIZE" value="4">
</constant>
<constant name="CANVAS_ITEM_Z_MIN" value="-4096">
+ The minimum Z-layer for canvas items.
</constant>
<constant name="CANVAS_ITEM_Z_MAX" value="4096">
+ The maximum Z-layer for canvas items.
</constant>
<constant name="MAX_GLOW_LEVELS" value="7">
</constant>
<constant name="MAX_CURSORS" value="8">
</constant>
<constant name="MATERIAL_RENDER_PRIORITY_MIN" value="-128">
+ The minimum renderpriority of all materials.
</constant>
<constant name="MATERIAL_RENDER_PRIORITY_MAX" value="127">
+ The maximum renderpriority of all materials.
</constant>
<constant name="CUBEMAP_LEFT" value="0" enum="CubeMapSide">
+ Marks the left side of a cubemap.
</constant>
<constant name="CUBEMAP_RIGHT" value="1" enum="CubeMapSide">
+ Marks the right side of a cubemap.
</constant>
<constant name="CUBEMAP_BOTTOM" value="2" enum="CubeMapSide">
+ Marks the bottom side of a cubemap.
</constant>
<constant name="CUBEMAP_TOP" value="3" enum="CubeMapSide">
+ Marks the top side of a cubemap.
</constant>
<constant name="CUBEMAP_FRONT" value="4" enum="CubeMapSide">
+ Marks the front side of a cubemap.
</constant>
<constant name="CUBEMAP_BACK" value="5" enum="CubeMapSide">
+ Marks the back side of a cubemap.
</constant>
<constant name="TEXTURE_FLAG_MIPMAPS" value="1" enum="TextureFlags">
+ Generate mipmaps, which are smaller versions of the same texture to use when zoomed out, keeping the aspect ratio.
</constant>
<constant name="TEXTURE_FLAG_REPEAT" value="2" enum="TextureFlags">
+ Repeat (instead of clamp to edge).
</constant>
<constant name="TEXTURE_FLAG_FILTER" value="4" enum="TextureFlags">
+ Turn on magnifying filter, to enable smooth zooming in of the texture.
</constant>
<constant name="TEXTURE_FLAG_ANISOTROPIC_FILTER" value="8" enum="TextureFlags">
+ Anisotropic mipmap filtering. Generates smaller versions of the same texture with different aspect ratios.
+ More effective on planes often shown going to the horrizon as those textures (Walls or Ground for example) get squashed in the viewport to different aspect ratios and regular mipmaps keep the aspect ratio so they don't optimize storage that well in those cases.
</constant>
<constant name="TEXTURE_FLAG_CONVERT_TO_LINEAR" value="16" enum="TextureFlags">
+ Converts texture to SRGB color space.
</constant>
<constant name="TEXTURE_FLAG_MIRRORED_REPEAT" value="32" enum="TextureFlags">
+ Repeat texture with alternate sections mirrored.
</constant>
<constant name="TEXTURE_FLAG_CUBEMAP" value="2048" enum="TextureFlags">
+ Texture is a cubemap.
</constant>
<constant name="TEXTURE_FLAG_USED_FOR_STREAMING" value="4096" enum="TextureFlags">
+ Texture is a video surface.
</constant>
<constant name="TEXTURE_FLAGS_DEFAULT" value="7" enum="TextureFlags">
+ Default flags. Generate mipmaps, repeat, and filter are enabled.
</constant>
<constant name="SHADER_SPATIAL" value="0" enum="ShaderMode">
+ Shader is a 3D shader.
</constant>
<constant name="SHADER_CANVAS_ITEM" value="1" enum="ShaderMode">
+ Shader is a 2D shader.
</constant>
<constant name="SHADER_PARTICLES" value="2" enum="ShaderMode">
+ Shader is a particle shader.
</constant>
<constant name="SHADER_MAX" value="3" enum="ShaderMode">
+ Marks maximum of the shader types array. used internally.
</constant>
<constant name="ARRAY_VERTEX" value="0" enum="ArrayType">
+ Array is a vertex array.
</constant>
<constant name="ARRAY_NORMAL" value="1" enum="ArrayType">
+ Array is a normal array.
</constant>
<constant name="ARRAY_TANGENT" value="2" enum="ArrayType">
+ Array is a tangent array.
</constant>
<constant name="ARRAY_COLOR" value="3" enum="ArrayType">
+ Array is a color array.
</constant>
<constant name="ARRAY_TEX_UV" value="4" enum="ArrayType">
+ Array is a uv coordinates array.
</constant>
<constant name="ARRAY_TEX_UV2" value="5" enum="ArrayType">
+ Array is a uv coordinates array for the second uv coordinates.
</constant>
<constant name="ARRAY_BONES" value="6" enum="ArrayType">
+ Array contains bone information.
</constant>
<constant name="ARRAY_WEIGHTS" value="7" enum="ArrayType">
+ Array is weight information.
</constant>
<constant name="ARRAY_INDEX" value="8" enum="ArrayType">
+ Array is index array.
</constant>
<constant name="ARRAY_MAX" value="9" enum="ArrayType">
+ Marks the maximum of the array types. Used internally.
</constant>
<constant name="ARRAY_FORMAT_VERTEX" value="1" enum="ArrayFormat">
+ Flag used to mark a vertex array.
</constant>
<constant name="ARRAY_FORMAT_NORMAL" value="2" enum="ArrayFormat">
+ Flag used to mark a normal array.
</constant>
<constant name="ARRAY_FORMAT_TANGENT" value="4" enum="ArrayFormat">
+ Flag used to mark a tangent array.
</constant>
<constant name="ARRAY_FORMAT_COLOR" value="8" enum="ArrayFormat">
+ Flag used to mark a color array.
</constant>
<constant name="ARRAY_FORMAT_TEX_UV" value="16" enum="ArrayFormat">
+ Flag used to mark a uv coordinates array.
</constant>
<constant name="ARRAY_FORMAT_TEX_UV2" value="32" enum="ArrayFormat">
+ Flag used to mark a uv coordinates array for the second uv coordinates.
</constant>
<constant name="ARRAY_FORMAT_BONES" value="64" enum="ArrayFormat">
+ Flag used to mark a bone information array.
</constant>
<constant name="ARRAY_FORMAT_WEIGHTS" value="128" enum="ArrayFormat">
+ Flag used to mark a weights array.
</constant>
<constant name="ARRAY_FORMAT_INDEX" value="256" enum="ArrayFormat">
+ Flag used to mark a index array.
</constant>
<constant name="ARRAY_COMPRESS_VERTEX" value="512" enum="ArrayFormat">
+ Flag used to mark a compressed (half float) vertex array.
</constant>
<constant name="ARRAY_COMPRESS_NORMAL" value="1024" enum="ArrayFormat">
+ Flag used to mark a compressed (half float) normal array.
</constant>
<constant name="ARRAY_COMPRESS_TANGENT" value="2048" enum="ArrayFormat">
+ Flag used to mark a compressed (half float) tangent array.
</constant>
<constant name="ARRAY_COMPRESS_COLOR" value="4096" enum="ArrayFormat">
+ Flag used to mark a compressed (half float) color array.
</constant>
<constant name="ARRAY_COMPRESS_TEX_UV" value="8192" enum="ArrayFormat">
+ Flag used to mark a compressed (half float) uv coordinates array.
</constant>
<constant name="ARRAY_COMPRESS_TEX_UV2" value="16384" enum="ArrayFormat">
+ Flag used to mark a compressed (half float) uv coordinates array for the second uv coordinates.
</constant>
<constant name="ARRAY_COMPRESS_BONES" value="32768" enum="ArrayFormat">
</constant>
<constant name="ARRAY_COMPRESS_WEIGHTS" value="65536" enum="ArrayFormat">
+ Flag used to mark a compressed (half float) weight array.
</constant>
<constant name="ARRAY_COMPRESS_INDEX" value="131072" enum="ArrayFormat">
</constant>
<constant name="ARRAY_FLAG_USE_2D_VERTICES" value="262144" enum="ArrayFormat">
+ Flag used to mark that the array contains 2D vertices.
</constant>
<constant name="ARRAY_FLAG_USE_16_BIT_BONES" value="524288" enum="ArrayFormat">
+ Flag used to mark that the array uses 16 bit bones instead of 8 bit.
</constant>
<constant name="ARRAY_COMPRESS_DEFAULT" value="97792" enum="ArrayFormat">
+ Used to set flags ARRAY_COMPRESS_VERTEX, ARRAY_COMPRESS_NORMAL, ARRAY_COMPRESS_TANGENT, ARRAY_COMPRESS_COLOR, ARRAY_COMPRESS_TEX_UV, ARRAY_COMPRESS_TEX_UV2 and ARRAY_COMPRESS_WEIGHTS quickly.
</constant>
<constant name="PRIMITIVE_POINTS" value="0" enum="PrimitiveType">
+ Primitive to draw consists of points.
</constant>
<constant name="PRIMITIVE_LINES" value="1" enum="PrimitiveType">
+ Primitive to draw consists of lines.
</constant>
<constant name="PRIMITIVE_LINE_STRIP" value="2" enum="PrimitiveType">
+ Primitive to draw consists of a line strip from start to end.
</constant>
<constant name="PRIMITIVE_LINE_LOOP" value="3" enum="PrimitiveType">
+ Primitive to draw consists of a line loop (a line strip with a line between the last and the first vertex).
</constant>
<constant name="PRIMITIVE_TRIANGLES" value="4" enum="PrimitiveType">
+ Primitive to draw consists of triangles.
</constant>
<constant name="PRIMITIVE_TRIANGLE_STRIP" value="5" enum="PrimitiveType">
+ Primitive to draw consists of a triangle strip (the last 3 verticies are always combined to make a triangle).
</constant>
<constant name="PRIMITIVE_TRIANGLE_FAN" value="6" enum="PrimitiveType">
+ Primitive to draw consists of a triangle strip (the last 2 verticies are always combined with the first to make a triangle).
</constant>
<constant name="PRIMITIVE_MAX" value="7" enum="PrimitiveType">
+ Marks the primitive types endpoint. used internally.
</constant>
<constant name="BLEND_SHAPE_MODE_NORMALIZED" value="0" enum="BlendShapeMode">
</constant>
<constant name="BLEND_SHAPE_MODE_RELATIVE" value="1" enum="BlendShapeMode">
</constant>
<constant name="LIGHT_DIRECTIONAL" value="0" enum="LightType">
+ Is a directional (sun) light.
</constant>
<constant name="LIGHT_OMNI" value="1" enum="LightType">
+ is an omni light.
</constant>
<constant name="LIGHT_SPOT" value="2" enum="LightType">
+ is an spot light.
</constant>
<constant name="LIGHT_PARAM_ENERGY" value="0" enum="LightParam">
+ The light's energy.
</constant>
<constant name="LIGHT_PARAM_SPECULAR" value="2" enum="LightParam">
+ The light's influence on specularity.
</constant>
<constant name="LIGHT_PARAM_RANGE" value="3" enum="LightParam">
+ The light's range.
</constant>
<constant name="LIGHT_PARAM_ATTENUATION" value="4" enum="LightParam">
+ The light's attenuation.
</constant>
<constant name="LIGHT_PARAM_SPOT_ANGLE" value="5" enum="LightParam">
+ The spotlight's angle.
</constant>
<constant name="LIGHT_PARAM_SPOT_ATTENUATION" value="6" enum="LightParam">
+ The spotlight's attenuation.
</constant>
<constant name="LIGHT_PARAM_CONTACT_SHADOW_SIZE" value="7" enum="LightParam">
+ Scales the shadow color.
</constant>
<constant name="LIGHT_PARAM_SHADOW_MAX_DISTANCE" value="8" enum="LightParam">
</constant>
@@ -1973,6 +2212,7 @@
<constant name="LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE" value="14" enum="LightParam">
</constant>
<constant name="LIGHT_PARAM_MAX" value="15" enum="LightParam">
+ The light parameters endpoint. Used internally.
</constant>
<constant name="VIEWPORT_UPDATE_DISABLED" value="0" enum="ViewportUpdateMode">
</constant>
@@ -1983,28 +2223,40 @@
<constant name="VIEWPORT_UPDATE_ALWAYS" value="3" enum="ViewportUpdateMode">
</constant>
<constant name="VIEWPORT_CLEAR_ALWAYS" value="0" enum="ViewportClearMode">
+ The viewport is always cleared before drawing.
</constant>
<constant name="VIEWPORT_CLEAR_NEVER" value="1" enum="ViewportClearMode">
+ The viewport is never cleared before drawing.
</constant>
<constant name="VIEWPORT_CLEAR_ONLY_NEXT_FRAME" value="2" enum="ViewportClearMode">
+ The viewport is cleared once, then the clear mode is set to [VIEWPORT_CLEAR_NEVER].
</constant>
<constant name="VIEWPORT_MSAA_DISABLED" value="0" enum="ViewportMSAA">
+ Multisample antialiasing is disabled.
</constant>
<constant name="VIEWPORT_MSAA_2X" value="1" enum="ViewportMSAA">
+ Multisample antialiasing is set to 2X.
</constant>
<constant name="VIEWPORT_MSAA_4X" value="2" enum="ViewportMSAA">
+ Multisample antialiasing is set to 4X.
</constant>
<constant name="VIEWPORT_MSAA_8X" value="3" enum="ViewportMSAA">
+ Multisample antialiasing is set to 8X.
</constant>
<constant name="VIEWPORT_MSAA_16X" value="4" enum="ViewportMSAA">
+ Multisample antialiasing is set to 16X.
</constant>
<constant name="VIEWPORT_USAGE_2D" value="0" enum="ViewportUsage">
+ The Viewport does not render 3D but samples.
</constant>
<constant name="VIEWPORT_USAGE_2D_NO_SAMPLING" value="1" enum="ViewportUsage">
+ The Viewport does not render 3D and does not sample.
</constant>
<constant name="VIEWPORT_USAGE_3D" value="2" enum="ViewportUsage">
+ The Viewport renders 3D with effects.
</constant>
<constant name="VIEWPORT_USAGE_3D_NO_EFFECTS" value="3" enum="ViewportUsage">
+ The Viewport renders 3D but without effects.
</constant>
<constant name="VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME" value="0" enum="ViewportRenderInfo">
</constant>
@@ -2019,14 +2271,19 @@
<constant name="VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME" value="5" enum="ViewportRenderInfo">
</constant>
<constant name="VIEWPORT_RENDER_INFO_MAX" value="6" enum="ViewportRenderInfo">
+ Marks end of VIEWPORT_RENDER_INFO* constants. Used internally.
</constant>
<constant name="VIEWPORT_DEBUG_DRAW_DISABLED" value="0" enum="ViewportDebugDraw">
+ Debug draw is disabled. Default setting.
</constant>
<constant name="VIEWPORT_DEBUG_DRAW_UNSHADED" value="1" enum="ViewportDebugDraw">
+ Debug draw sets objects to unshaded.
</constant>
<constant name="VIEWPORT_DEBUG_DRAW_OVERDRAW" value="2" enum="ViewportDebugDraw">
+ Overwrites clear color to [code](0,0,0,0)[/code].
</constant>
<constant name="VIEWPORT_DEBUG_DRAW_WIREFRAME" value="3" enum="ViewportDebugDraw">
+ Debug draw draws objects in wireframe.
</constant>
<constant name="SCENARIO_DEBUG_DISABLED" value="0" enum="ScenarioDebugMode">
</constant>
@@ -2037,38 +2294,53 @@
<constant name="SCENARIO_DEBUG_SHADELESS" value="3" enum="ScenarioDebugMode">
</constant>
<constant name="INSTANCE_NONE" value="0" enum="InstanceType">
+ The instance does not have a type.
</constant>
<constant name="INSTANCE_MESH" value="1" enum="InstanceType">
+ The instance is a mesh.
</constant>
<constant name="INSTANCE_MULTIMESH" value="2" enum="InstanceType">
+ The instance is a multimesh.
</constant>
<constant name="INSTANCE_IMMEDIATE" value="3" enum="InstanceType">
+ The instance is an immediate geometry.
</constant>
<constant name="INSTANCE_PARTICLES" value="4" enum="InstanceType">
+ The instance is a particle emitter.
</constant>
<constant name="INSTANCE_LIGHT" value="5" enum="InstanceType">
+ The instance is a light.
</constant>
<constant name="INSTANCE_REFLECTION_PROBE" value="6" enum="InstanceType">
</constant>
<constant name="INSTANCE_GI_PROBE" value="7" enum="InstanceType">
</constant>
<constant name="INSTANCE_MAX" value="8" enum="InstanceType">
+ The max value for INSTANCE_* constants, used internally.
</constant>
<constant name="INSTANCE_GEOMETRY_MASK" value="30" enum="InstanceType">
+ A combination of the flags of geometry instances (mesh, multimesh, immediate and particles).
</constant>
<constant name="NINE_PATCH_STRETCH" value="0" enum="NinePatchAxisMode">
+ The nine patch gets stretched where needed.
</constant>
<constant name="NINE_PATCH_TILE" value="1" enum="NinePatchAxisMode">
+ The nine patch gets filled with tiles where needed.
</constant>
<constant name="NINE_PATCH_TILE_FIT" value="2" enum="NinePatchAxisMode">
+ The nine patch gets filled with tiles where needed and stretches them a bit if needed.
</constant>
<constant name="CANVAS_LIGHT_MODE_ADD" value="0" enum="CanvasLightMode">
+ Adds light color additive to the canvas.
</constant>
<constant name="CANVAS_LIGHT_MODE_SUB" value="1" enum="CanvasLightMode">
+ Adds light color subtractive to the canvas.
</constant>
<constant name="CANVAS_LIGHT_MODE_MIX" value="2" enum="CanvasLightMode">
+ The light adds color depending on transparency.
</constant>
<constant name="CANVAS_LIGHT_MODE_MASK" value="3" enum="CanvasLightMode">
+ The light adds color depending on mask.
</constant>
<constant name="CANVAS_LIGHT_FILTER_NONE" value="0" enum="CanvasLightShadowFilter">
</constant>
@@ -2083,30 +2355,42 @@
<constant name="CANVAS_LIGHT_FILTER_PCF13" value="5" enum="CanvasLightShadowFilter">
</constant>
<constant name="CANVAS_OCCLUDER_POLYGON_CULL_DISABLED" value="0" enum="CanvasOccluderPolygonCullMode">
+ Culling of the canvas occluder is disabled.
</constant>
<constant name="CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE" value="1" enum="CanvasOccluderPolygonCullMode">
+ Culling of the canvas occluder is clockwise.
</constant>
<constant name="CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE" value="2" enum="CanvasOccluderPolygonCullMode">
+ Culling of the canvas occluder is counterclockwise.
</constant>
<constant name="INFO_OBJECTS_IN_FRAME" value="0" enum="RenderInfo">
+ The amount of objects in the frame.
</constant>
<constant name="INFO_VERTICES_IN_FRAME" value="1" enum="RenderInfo">
+ The amount of vertices in the frame.
</constant>
<constant name="INFO_MATERIAL_CHANGES_IN_FRAME" value="2" enum="RenderInfo">
+ The amount of modified materials in the frame.
</constant>
<constant name="INFO_SHADER_CHANGES_IN_FRAME" value="3" enum="RenderInfo">
+ The amount of shader rebinds in the frame.
</constant>
<constant name="INFO_SURFACE_CHANGES_IN_FRAME" value="4" enum="RenderInfo">
+ The amount of surface changes in the frame.
</constant>
<constant name="INFO_DRAW_CALLS_IN_FRAME" value="5" enum="RenderInfo">
+ The amount of draw calls in frame.
</constant>
<constant name="INFO_USAGE_VIDEO_MEM_TOTAL" value="6" enum="RenderInfo">
</constant>
<constant name="INFO_VIDEO_MEM_USED" value="7" enum="RenderInfo">
+ The amount of vertex memory and texture memory used.
</constant>
<constant name="INFO_TEXTURE_MEM_USED" value="8" enum="RenderInfo">
+ The amount of texture memory used.
</constant>
<constant name="INFO_VERTEX_MEM_USED" value="9" enum="RenderInfo">
+ The amount of vertex memory used.
</constant>
<constant name="FEATURE_SHADERS" value="0" enum="Features">
</constant>
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 0839f930c9..309497c938 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -527,7 +527,9 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
_draw_generic(GL_TRIANGLE_STRIP, pline->triangles.size(), pline->triangles.ptr(), NULL, pline->triangle_colors.ptr(), pline->triangle_colors.size() == 1);
#ifdef GLES_OVER_GL
glEnable(GL_LINE_SMOOTH);
- if (pline->lines.size()) {
+ if (pline->multiline) {
+ //needs to be different
+ } else {
_draw_generic(GL_LINE_LOOP, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1);
}
glDisable(GL_LINE_SMOOTH);
@@ -538,7 +540,23 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
if (pline->antialiased)
glEnable(GL_LINE_SMOOTH);
#endif
- _draw_generic(GL_LINE_STRIP, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1);
+
+ if (pline->multiline) {
+ int todo = pline->lines.size() / 2;
+ int max_per_call = data.polygon_buffer_size / (sizeof(real_t) * 4);
+ int offset = 0;
+
+ while (todo) {
+ int to_draw = MIN(max_per_call, todo);
+ _draw_generic(GL_LINES, to_draw * 2, &pline->lines.ptr()[offset], NULL, pline->line_colors.size() == 1 ? pline->line_colors.ptr() : &pline->line_colors.ptr()[offset], pline->line_colors.size() == 1);
+ todo -= to_draw;
+ offset += to_draw * 2;
+ }
+
+ } else {
+
+ _draw_generic(GL_LINES, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1);
+ }
#ifdef GLES_OVER_GL
if (pline->antialiased)
@@ -1705,6 +1723,7 @@ void RasterizerCanvasGLES3::initialize() {
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
glBufferData(GL_ARRAY_BUFFER, poly_size, NULL, GL_DYNAMIC_DRAW); //allocate max size
glBindBuffer(GL_ARRAY_BUFFER, 0);
+ data.polygon_buffer_size = poly_size;
//quad arrays
for (int i = 0; i < 4; i++) {
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index 325df8e4f1..21102e8c25 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -81,6 +81,16 @@ static int _get_datatype_size(SL::DataType p_type) {
ERR_FAIL_V(0);
}
+static String _interpstr(SL::DataInterpolation p_interp) {
+
+ switch (p_interp) {
+ case SL::INTERPOLATION_FLAT: return "flat ";
+ case SL::INTERPOLATION_NO_PERSPECTIVE: return "noperspective ";
+ case SL::INTERPOLATION_SMOOTH: return "smooth ";
+ }
+ return "";
+}
+
static String _prestr(SL::DataPrecision p_pres) {
switch (p_pres) {
@@ -220,7 +230,6 @@ void ShaderCompilerGLES3::_dump_function_deps(SL::ShaderNode *p_node, const Stri
for (Set<StringName>::Element *E = p_node->functions[fidx].uses_function.front(); E; E = E->next()) {
- print_line(String(p_node->functions[fidx].name) + " uses function: " + String(E->get()));
if (added.has(E->get())) {
continue; //was added already
}
@@ -383,12 +392,13 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
for (Map<StringName, SL::ShaderNode::Varying>::Element *E = pnode->varyings.front(); E; E = E->next()) {
String vcode;
+ String interp_mode = _interpstr(E->get().interpolation);
vcode += _prestr(E->get().precission);
vcode += _typestr(E->get().type);
vcode += " " + _mkid(E->key());
vcode += ";\n";
- r_gen_code.vertex_global += "out " + vcode;
- r_gen_code.fragment_global += "in " + vcode;
+ r_gen_code.vertex_global += interp_mode + "out " + vcode;
+ r_gen_code.fragment_global += interp_mode + "in " + vcode;
}
Map<StringName, String> function_code;
diff --git a/drivers/gles3/shaders/particles.glsl b/drivers/gles3/shaders/particles.glsl
index a62c124dfe..fbee08c0fe 100644
--- a/drivers/gles3/shaders/particles.glsl
+++ b/drivers/gles3/shaders/particles.glsl
@@ -116,7 +116,7 @@ void main() {
#endif
}
- } else {
+ } else if(delta > 0.0) {
if (restart_phase >= prev_system_phase) {
restart=true;
#ifdef USE_FRACTIONAL_DELTA
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 5a06a58b80..bc18707deb 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -141,42 +141,14 @@ void OS_Unix::alert(const String &p_alert, const String &p_title) {
fprintf(stderr, "ERROR: %s\n", p_alert.utf8().get_data());
}
-static int has_data(FILE *p_fd, int timeout_usec = 0) {
-
- fd_set readset;
- int fd = fileno(p_fd);
- FD_ZERO(&readset);
- FD_SET(fd, &readset);
- timeval time;
- time.tv_sec = 0;
- time.tv_usec = timeout_usec;
- int res = 0; //select(fd + 1, &readset, NULL, NULL, &time);
- return res > 0;
-};
-
String OS_Unix::get_stdin_string(bool p_block) {
- String ret;
if (p_block) {
char buff[1024];
- ret = stdin_buf + fgets(buff, 1024, stdin);
+ String ret = stdin_buf + fgets(buff, 1024, stdin);
stdin_buf = "";
return ret;
- };
-
- while (has_data(stdin)) {
-
- char ch;
- read(fileno(stdin), &ch, 1);
- if (ch == '\n') {
- ret = stdin_buf;
- stdin_buf = "";
- return ret;
- } else {
- char str[2] = { ch, 0 };
- stdin_buf += str;
- };
- };
+ }
return "";
}
@@ -194,8 +166,6 @@ uint64_t OS_Unix::get_unix_time() const {
uint64_t OS_Unix::get_system_time_secs() const {
struct timeval tv_now;
gettimeofday(&tv_now, NULL);
- //localtime(&tv_now.tv_usec);
- //localtime((const long *)&tv_now.tv_usec);
return uint64_t(tv_now.tv_sec);
}
diff --git a/editor/animation_editor.cpp b/editor/animation_editor.cpp
index 1d70f8ba55..c6757ba98f 100644
--- a/editor/animation_editor.cpp
+++ b/editor/animation_editor.cpp
@@ -1124,6 +1124,8 @@ void AnimationKeyEditor::_track_editor_draw() {
Ref<Texture> add_key_icon = get_icon("TrackAddKey", "EditorIcons");
Ref<Texture> add_key_icon_hl = get_icon("TrackAddKeyHl", "EditorIcons");
Ref<Texture> down_icon = get_icon("select_arrow", "Tree");
+ Ref<Texture> checked = get_icon("checked", "Tree");
+ Ref<Texture> unchecked = get_icon("unchecked", "Tree");
Ref<Texture> wrap_icon[2] = {
get_icon("InterpWrapClamp", "EditorIcons"),
@@ -1170,6 +1172,7 @@ void AnimationKeyEditor::_track_editor_draw() {
v_scroll->set_page(fit);
}
+ int left_check_ofs = checked->get_width();
int settings_limit = size.width - right_separator_ofs;
int name_limit = settings_limit * name_column_ratio;
@@ -1332,6 +1335,7 @@ void AnimationKeyEditor::_track_editor_draw() {
valid_type = obj->get_static_property_type_indexed(leftover_path, &prop_exists);
}
+ // Draw background color of the whole track
if (/*mouse_over.over!=MouseOver::OVER_NONE &&*/ idx == mouse_over.track) {
Color sepc = hover_color;
te->draw_rect(Rect2(ofs + Point2(0, y), Size2(size.width, h - 1)), sepc);
@@ -1343,14 +1347,20 @@ void AnimationKeyEditor::_track_editor_draw() {
te->draw_rect(Rect2(ofs + Point2(0, y), Size2(size.width - 1, h - 1)), tc);
}
- te->draw_texture(type_icon[animation->track_get_type(idx)], ofs + Point2(0, y + (h - type_icon[0]->get_height()) / 2).floor());
+ // Draw track enabled state check box
+ Ref<Texture> check_box = animation->track_is_enabled(idx) ? checked : unchecked;
+ te->draw_texture(check_box, ofs + Point2(0, y + (h - checked->get_height()) / 2).floor());
+
+ // Draw track type glyph and node path
+ te->draw_texture(type_icon[animation->track_get_type(idx)], ofs + Point2(left_check_ofs + sep, y + (h - type_icon[0]->get_height()) / 2).floor());
NodePath np = animation->track_get_path(idx);
Node *n = root ? root->get_node(np) : (Node *)NULL;
Color ncol = color;
if (n && editor_selection->is_selected(n))
ncol = track_select_color;
- te->draw_string(font, Point2(ofs + Point2(type_icon[0]->get_width() + sep, y + font->get_ascent() + (sep / 2))).floor(), np, ncol, name_limit - (type_icon[0]->get_width() + sep) - 5);
+ te->draw_string(font, Point2(ofs + Point2(left_check_ofs + sep + type_icon[0]->get_width() + sep, y + font->get_ascent() + (sep / 2))).floor(), np, ncol, name_limit - (type_icon[0]->get_width() + sep) - 5);
+ // Draw separator line below track area
if (!obj)
te->draw_line(ofs + Point2(0, y + h / 2), ofs + Point2(name_limit, y + h / 2), invalid_path_color);
@@ -1798,6 +1808,7 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input)
Ref<Texture> down_icon = get_icon("select_arrow", "Tree");
Ref<Texture> hsize_icon = get_icon("Hsize", "EditorIcons");
Ref<Texture> add_key_icon = get_icon("TrackAddKey", "EditorIcons");
+ Ref<Texture> check_icon = get_icon("checked", "Tree");
Ref<Texture> wrap_icon[2] = {
get_icon("InterpWrapClamp", "EditorIcons"),
@@ -1832,6 +1843,7 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input)
v_scroll->set_page(fit);
}
+ int left_check_ofs = check_icon->get_width();
int settings_limit = size.width - right_separator_ofs;
int name_limit = settings_limit * name_column_ratio;
@@ -2092,7 +2104,12 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input)
return;
}
- if (mpos.x < name_limit - (type_icon[0]->get_width() / 2.0)) {
+ if (mpos.x < left_check_ofs) {
+ // Checkbox on the very left to enable/disable tracks.
+
+ animation->track_set_enabled(idx, !animation->track_is_enabled(idx));
+
+ } else if (mpos.x < name_limit - (type_icon[0]->get_width() / 2.0)) {
//name column
// area
@@ -2103,7 +2120,7 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input)
return;
}
- Rect2 area(ofs.x, ofs.y + ((int(mpos.y) / h) + 1) * h, name_limit, h);
+ Rect2 area(ofs.x + left_check_ofs + sep, ofs.y + ((int(mpos.y) / h) + 1) * h, name_limit - left_check_ofs - sep, h);
track_name->set_text(animation->track_get_path(idx));
track_name->set_position(te->get_global_position() + area.position);
track_name->set_size(area.size);
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 8f427582ae..676b168371 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -202,8 +202,9 @@ class EditorHelpSearch::IncrementalSearch : public Reference {
}
public:
- IncrementalSearch(EditorHelpSearch *p_search, Tree *p_search_options, const String &p_term)
- : search(p_search), search_options(p_search_options) {
+ IncrementalSearch(EditorHelpSearch *p_search, Tree *p_search_options, const String &p_term) :
+ search(p_search),
+ search_options(p_search_options) {
def_icon = search->get_icon("Node", "EditorIcons");
doc = EditorHelp::get_doc_data();
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 0252358a27..27ed53bb42 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -1884,7 +1884,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), scene_filename != "" ? scene_filename : "unsaved scene"));
save_confirmation->popup_centered_minsize();
break;
+ } else {
+ tab_closing = editor_data.get_edited_scene();
}
+
} // fallthrough
case SCENE_TAB_CLOSE:
case FILE_SAVE_SCENE: {
@@ -3366,7 +3369,6 @@ void EditorNode::register_editor_types() {
ClassDB::register_class<EditorResourceConversionPlugin>();
ClassDB::register_class<EditorSceneImporter>();
-
// FIXME: Is this stuff obsolete, or should it be ported to new APIs?
ClassDB::register_class<EditorScenePostImport>();
//ClassDB::register_type<EditorImportExport>();
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index a39e4d6efb..5c4c2b694f 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -565,12 +565,12 @@ void EditorPlugin::save_global_state() {}
void EditorPlugin::add_import_plugin(const Ref<EditorImportPlugin> &p_importer) {
ResourceFormatImporter::get_singleton()->add_importer(p_importer);
- EditorFileSystem::get_singleton()->scan();
+ EditorFileSystem::get_singleton()->call_deferred("scan");
}
void EditorPlugin::remove_import_plugin(const Ref<EditorImportPlugin> &p_importer) {
ResourceFormatImporter::get_singleton()->remove_importer(p_importer);
- EditorFileSystem::get_singleton()->scan();
+ EditorFileSystem::get_singleton()->call_deferred("scan");
}
void EditorPlugin::add_export_plugin(const Ref<EditorExportPlugin> &p_exporter) {
@@ -587,7 +587,6 @@ void EditorPlugin::add_scene_import_plugin(const Ref<EditorSceneImporter> &p_imp
void EditorPlugin::remove_scene_import_plugin(const Ref<EditorSceneImporter> &p_importer) {
ResourceImporterScene::get_singleton()->remove_importer(p_importer);
-
}
void EditorPlugin::set_window_layout(Ref<ConfigFile> p_layout) {
diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h
index 89a6d3d250..f45d1c1ecc 100644
--- a/editor/editor_plugin.h
+++ b/editor/editor_plugin.h
@@ -31,11 +31,11 @@
#define EDITOR_PLUGIN_H
#include "editor/import/editor_import_plugin.h"
+#include "editor/import/resource_importer_scene.h"
#include "io/config_file.h"
#include "scene/gui/tool_button.h"
#include "scene/main/node.h"
#include "scene/resources/texture.h"
-#include "editor/import/resource_importer_scene.h"
#include "undo_redo.h"
/**
diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp
index 90cbabcc4f..09bfa0aff0 100644
--- a/editor/editor_run.cpp
+++ b/editor/editor_run.cpp
@@ -101,7 +101,14 @@ Error EditorRun::run(const String &p_scene, const String p_custom_args, const Li
args.push_back(itos(screen_rect.position.x) + "," + itos(screen_rect.position.y));
} break;
case 1: { // centered
- Vector2 pos = screen_rect.position + ((screen_rect.size - desired_size) / 2).floor();
+ int display_scale = 1;
+#ifdef OSX_ENABLED
+ if (OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).x > 2000) {
+ display_scale = 2;
+ }
+#endif
+
+ Vector2 pos = screen_rect.position + ((screen_rect.size / display_scale - desired_size) / 2).floor();
args.push_back("--position");
args.push_back(itos(pos.x) + "," + itos(pos.y));
} break;
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 04e09abcea..d199b27b83 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -348,7 +348,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/files/autosave_interval_secs", 0);
_initial_set("text_editor/cursor/block_caret", false);
- _initial_set("text_editor/cursor/caret_blink", false);
+ _initial_set("text_editor/cursor/caret_blink", true);
_initial_set("text_editor/cursor/caret_blink_speed", 0.65);
hints["text_editor/cursor/caret_blink_speed"] = PropertyInfo(Variant::REAL, "text_editor/cursor/caret_blink_speed", PROPERTY_HINT_RANGE, "0.1, 10, 0.1");
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 4661fcf668..152eda7d91 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -587,9 +587,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// Checkbox
Ref<StyleBoxFlat> sb_checkbox = style_menu->duplicate();
- // HACK, in reality, the checkbox draws the text over the icon by default, so the margin compensates that.
- const int cb_w = theme->get_icon("GuiChecked", "EditorIcons")->get_width() + default_margin_size;
- sb_checkbox->set_default_margin(MARGIN_LEFT, cb_w * EDSCALE);
+ sb_checkbox->set_default_margin(MARGIN_LEFT, default_margin_size * EDSCALE);
sb_checkbox->set_default_margin(MARGIN_RIGHT, default_margin_size * EDSCALE);
sb_checkbox->set_default_margin(MARGIN_TOP, default_margin_size * EDSCALE);
sb_checkbox->set_default_margin(MARGIN_BOTTOM, default_margin_size * EDSCALE);
@@ -625,6 +623,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_icon("radio_checked", "PopupMenu", theme->get_icon("GuiChecked", "EditorIcons"));
theme->set_icon("radio_unchecked", "PopupMenu", theme->get_icon("GuiUnchecked", "EditorIcons"));
theme->set_icon("submenu", "PopupMenu", theme->get_icon("ArrowRight", "EditorIcons"));
+ theme->set_icon("visibility_hidden", "PopupMenu", theme->get_icon("GuiVisibilityHidden", "EditorIcons"));
+ theme->set_icon("visibility_visible", "PopupMenu", theme->get_icon("GuiVisibilityVisible", "EditorIcons"));
+ theme->set_icon("visibility_xray", "PopupMenu", theme->get_icon("GuiVisibilityXray", "EditorIcons"));
theme->set_constant("vseparation", "PopupMenu", (extra_spacing + default_margin_size) * EDSCALE);
// Tree & ItemList background
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index ca6571fdda..9ece36ea80 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -806,6 +806,39 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
memdelete(da);
}
+void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const {
+ //Ensure folder paths end with "/"
+ String old_path = (p_item.is_file || p_item.path.ends_with("/")) ? p_item.path : (p_item.path + "/");
+ String new_path = (p_item.is_file || p_new_path.ends_with("/")) ? p_new_path : (p_new_path + "/");
+
+ if (new_path == old_path) {
+ return;
+ } else if (old_path == "res://") {
+ EditorNode::get_singleton()->add_io_error(TTR("Cannot move/rename resources root."));
+ return;
+ } else if (!p_item.is_file && new_path.begins_with(old_path)) {
+ //This check doesn't erroneously catch renaming to a longer name as folder paths always end with "/"
+ EditorNode::get_singleton()->add_io_error(TTR("Cannot move a folder into itself.\n") + old_path + "\n");
+ return;
+ }
+
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ print_line("Duplicating " + old_path + " -> " + new_path);
+ Error err = da->copy(old_path, new_path);
+ if (err == OK) {
+ //Move/Rename any corresponding import settings too
+ if (p_item.is_file && FileAccess::exists(old_path + ".import")) {
+ err = da->copy(old_path + ".import", new_path + ".import");
+ if (err != OK) {
+ EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:\n") + old_path + ".import\n");
+ }
+ }
+ } else {
+ EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:\n") + old_path + "\n");
+ }
+ memdelete(da);
+}
+
void FileSystemDock::_update_dependencies_after_move(const Map<String, String> &p_renames) const {
//The following code assumes that the following holds:
// 1) EditorFileSystem contains the old paths/folder structure from before the rename/move.
@@ -888,6 +921,39 @@ void FileSystemDock::_rename_operation_confirm() {
_rescan();
}
+void FileSystemDock::_duplicate_operation_confirm() {
+
+ String new_name = duplicate_dialog_text->get_text().strip_edges();
+ if (new_name.length() == 0) {
+ EditorNode::get_singleton()->show_warning(TTR("No name provided."));
+ return;
+ } else if (new_name.find("/") != -1 || new_name.find("\\") != -1 || new_name.find(":") != -1) {
+ EditorNode::get_singleton()->show_warning(TTR("Name contains invalid characters."));
+ return;
+ }
+
+ String old_path = to_duplicate.path.ends_with("/") ? to_duplicate.path.substr(0, to_duplicate.path.length() - 1) : to_rename.path;
+ String new_path = old_path.get_base_dir().plus_file(new_name);
+ if (old_path == new_path) {
+ return;
+ }
+
+ //Present a more user friendly warning for name conflict
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (da->file_exists(new_path) || da->dir_exists(new_path)) {
+ EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
+ memdelete(da);
+ return;
+ }
+ memdelete(da);
+
+ _try_duplicate_item(to_duplicate, new_name);
+
+ //Rescan everything
+ print_line("call rescan!");
+ _rescan();
+}
+
void FileSystemDock::_move_operation_confirm(const String &p_to_path) {
Map<String, String> renames;
@@ -1003,6 +1069,27 @@ void FileSystemDock::_file_option(int p_option) {
//2) warn
}
} break;
+ case FILE_DUPLICATE: {
+ int idx = files->get_current();
+ if (idx < 0 || idx >= files->get_item_count())
+ break;
+
+ to_duplicate.path = files->get_item_metadata(idx);
+ to_duplicate.is_file = !to_duplicate.path.ends_with("/");
+ if (to_duplicate.is_file) {
+ String name = to_duplicate.path.get_file();
+ duplicate_dialog->set_title(TTR("Duplicating file:") + " " + name);
+ duplicate_dialog_text->set_text(name);
+ duplicate_dialog_text->select(0, name.find_last("."));
+ } else {
+ String name = to_duplicate.path.substr(0, to_duplicate.path.length() - 1).get_file();
+ duplicate_dialog->set_title(TTR("Duplicating folder:") + " " + name);
+ duplicate_dialog_text->set_text(name);
+ duplicate_dialog_text->select(0, name.length());
+ }
+ duplicate_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE);
+ duplicate_dialog_text->grab_focus();
+ } break;
case FILE_INFO: {
} break;
@@ -1441,10 +1528,14 @@ void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) {
if (!all_files_scenes && filenames.size() == 1) {
file_options->add_item(TTR("Open"), FILE_OPEN);
file_options->add_separator();
+ }
+
+ if (filenames.size() == 1) {
file_options->add_item(TTR("Edit Dependencies.."), FILE_DEPENDENCIES);
file_options->add_item(TTR("View Owners.."), FILE_OWNERS);
file_options->add_separator();
}
+
} else if (all_folders && foldernames.size() > 0) {
file_options->add_item(TTR("Open"), FILE_OPEN);
file_options->add_separator();
@@ -1455,6 +1546,7 @@ void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) {
if (num_items == 1) {
file_options->add_item(TTR("Copy Path"), FILE_COPY_PATH);
file_options->add_item(TTR("Rename.."), FILE_RENAME);
+ file_options->add_item(TTR("Duplicate.."), FILE_DUPLICATE);
}
file_options->add_item(TTR("Move To.."), FILE_MOVE);
file_options->add_item(TTR("Delete"), FILE_REMOVE);
@@ -1566,6 +1658,7 @@ void FileSystemDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_make_dir_confirm"), &FileSystemDock::_make_dir_confirm);
ClassDB::bind_method(D_METHOD("_move_operation_confirm"), &FileSystemDock::_move_operation_confirm);
ClassDB::bind_method(D_METHOD("_rename_operation_confirm"), &FileSystemDock::_rename_operation_confirm);
+ ClassDB::bind_method(D_METHOD("_duplicate_operation_confirm"), &FileSystemDock::_duplicate_operation_confirm);
ClassDB::bind_method(D_METHOD("_search_changed"), &FileSystemDock::_search_changed);
@@ -1739,6 +1832,17 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
rename_dialog->register_text_enter(rename_dialog_text);
rename_dialog->connect("confirmed", this, "_rename_operation_confirm");
+ duplicate_dialog = memnew(ConfirmationDialog);
+ VBoxContainer *duplicate_dialog_vb = memnew(VBoxContainer);
+ duplicate_dialog->add_child(duplicate_dialog_vb);
+
+ duplicate_dialog_text = memnew(LineEdit);
+ duplicate_dialog_vb->add_margin_child(TTR("Name:"), duplicate_dialog_text);
+ duplicate_dialog->get_ok()->set_text(TTR("Duplicate"));
+ add_child(duplicate_dialog);
+ duplicate_dialog->register_text_enter(duplicate_dialog_text);
+ duplicate_dialog->connect("confirmed", this, "_duplicate_operation_confirm");
+
make_dir_dialog = memnew(ConfirmationDialog);
make_dir_dialog->set_title(TTR("Create Folder"));
VBoxContainer *make_folder_dialog_vb = memnew(VBoxContainer);
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index b004b1974d..bc8d835ba1 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -70,6 +70,7 @@ private:
FILE_MOVE,
FILE_RENAME,
FILE_REMOVE,
+ FILE_DUPLICATE,
FILE_REIMPORT,
FILE_INFO,
FILE_NEW_FOLDER,
@@ -120,6 +121,8 @@ private:
EditorDirDialog *move_dialog;
ConfirmationDialog *rename_dialog;
LineEdit *rename_dialog_text;
+ ConfirmationDialog *duplicate_dialog;
+ LineEdit *duplicate_dialog_text;
ConfirmationDialog *make_dir_dialog;
LineEdit *make_dir_dialog_text;
@@ -136,6 +139,7 @@ private:
is_file(p_is_file) {}
};
FileOrFolder to_rename;
+ FileOrFolder to_duplicate;
Vector<FileOrFolder> to_move;
Vector<String> history;
@@ -172,10 +176,12 @@ private:
void _get_all_files_in_dir(EditorFileSystemDirectory *efsd, Vector<String> &files) const;
void _find_remaps(EditorFileSystemDirectory *efsd, const Map<String, String> &renames, Vector<String> &to_remaps) const;
void _try_move_item(const FileOrFolder &p_item, const String &p_new_path, Map<String, String> &p_renames) const;
+ void _try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const;
void _update_dependencies_after_move(const Map<String, String> &p_renames) const;
void _make_dir_confirm();
void _rename_operation_confirm();
+ void _duplicate_operation_confirm();
void _move_operation_confirm(const String &p_to_path);
void _file_option(int p_option);
diff --git a/editor/icons/icon_GUI_visibility_hidden.svg b/editor/icons/icon_GUI_visibility_hidden.svg
new file mode 100644
index 0000000000..2add2e9eb8
--- /dev/null
+++ b/editor/icons/icon_GUI_visibility_hidden.svg
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ version="1.1"
+ viewBox="0 0 16 16"
+ id="svg2"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="icon_GUI_visibility_hidden.svg">
+ <metadata
+ id="metadata12">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs10" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1027"
+ id="namedview8"
+ showgrid="false"
+ inkscape:zoom="14.75"
+ inkscape:cx="18.882384"
+ inkscape:cy="7.2939487"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" />
+ <path
+ style="color:#000000;text-indent:0;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;white-space:normal;isolation:auto;mix-blend-mode:normal;solid-color:#000000;fill:#e0e0e0;fill-opacity:1;fill-rule:evenodd;color-rendering:auto;image-rendering:auto;shape-rendering:auto"
+ d="M 8.3320312 2.1328125 C 8.1166713 2.129146 7.900423 2.1368613 7.6855469 2.1542969 C 4.8418629 2.3850399 2.1034153 4.4237115 1.0449219 7.5722656 C 0.98765482 7.7577705 0.9856205 7.9559357 1.0390625 8.1425781 C 1.2458895 8.8664725 1.5352035 9.5092453 1.8730469 10.089844 L 12.501953 3.7890625 C 11.256805 2.6845102 9.797893 2.1577685 8.3320312 2.1328125 z M 14.554688 3.3046875 L 0.7421875 11.507812 L 1.4453125 12.695312 L 15.257812 4.4921875 L 14.554688 3.3046875 z M 14.169922 5.8847656 L 3.6171875 12.140625 C 4.9944165 13.294116 6.6188565 13.867188 8 13.867188 C 10.5 13.867188 13.836536 12.077978 14.960938 8.1425781 C 15.012856 7.9619931 15.012856 7.7704285 14.960938 7.5898438 C 14.731965 6.9583712 14.46336 6.3981967 14.169922 5.8847656 z "
+ id="path6" />
+</svg>
diff --git a/editor/icons/icon_GUI_visibility_visible.svg b/editor/icons/icon_GUI_visibility_visible.svg
new file mode 100644
index 0000000000..11ae563779
--- /dev/null
+++ b/editor/icons/icon_GUI_visibility_visible.svg
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ version="1.1"
+ viewBox="0 0 16 16"
+ id="svg2"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="icon_visibility_visible.svg">
+ <metadata
+ id="metadata12">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs10" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1027"
+ id="namedview8"
+ showgrid="false"
+ inkscape:zoom="14.75"
+ inkscape:cx="15.823281"
+ inkscape:cy="12.108563"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" />
+ <g
+ transform="translate(0 -1036.4)"
+ id="g4"
+ style="fill:#e0e0e0;fill-opacity:1">
+ <path
+ transform="translate(0,1036.4)"
+ d="M 8,2 C 5.4433,2 2.2093,3.9477 1.0449,7.7051 c -0.0572671,0.1855049 -0.059303,0.3836676 -0.00586,0.57031 1.1244,3.9354 4.4609,5.7246 6.9609,5.7246 2.5000004,0 5.8365004,-1.7892 6.9609004,-5.7246 0.05192,-0.180585 0.05192,-0.372145 0,-0.55273 -1.1003,-3.7876 -4.4066,-5.7227 -6.9609004,-5.7227 z m 0,2 c 2.209139,0 4,1.790861 4,4 0,2.209139 -1.790861,4 -4,4 C 5.790861,12 4,10.209139 4,8 4,5.790861 5.790861,4 8,4 Z M 8,6 C 6.8954305,6 6,6.8954305 6,8 6,9.1045695 6.8954305,10 8,10 9.1045695,10 10,9.1045695 10,8 10,6.8954305 9.1045695,6 8,6 Z"
+ style="color:#000000;text-indent:0;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;white-space:normal;isolation:auto;mix-blend-mode:normal;solid-color:#000000;fill:#e0e0e0;fill-opacity:1;fill-rule:evenodd;color-rendering:auto;image-rendering:auto;shape-rendering:auto"
+ id="path6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccsccccssssssssss" />
+ </g>
+</svg>
diff --git a/editor/icons/icon_GUI_visibility_xray.svg b/editor/icons/icon_GUI_visibility_xray.svg
new file mode 100644
index 0000000000..1fd9fcf1b5
--- /dev/null
+++ b/editor/icons/icon_GUI_visibility_xray.svg
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ version="1.1"
+ viewBox="0 0 16 16"
+ id="svg2"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="icon_GUI_visibility_xray.svg">
+ <metadata
+ id="metadata12">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs10" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1027"
+ id="namedview8"
+ showgrid="false"
+ inkscape:zoom="7.375"
+ inkscape:cx="43.019438"
+ inkscape:cy="-8.9853027"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" />
+ <g
+ transform="translate(0.20338214,-1036.671)"
+ id="g4"
+ style="fill:#e0e0e0;fill-opacity:1" />
+ <path
+ id="path4154"
+ style="opacity:1;fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.42799997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="m 5.0107427,7.1191578 c -0.084872,0.2859445 -0.1282828,0.5825859 -0.128907,0.8808593 8.579e-4,0.263009 0.034983,0.5248532 0.101563,0.7792969 l 6.0312493,0 C 11.081887,8.5249547 11.116668,8.2631092 11.118164,8.0000171 11.11754,7.7017437 11.074129,7.4051023 10.989257,7.1191578 Z M 7.9999096,2.000005 c -2.5567,0 -5.7907,1.9477 -6.9551,5.7051 -0.057267,0.1855049 -0.059303,0.3836676 -0.00586,0.57031 1.1244,3.9354 4.4609,5.7246 6.9609,5.7246 2.4999994,0 5.8364994,-1.7892 6.9608994,-5.7246 0.05192,-0.180585 0.05192,-0.372145 0,-0.55273 -1.1003,-3.7876 -4.4066,-5.7227 -6.9608994,-5.7227 z m 0,2 c 2.2091384,0 3.9999994,1.790861 3.9999994,4 0,2.209139 -1.790861,4 -3.9999994,4 -2.209139,0 -4,-1.790861 -4,-4 0,-2.209139 1.790861,-4 4,-4 z"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccsccccsssss" />
+</svg>
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index c38391c71b..c4315f1b83 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -1979,7 +1979,7 @@ Node *EditorSceneImporterCollada::import_scene(const String &p_path, uint32_t p_
return state.scene;
}
-Ref<Animation> EditorSceneImporterCollada::import_animation(const String &p_path, uint32_t p_flags,int p_bake_fps) {
+Ref<Animation> EditorSceneImporterCollada::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) {
ColladaImport state;
diff --git a/editor/import/editor_import_collada.h b/editor/import/editor_import_collada.h
index 986b5b766f..904080c19b 100644
--- a/editor/import/editor_import_collada.h
+++ b/editor/import/editor_import_collada.h
@@ -40,7 +40,7 @@ public:
virtual uint32_t get_import_flags() const;
virtual void get_extensions(List<String> *r_extensions) const;
virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps = NULL, Error *r_err = NULL);
- virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags,int p_bake_fps);
+ virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps);
EditorSceneImporterCollada();
};
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index e801f3e7c3..00eb69a568 100644
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ b/editor/import/editor_scene_importer_gltf.cpp
@@ -1597,8 +1597,11 @@ void EditorSceneImporterGLTF::_generate_node(GLTFState &state, int p_node, Node
if (n->mesh >= 0) {
ERR_FAIL_INDEX(n->mesh, state.meshes.size());
MeshInstance *mi = memnew(MeshInstance);
- const GLTFMesh &mesh = state.meshes[n->mesh];
+ GLTFMesh &mesh = state.meshes[n->mesh];
mi->set_mesh(mesh.mesh);
+ if (mesh.mesh->get_name() == "") {
+ mesh.mesh->set_name(n->name);
+ }
for (int i = 0; i < mesh.blend_weights.size(); i++) {
mi->set("blend_shapes/" + mesh.mesh->get_blend_shape_name(i), mesh.blend_weights[i]);
}
diff --git a/editor/import/editor_scene_importer_gltf.h b/editor/import/editor_scene_importer_gltf.h
index 0c8000427e..91c584a05a 100644
--- a/editor/import/editor_scene_importer_gltf.h
+++ b/editor/import/editor_scene_importer_gltf.h
@@ -296,7 +296,7 @@ public:
virtual uint32_t get_import_flags() const;
virtual void get_extensions(List<String> *r_extensions) const;
virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps = NULL, Error *r_err = NULL);
- virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags,int p_bake_fps);
+ virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps);
EditorSceneImporterGLTF();
};
diff --git a/editor/import/resource_importer_obj.h b/editor/import/resource_importer_obj.h
index 09dc8ac8a1..e66ea47b69 100644
--- a/editor/import/resource_importer_obj.h
+++ b/editor/import/resource_importer_obj.h
@@ -40,7 +40,7 @@ public:
virtual uint32_t get_import_flags() const;
virtual void get_extensions(List<String> *r_extensions) const;
virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = NULL);
- virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags,int p_bake_fps);
+ virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps);
EditorOBJImporter();
};
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index 4ef8ec48a0..08d2897250 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -47,8 +47,6 @@
#include "scene/resources/ray_shape.h"
#include "scene/resources/sphere_shape.h"
-
-
uint32_t EditorSceneImporter::get_import_flags() const {
if (get_script_instance()) {
@@ -60,80 +58,73 @@ uint32_t EditorSceneImporter::get_import_flags() const {
void EditorSceneImporter::get_extensions(List<String> *r_extensions) const {
if (get_script_instance()) {
- Array arr= get_script_instance()->call("_get_extensions");
- for(int i=0;i<arr.size();i++) {
+ Array arr = get_script_instance()->call("_get_extensions");
+ for (int i = 0; i < arr.size(); i++) {
r_extensions->push_back(arr[i]);
}
return;
}
ERR_FAIL();
-
}
Node *EditorSceneImporter::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) {
if (get_script_instance()) {
- return get_script_instance()->call("_import_scene",p_path,p_flags,p_bake_fps);
+ return get_script_instance()->call("_import_scene", p_path, p_flags, p_bake_fps);
}
ERR_FAIL_V(NULL);
-
}
-Ref<Animation> EditorSceneImporter::import_animation(const String &p_path, uint32_t p_flags,int p_bake_fps) {
+Ref<Animation> EditorSceneImporter::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) {
if (get_script_instance()) {
- return get_script_instance()->call("_import_animation",p_path,p_flags);
+ return get_script_instance()->call("_import_animation", p_path, p_flags);
}
ERR_FAIL_V(NULL);
-
}
//for documenters, these functions are useful when an importer calls an external conversion helper (like, fbx2gltf),
//and you want to load the resulting file
-Node* EditorSceneImporter::import_scene_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps) {
-
- return ResourceImporterScene::get_singleton()->import_scene_from_other_importer(this,p_path,p_flags,p_bake_fps);
+Node *EditorSceneImporter::import_scene_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps) {
+ return ResourceImporterScene::get_singleton()->import_scene_from_other_importer(this, p_path, p_flags, p_bake_fps);
}
Ref<Animation> EditorSceneImporter::import_animation_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps) {
- return ResourceImporterScene::get_singleton()->import_animation_from_other_importer(this,p_path,p_flags,p_bake_fps);
-
+ return ResourceImporterScene::get_singleton()->import_animation_from_other_importer(this, p_path, p_flags, p_bake_fps);
}
void EditorSceneImporter::_bind_methods() {
- ClassDB::bind_method(D_METHOD("import_scene_from_other_importer","path","flags","bake_fps"),&EditorSceneImporter::import_scene_from_other_importer);
- ClassDB::bind_method(D_METHOD("import_animation_from_other_importer","path","flags","bake_fps"),&EditorSceneImporter::import_animation_from_other_importer);
+ ClassDB::bind_method(D_METHOD("import_scene_from_other_importer", "path", "flags", "bake_fps"), &EditorSceneImporter::import_scene_from_other_importer);
+ ClassDB::bind_method(D_METHOD("import_animation_from_other_importer", "path", "flags", "bake_fps"), &EditorSceneImporter::import_animation_from_other_importer);
BIND_VMETHOD(MethodInfo(Variant::INT, "_get_import_flags"));
BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_get_extensions"));
- MethodInfo mi = MethodInfo(Variant::OBJECT, "_import_scene",PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "flags"), PropertyInfo(Variant::INT, "bake_fps"));
- mi.return_val.class_name="Node";
+ MethodInfo mi = MethodInfo(Variant::OBJECT, "_import_scene", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "flags"), PropertyInfo(Variant::INT, "bake_fps"));
+ mi.return_val.class_name = "Node";
BIND_VMETHOD(mi);
- mi = MethodInfo(Variant::OBJECT, "_import_animation",PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "flags"), PropertyInfo(Variant::INT, "bake_fps"));
- mi.return_val.class_name="Animation";
+ mi = MethodInfo(Variant::OBJECT, "_import_animation", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "flags"), PropertyInfo(Variant::INT, "bake_fps"));
+ mi.return_val.class_name = "Animation";
BIND_VMETHOD(mi);
- BIND_CONSTANT( IMPORT_SCENE );
- BIND_CONSTANT( IMPORT_ANIMATION );
- BIND_CONSTANT( IMPORT_ANIMATION_DETECT_LOOP );
- BIND_CONSTANT( IMPORT_ANIMATION_OPTIMIZE );
- BIND_CONSTANT( IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS );
- BIND_CONSTANT( IMPORT_ANIMATION_KEEP_VALUE_TRACKS );
- BIND_CONSTANT( IMPORT_GENERATE_TANGENT_ARRAYS );
- BIND_CONSTANT( IMPORT_FAIL_ON_MISSING_DEPENDENCIES );
- BIND_CONSTANT( IMPORT_MATERIALS_IN_INSTANCES );
- BIND_CONSTANT( IMPORT_USE_COMPRESSION );
-
+ BIND_CONSTANT(IMPORT_SCENE);
+ BIND_CONSTANT(IMPORT_ANIMATION);
+ BIND_CONSTANT(IMPORT_ANIMATION_DETECT_LOOP);
+ BIND_CONSTANT(IMPORT_ANIMATION_OPTIMIZE);
+ BIND_CONSTANT(IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS);
+ BIND_CONSTANT(IMPORT_ANIMATION_KEEP_VALUE_TRACKS);
+ BIND_CONSTANT(IMPORT_GENERATE_TANGENT_ARRAYS);
+ BIND_CONSTANT(IMPORT_FAIL_ON_MISSING_DEPENDENCIES);
+ BIND_CONSTANT(IMPORT_MATERIALS_IN_INSTANCES);
+ BIND_CONSTANT(IMPORT_USE_COMPRESSION);
}
-
/////////////////////////////////
void EditorScenePostImport::_bind_methods() {
@@ -201,6 +192,10 @@ bool ResourceImporterScene::get_option_visibility(const String &p_option, const
return false;
}
+ if (p_option == "meshes/lightmap_texel_size" && int(p_options["meshes/light_baking"]) < 2) {
+ return false;
+ }
+
return true;
}
@@ -961,6 +956,36 @@ static String _make_extname(const String &p_str) {
return ext_name;
}
+void ResourceImporterScene::_find_meshes(Node *p_node, Map<Ref<ArrayMesh>, Transform> &meshes) {
+
+ List<PropertyInfo> pi;
+ p_node->get_property_list(&pi);
+
+ MeshInstance *mi = Object::cast_to<MeshInstance>(p_node);
+
+ if (mi) {
+
+ Ref<ArrayMesh> mesh = mi->get_mesh();
+
+ if (mesh.is_valid() && !meshes.has(mesh)) {
+ Spatial *s = mi;
+ while (s->get_parent_spatial()) {
+ s = s->get_parent_spatial();
+ }
+
+ if (s == mi) {
+ meshes[mesh] = s->get_transform();
+ } else {
+ meshes[mesh] = s->get_transform() * mi->get_relative_transform(s);
+ }
+ }
+ }
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+
+ _find_meshes(p_node->get_child(i), meshes);
+ }
+}
+
void ResourceImporterScene::_make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_keep_animations, bool p_make_materials, bool p_keep_materials, bool p_make_meshes, Map<Ref<Animation>, Ref<Animation> > &p_animations, Map<Ref<Material>, Ref<Material> > &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh> > &p_meshes) {
List<PropertyInfo> pi;
@@ -1140,7 +1165,8 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/compress"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/ensure_tangents"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/storage", PROPERTY_HINT_ENUM, "Built-In,Files"), meshes_out ? 1 : 0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Enable"), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Enable,Gen Lightmaps"), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.05));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "external_files/store_in_subdir"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 15));
@@ -1171,17 +1197,16 @@ void ResourceImporterScene::_replace_owner(Node *p_node, Node *p_scene, Node *p_
Node *n = p_node->get_child(i);
_replace_owner(n, p_scene, p_new_owner);
}
-
}
-Node* ResourceImporterScene::import_scene_from_other_importer(EditorSceneImporter *p_exception,const String &p_path, uint32_t p_flags, int p_bake_fps) {
+Node *ResourceImporterScene::import_scene_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps) {
Ref<EditorSceneImporter> importer;
String ext = p_path.get_extension().to_lower();
for (Set<Ref<EditorSceneImporter> >::Element *E = importers.front(); E; E = E->next()) {
- if (E->get().ptr()==p_exception)
+ if (E->get().ptr() == p_exception)
continue;
List<String> extensions;
E->get()->get_extensions(&extensions);
@@ -1199,42 +1224,41 @@ Node* ResourceImporterScene::import_scene_from_other_importer(EditorSceneImporte
break;
}
- ERR_FAIL_COND_V(!importer.is_valid(),NULL);
+ ERR_FAIL_COND_V(!importer.is_valid(), NULL);
List<String> missing;
Error err;
- return importer->import_scene(p_path,p_flags,p_bake_fps,&missing,&err);
+ return importer->import_scene(p_path, p_flags, p_bake_fps, &missing, &err);
}
-Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(EditorSceneImporter *p_exception,const String &p_path, uint32_t p_flags, int p_bake_fps) {
-
+Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps) {
- Ref<EditorSceneImporter> importer;
- String ext = p_path.get_extension().to_lower();
+ Ref<EditorSceneImporter> importer;
+ String ext = p_path.get_extension().to_lower();
- for (Set<Ref<EditorSceneImporter> >::Element *E = importers.front(); E; E = E->next()) {
+ for (Set<Ref<EditorSceneImporter> >::Element *E = importers.front(); E; E = E->next()) {
- if (E->get().ptr()==p_exception)
- continue;
- List<String> extensions;
- E->get()->get_extensions(&extensions);
+ if (E->get().ptr() == p_exception)
+ continue;
+ List<String> extensions;
+ E->get()->get_extensions(&extensions);
- for (List<String>::Element *F = extensions.front(); F; F = F->next()) {
+ for (List<String>::Element *F = extensions.front(); F; F = F->next()) {
- if (F->get().to_lower() == ext) {
+ if (F->get().to_lower() == ext) {
- importer = E->get();
- break;
- }
- }
+ importer = E->get();
+ break;
+ }
+ }
- if (importer.is_valid())
- break;
- }
+ if (importer.is_valid())
+ break;
+ }
- ERR_FAIL_COND_V(!importer.is_valid(),NULL);
+ ERR_FAIL_COND_V(!importer.is_valid(), NULL);
- return importer->import_animation(p_path,p_flags,p_bake_fps);
+ return importer->import_animation(p_path, p_flags, p_bake_fps);
}
Error ResourceImporterScene::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files) {
@@ -1371,6 +1395,37 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
}
}
+ if (light_bake_mode == 2 /* || generate LOD */) {
+
+ Map<Ref<ArrayMesh>, Transform> meshes;
+ _find_meshes(scene, meshes);
+
+ if (light_bake_mode == 2) {
+
+ float texel_size = p_options["meshes/lightmap_texel_size"];
+ texel_size = MAX(0.001, texel_size);
+
+ EditorProgress progress("gen_lightmaps", TTR("Generating Lightmaps"), meshes.size());
+ int step = 0;
+ for (Map<Ref<ArrayMesh>, Transform>::Element *E = meshes.front(); E; E = E->next()) {
+
+ Ref<ArrayMesh> mesh = E->key();
+ String name = mesh->get_name();
+ if (name == "") { //should not happen but..
+ name = "Mesh " + itos(step);
+ }
+
+ progress.step(TTR("Generating for Mesh: ") + name + " (" + itos(step) + "/" + itos(meshes.size()) + ")", step);
+
+ Error err = mesh->lightmap_unwrap(E->get(), texel_size);
+ if (err != OK) {
+ EditorNode::add_io_error("Mesh '" + name + "' failed lightmap generation. Please fix geometry.");
+ }
+ step++;
+ }
+ }
+ }
+
if (external_animations || external_materials || external_meshes) {
Map<Ref<Animation>, Ref<Animation> > anim_map;
Map<Ref<Material>, Ref<Material> > mat_map;
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index fc6ce05fa4..933585a48c 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -40,13 +40,13 @@ class Material;
class EditorSceneImporter : public Reference {
GDCLASS(EditorSceneImporter, Reference);
-protected:
+protected:
static void _bind_methods();
-
- Node* import_scene_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps);
+ Node *import_scene_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps);
Ref<Animation> import_animation_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps);
+
public:
enum ImportFlags {
IMPORT_SCENE = 1,
@@ -62,11 +62,10 @@ public:
};
-
virtual uint32_t get_import_flags() const;
virtual void get_extensions(List<String> *r_extensions) const;
virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = NULL);
- virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags,int p_bake_fps);
+ virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps);
EditorSceneImporter() {}
};
@@ -136,6 +135,8 @@ public:
virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const;
virtual int get_import_order() const { return 100; } //after everything
+ void _find_meshes(Node *p_node, Map<Ref<ArrayMesh>, Transform> &meshes);
+
void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_keep_animations, bool p_make_materials, bool p_keep_materials, bool p_make_meshes, Map<Ref<Animation>, Ref<Animation> > &p_animations, Map<Ref<Material>, Ref<Material> > &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh> > &p_meshes);
Node *_fix_node(Node *p_node, Node *p_root, Map<Ref<ArrayMesh>, Ref<Shape> > &collision_map, LightBakeMode p_light_bake_mode);
@@ -147,8 +148,8 @@ public:
virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL);
- Node* import_scene_from_other_importer(EditorSceneImporter *p_exception,const String &p_path, uint32_t p_flags, int p_bake_fps);
- Ref<Animation> import_animation_from_other_importer(EditorSceneImporter *p_exception,const String &p_path, uint32_t p_flags, int p_bake_fps);
+ Node *import_scene_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps);
+ Ref<Animation> import_animation_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps);
ResourceImporterScene();
};
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index eee54f3cd2..3ab8f318a7 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -915,6 +915,11 @@ void EditorAssetLibrary::_search(int p_page) {
_api_request("asset", REQUESTING_SEARCH, args);
}
+void EditorAssetLibrary::_search_text_entered(const String &p_text) {
+
+ _search();
+}
+
HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int p_page_len, int p_total_items, int p_current_items) {
HBoxContainer *hbc = memnew(HBoxContainer);
@@ -1280,6 +1285,7 @@ void EditorAssetLibrary::_bind_methods() {
ClassDB::bind_method("_select_category", &EditorAssetLibrary::_select_category);
ClassDB::bind_method("_image_request_completed", &EditorAssetLibrary::_image_request_completed);
ClassDB::bind_method("_search", &EditorAssetLibrary::_search, DEFVAL(0));
+ ClassDB::bind_method("_search_text_entered", &EditorAssetLibrary::_search_text_entered);
ClassDB::bind_method("_install_asset", &EditorAssetLibrary::_install_asset);
ClassDB::bind_method("_manage_plugins", &EditorAssetLibrary::_manage_plugins);
ClassDB::bind_method("_asset_open", &EditorAssetLibrary::_asset_open);
@@ -1309,7 +1315,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
filter = memnew(LineEdit);
search_hb->add_child(filter);
filter->set_h_size_flags(SIZE_EXPAND_FILL);
- filter->connect("text_entered", this, "_search");
+ filter->connect("text_entered", this, "_search_text_entered");
search = memnew(Button(TTR("Search")));
search->connect("pressed", this, "_search");
search_hb->add_child(search);
diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h
index 90d597e70a..5536fbb2ec 100644
--- a/editor/plugins/asset_library_editor_plugin.h
+++ b/editor/plugins/asset_library_editor_plugin.h
@@ -284,6 +284,7 @@ class EditorAssetLibrary : public PanelContainer {
void _search(int p_page = 0);
void _rerun_search(int p_ignore);
+ void _search_text_entered(const String &p_text = "");
void _api_request(const String &p_request, RequestType p_request_type, const String &p_arguments = "");
void _http_request_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data);
void _http_download_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data);
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 8eee9c7e7c..ad22c12372 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -4342,6 +4342,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
drag = DRAG_NONE;
bone_last_frame = 0;
additive_selection = false;
+
+ // Update the menus checkboxes
+ call_deferred("set_state", get_state());
}
CanvasItemEditor *CanvasItemEditor::singleton = NULL;
@@ -4486,15 +4489,24 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String &
Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(ResourceCache::get(path)));
Size2 texture_size = texture->get_size();
- editor_data->get_undo_redo().add_do_method(parent, "add_child", child);
- editor_data->get_undo_redo().add_do_method(child, "set_owner", editor->get_edited_scene());
- editor_data->get_undo_redo().add_do_reference(child);
- editor_data->get_undo_redo().add_undo_method(parent, "remove_child", child);
+ if (parent) {
+ editor_data->get_undo_redo().add_do_method(parent, "add_child", child);
+ editor_data->get_undo_redo().add_do_method(child, "set_owner", editor->get_edited_scene());
+ editor_data->get_undo_redo().add_do_reference(child);
+ editor_data->get_undo_redo().add_undo_method(parent, "remove_child", child);
+ } else { // if we haven't parent, lets try to make a child as a parent.
+ editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", child);
+ editor_data->get_undo_redo().add_do_method(child, "set_owner", editor->get_edited_scene());
+ editor_data->get_undo_redo().add_do_reference(child);
+ editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", (Object *)NULL);
+ }
- String new_name = parent->validate_child_name(child);
- ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
- editor_data->get_undo_redo().add_do_method(sed, "live_debug_create_node", editor->get_edited_scene()->get_path_to(parent), child->get_class(), new_name);
- editor_data->get_undo_redo().add_undo_method(sed, "live_debug_remove_node", NodePath(String(editor->get_edited_scene()->get_path_to(parent)) + "/" + new_name));
+ if (parent) {
+ String new_name = parent->validate_child_name(child);
+ ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
+ editor_data->get_undo_redo().add_do_method(sed, "live_debug_create_node", editor->get_edited_scene()->get_path_to(parent), child->get_class(), new_name);
+ editor_data->get_undo_redo().add_undo_method(sed, "live_debug_remove_node", NodePath(String(editor->get_edited_scene()->get_path_to(parent)) + "/" + new_name));
+ }
// handle with different property for texture
String property = "texture";
@@ -4527,8 +4539,8 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String &
}
// locate at preview position
- Point2 pos;
- if (parent->has_method("get_global_position")) {
+ Point2 pos = Point2(0, 0);
+ if (parent && parent->has_method("get_global_position")) {
pos = parent->call("get_global_position");
}
Transform2D trans = canvas->get_canvas_transform();
@@ -4689,6 +4701,18 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian
return false;
}
+void CanvasItemEditorViewport::_show_resource_type_selector() {
+ List<BaseButton *> btn_list;
+ button_group->get_buttons(&btn_list);
+
+ for (int i = 0; i < btn_list.size(); i++) {
+ CheckBox *check = Object::cast_to<CheckBox>(btn_list[i]);
+ check->set_pressed(check->get_text() == default_type);
+ }
+ selector->set_title(vformat(TTR("Add %s"), default_type));
+ selector->popup_centered_minsize();
+}
+
void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p_data) {
bool is_shift = Input::get_singleton()->is_key_pressed(KEY_SHIFT);
bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT);
@@ -4705,10 +4729,9 @@ void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p
if (root_node) {
list.push_back(root_node);
} else {
- accept->get_ok()->set_text(TTR("OK :("));
- accept->set_text(TTR("No parent to instance a child at."));
- accept->popup_centered_minsize();
- _remove_preview();
+ drop_pos = p_point;
+ target_node = NULL;
+ _show_resource_type_selector();
return;
}
}
@@ -4727,15 +4750,7 @@ void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p
drop_pos = p_point;
if (is_alt) {
- List<BaseButton *> btn_list;
- button_group->get_buttons(&btn_list);
-
- for (int i = 0; i < btn_list.size(); i++) {
- CheckBox *check = Object::cast_to<CheckBox>(btn_list[i]);
- check->set_pressed(check->get_text() == default_type);
- }
- selector->set_title(vformat(TTR("Add %s"), default_type));
- selector->popup_centered_minsize();
+ _show_resource_type_selector();
} else {
_perform_drop_data();
}
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index 457833e1a7..4be09a16e9 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -578,6 +578,7 @@ class CanvasItemEditorViewport : public Control {
void _create_nodes(Node *parent, Node *child, String &path, const Point2 &p_point);
bool _create_instance(Node *parent, String &path, const Point2 &p_point);
void _perform_drop_data();
+ void _show_resource_type_selector();
static void _bind_methods();
diff --git a/editor/plugins/mesh_instance_editor_plugin.cpp b/editor/plugins/mesh_instance_editor_plugin.cpp
index 84fc0cecf2..9d116349c0 100644
--- a/editor/plugins/mesh_instance_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_editor_plugin.cpp
@@ -195,7 +195,139 @@ void MeshInstanceEditor::_menu_option(int p_option) {
outline_dialog->popup_centered(Vector2(200, 90));
} break;
+ case MENU_OPTION_CREATE_UV2: {
+
+ Ref<ArrayMesh> mesh = node->get_mesh();
+ if (!mesh.is_valid()) {
+ err_dialog->set_text(TTR("Contained Mesh is not of type ArrayMesh."));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+
+ Error err = mesh->lightmap_unwrap(node->get_global_transform());
+ if (err != OK) {
+ err_dialog->set_text(TTR("UV Unwrap failed, mesh may not be manifold?"));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+
+ } break;
+ case MENU_OPTION_DEBUG_UV1: {
+ Ref<Mesh> mesh = node->get_mesh();
+ if (!mesh.is_valid()) {
+ err_dialog->set_text(TTR("No mesh to debug."));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+ _create_uv_lines(0);
+ } break;
+ case MENU_OPTION_DEBUG_UV2: {
+ Ref<Mesh> mesh = node->get_mesh();
+ if (!mesh.is_valid()) {
+ err_dialog->set_text(TTR("No mesh to debug."));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+ _create_uv_lines(1);
+ } break;
+ }
+}
+
+struct MeshInstanceEditorEdgeSort {
+
+ Vector2 a;
+ Vector2 b;
+
+ bool operator<(const MeshInstanceEditorEdgeSort &p_b) const {
+ if (a == p_b.a)
+ return b < p_b.b;
+ else
+ return a < p_b.a;
+ }
+
+ MeshInstanceEditorEdgeSort() {}
+ MeshInstanceEditorEdgeSort(const Vector2 &p_a, const Vector2 &p_b) {
+ if (p_a < p_b) {
+ a = p_a;
+ b = p_b;
+ } else {
+ b = p_a;
+ a = p_b;
+ }
+ }
+};
+
+void MeshInstanceEditor::_create_uv_lines(int p_layer) {
+
+ Ref<Mesh> mesh = node->get_mesh();
+ ERR_FAIL_COND(!mesh.is_valid());
+
+ Set<MeshInstanceEditorEdgeSort> edges;
+ uv_lines.clear();
+ for (int i = 0; i < mesh->get_surface_count(); i++) {
+ if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES)
+ continue;
+ Array a = mesh->surface_get_arrays(i);
+
+ PoolVector<Vector2> uv = a[p_layer == 0 ? Mesh::ARRAY_TEX_UV : Mesh::ARRAY_TEX_UV2];
+ if (uv.size() == 0) {
+ err_dialog->set_text(TTR("Model has no UV in this layer"));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+
+ PoolVector<Vector2>::Read r = uv.read();
+
+ PoolVector<int> indices = a[Mesh::ARRAY_INDEX];
+ PoolVector<int>::Read ri;
+
+ int ic;
+ bool use_indices;
+
+ if (indices.size()) {
+ ic = indices.size();
+ ri = indices.read();
+ use_indices = true;
+ } else {
+ ic = uv.size();
+ use_indices = false;
+ }
+
+ for (int j = 0; j < ic; j += 3) {
+
+ for (int k = 0; k < 3; k++) {
+
+ MeshInstanceEditorEdgeSort edge;
+ if (use_indices) {
+ edge.a = r[ri[j + k]];
+ edge.b = r[ri[j + ((k + 1) % 3)]];
+ } else {
+ edge.a = r[j + k];
+ edge.b = r[j + ((k + 1) % 3)];
+ }
+
+ if (edges.has(edge))
+ continue;
+
+ uv_lines.push_back(edge.a);
+ uv_lines.push_back(edge.b);
+ edges.insert(edge);
+ }
+ }
}
+
+ debug_uv_dialog->popup_centered_minsize();
+}
+
+void MeshInstanceEditor::_debug_uv_draw() {
+
+ if (uv_lines.size() == 0)
+ return;
+
+ debug_uv->set_clip_contents(true);
+ debug_uv->draw_rect(Rect2(Vector2(), debug_uv->get_size()), Color(0.2, 0.2, 0.0));
+ debug_uv->draw_set_transform(Vector2(), 0, debug_uv->get_size());
+ debug_uv->draw_multiline(uv_lines, Color(1.0, 0.8, 0.7));
}
void MeshInstanceEditor::_create_outline_mesh() {
@@ -244,6 +376,7 @@ void MeshInstanceEditor::_bind_methods() {
ClassDB::bind_method("_menu_option", &MeshInstanceEditor::_menu_option);
ClassDB::bind_method("_create_outline_mesh", &MeshInstanceEditor::_create_outline_mesh);
+ ClassDB::bind_method("_debug_uv_draw", &MeshInstanceEditor::_debug_uv_draw);
}
MeshInstanceEditor::MeshInstanceEditor() {
@@ -263,6 +396,10 @@ MeshInstanceEditor::MeshInstanceEditor() {
options->get_popup()->add_item(TTR("Create Navigation Mesh"), MENU_OPTION_CREATE_NAVMESH);
options->get_popup()->add_separator();
options->get_popup()->add_item(TTR("Create Outline Mesh.."), MENU_OPTION_CREATE_OUTLINE_MESH);
+ options->get_popup()->add_separator();
+ options->get_popup()->add_item(TTR("View UV1"), MENU_OPTION_DEBUG_UV1);
+ options->get_popup()->add_item(TTR("View UV2"), MENU_OPTION_DEBUG_UV2);
+ options->get_popup()->add_item(TTR("Unwrap UV2 for Lightmap/AO"), MENU_OPTION_CREATE_UV2);
options->get_popup()->connect("id_pressed", this, "_menu_option");
@@ -286,6 +423,14 @@ MeshInstanceEditor::MeshInstanceEditor() {
err_dialog = memnew(AcceptDialog);
add_child(err_dialog);
+
+ debug_uv_dialog = memnew(AcceptDialog);
+ debug_uv_dialog->set_title("UV Channel Debug");
+ add_child(debug_uv_dialog);
+ debug_uv = memnew(Control);
+ debug_uv->set_custom_minimum_size(Size2(600, 600) * EDSCALE);
+ debug_uv->connect("draw", this, "_debug_uv_draw");
+ debug_uv_dialog->add_child(debug_uv);
}
void MeshInstanceEditorPlugin::edit(Object *p_object) {
diff --git a/editor/plugins/mesh_instance_editor_plugin.h b/editor/plugins/mesh_instance_editor_plugin.h
index fa851458ce..68c149f98a 100644
--- a/editor/plugins/mesh_instance_editor_plugin.h
+++ b/editor/plugins/mesh_instance_editor_plugin.h
@@ -47,6 +47,9 @@ class MeshInstanceEditor : public Node {
MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE,
MENU_OPTION_CREATE_NAVMESH,
MENU_OPTION_CREATE_OUTLINE_MESH,
+ MENU_OPTION_CREATE_UV2,
+ MENU_OPTION_DEBUG_UV1,
+ MENU_OPTION_DEBUG_UV2,
};
MeshInstance *node;
@@ -58,11 +61,18 @@ class MeshInstanceEditor : public Node {
AcceptDialog *err_dialog;
+ AcceptDialog *debug_uv_dialog;
+ Control *debug_uv;
+ Vector<Vector2> uv_lines;
+
void _menu_option(int p_option);
void _create_outline_mesh();
+ void _create_uv_lines(int p_layer);
friend class MeshInstanceEditorPlugin;
+ void _debug_uv_draw();
+
protected:
void _node_removed(Node *p_node);
static void _bind_methods();
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 6a869aaadb..95f2739927 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -1015,14 +1015,9 @@ void ScriptTextEditor::_edit_option(int p_op) {
tx->end_complex_operation();
tx->update();
} break;
- case EDIT_FOLD_LINE: {
+ case EDIT_TOGGLE_FOLD_LINE: {
- tx->fold_line(tx->cursor_get_line());
- tx->update();
- } break;
- case EDIT_UNFOLD_LINE: {
-
- tx->unfold_line(tx->cursor_get_line());
+ tx->toggle_fold_line(tx->cursor_get_line());
tx->update();
} break;
case EDIT_FOLD_ALL_LINES: {
@@ -1517,13 +1512,9 @@ void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p
context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_right"), EDIT_INDENT_RIGHT);
context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT);
}
- if (p_can_fold) {
- // can fold
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/fold_line"), EDIT_FOLD_LINE);
- } else if (p_is_folded) {
- // can unfold
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/unfold_line"), EDIT_UNFOLD_LINE);
- }
+ if (p_can_fold || p_is_folded)
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_fold_line"), EDIT_TOGGLE_FOLD_LINE);
+
if (p_color) {
context_menu->add_separator();
context_menu->add_item(TTR("Pick Color"), EDIT_PICK_COLOR);
@@ -1587,9 +1578,8 @@ ScriptTextEditor::ScriptTextEditor() {
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/delete_line"), EDIT_DELETE_LINE);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/clone_down"), EDIT_CLONE_DOWN);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/fold_line"), EDIT_FOLD_LINE);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_fold_line"), EDIT_TOGGLE_FOLD_LINE);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/fold_all_lines"), EDIT_FOLD_ALL_LINES);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/unfold_line"), EDIT_UNFOLD_LINE);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/unfold_all_lines"), EDIT_UNFOLD_ALL_LINES);
edit_menu->get_popup()->add_separator();
#ifdef OSX_ENABLED
@@ -1668,8 +1658,7 @@ void ScriptTextEditor::register_editor() {
ED_SHORTCUT("script_text_editor/indent_right", TTR("Indent Right"), 0);
ED_SHORTCUT("script_text_editor/toggle_comment", TTR("Toggle Comment"), KEY_MASK_CMD | KEY_K);
ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_CMD | KEY_B);
- ED_SHORTCUT("script_text_editor/fold_line", TTR("Fold Line"), KEY_MASK_ALT | KEY_LEFT);
- ED_SHORTCUT("script_text_editor/unfold_line", TTR("Unfold Line"), KEY_MASK_ALT | KEY_RIGHT);
+ ED_SHORTCUT("script_text_editor/toggle_fold_line", TTR("Fold/Unfold Line"), KEY_MASK_ALT | KEY_F);
ED_SHORTCUT("script_text_editor/fold_all_lines", TTR("Fold All Lines"), 0);
ED_SHORTCUT("script_text_editor/unfold_all_lines", TTR("Unfold All Lines"), 0);
#ifdef OSX_ENABLED
diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h
index 722015ef3e..e3b81e7c3f 100644
--- a/editor/plugins/script_text_editor.h
+++ b/editor/plugins/script_text_editor.h
@@ -91,8 +91,7 @@ class ScriptTextEditor : public ScriptEditorBase {
EDIT_TO_UPPERCASE,
EDIT_TO_LOWERCASE,
EDIT_CAPITALIZE,
- EDIT_FOLD_LINE,
- EDIT_UNFOLD_LINE,
+ EDIT_TOGGLE_FOLD_LINE,
EDIT_FOLD_ALL_LINES,
EDIT_UNFOLD_ALL_LINES,
SEARCH_FIND,
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index b855d2d4c4..80638c6f1e 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -2624,7 +2624,6 @@ void SpatialEditorViewport::_menu_option(int p_option) {
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_WIREFRAME), false);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_OVERDRAW), false);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_SHADELESS), false);
-
} break;
case VIEW_DISPLAY_WIREFRAME: {
@@ -3756,6 +3755,10 @@ void SpatialEditor::select_gizmo_highlight_axis(int p_axis) {
}
}
+int SpatialEditor::get_skeleton_visibility_state() const {
+ return view_menu->get_popup()->get_item_state(view_menu->get_popup()->get_item_index(MENU_VISIBILITY_SKELETON));
+}
+
void SpatialEditor::update_transform_gizmo() {
List<Node *> &selection = editor_selection->get_selected_node_list();
@@ -3800,6 +3803,21 @@ void SpatialEditor::update_transform_gizmo() {
}
}
+void _update_all_gizmos(Node *p_node) {
+ for (int i = p_node->get_child_count() - 1; 0 <= i; --i) {
+ Spatial *spatial_node = Object::cast_to<Spatial>(p_node->get_child(i));
+ if (spatial_node) {
+ spatial_node->update_gizmo();
+ }
+
+ _update_all_gizmos(p_node->get_child(i));
+ }
+}
+
+void SpatialEditor::update_all_gizmos() {
+ _update_all_gizmos(SceneTree::get_singleton()->get_root());
+}
+
Object *SpatialEditor::_get_editor_data(Object *p_what) {
Spatial *sp = Object::cast_to<Spatial>(p_what);
@@ -4247,6 +4265,28 @@ void SpatialEditor::_menu_item_pressed(int p_option) {
_refresh_menu_icons();
} break;
+ case MENU_VISIBILITY_SKELETON: {
+
+ const int idx = view_menu->get_popup()->get_item_index(MENU_VISIBILITY_SKELETON);
+ view_menu->get_popup()->toggle_item_statable(idx);
+
+ // Change icon
+ const int state = view_menu->get_popup()->get_item_state(idx);
+ switch (state) {
+ case 0:
+ view_menu->get_popup()->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_hidden"));
+ break;
+ case 1:
+ view_menu->get_popup()->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_visible"));
+ break;
+ case 2:
+ view_menu->get_popup()->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_xray"));
+ break;
+ }
+
+ update_all_gizmos();
+
+ } break;
}
}
@@ -4699,6 +4739,7 @@ void SpatialEditor::_notification(int p_what) {
view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), get_icon("Panels3", "EditorIcons"));
view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_icon("Panels3Alt", "EditorIcons"));
view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_icon("Panels4", "EditorIcons"));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VISIBILITY_SKELETON), view_menu->get_popup()->get_icon("visibility_visible"));
_menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
@@ -5035,6 +5076,10 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
p->add_separator();
p->add_shortcut(ED_SHORTCUT("spatial_editor/settings", TTR("Settings")), MENU_VIEW_CAMERA_SETTINGS);
+ p->add_separator();
+ p->add_statable_item(TTR("Skeleton Gizmo visibility"), 3, 1, MENU_VISIBILITY_SKELETON);
+ p->add_separator();
+
p->set_item_checked(p->get_item_index(MENU_VIEW_ORIGIN), true);
p->set_item_checked(p->get_item_index(MENU_VIEW_GRID), true);
diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h
index 0c2571017b..8369a5de54 100644
--- a/editor/plugins/spatial_editor_plugin.h
+++ b/editor/plugins/spatial_editor_plugin.h
@@ -92,7 +92,7 @@ class SpatialEditorViewport : public Control {
VIEW_DISPLAY_NORMAL,
VIEW_DISPLAY_WIREFRAME,
VIEW_DISPLAY_OVERDRAW,
- VIEW_DISPLAY_SHADELESS,
+ VIEW_DISPLAY_SHADELESS
};
public:
@@ -488,7 +488,8 @@ private:
MENU_VIEW_GRID,
MENU_VIEW_CAMERA_SETTINGS,
MENU_LOCK_SELECTED,
- MENU_UNLOCK_SELECTED
+ MENU_UNLOCK_SELECTED,
+ MENU_VISIBILITY_SKELETON
};
Button *tool_button[TOOL_MAX];
@@ -591,7 +592,10 @@ public:
Ref<ArrayMesh> get_scale_gizmo(int idx) const { return scale_gizmo[idx]; }
Ref<ArrayMesh> get_scale_plane_gizmo(int idx) const { return scale_plane_gizmo[idx]; }
+ int get_skeleton_visibility_state() const;
+
void update_transform_gizmo();
+ void update_all_gizmos();
void select_gizmo_highlight_axis(int p_axis);
void set_custom_camera(Node *p_camera) { custom_camera = p_camera; }
diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index eb2faa1ab1..b8c57fd959 100644
--- a/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
@@ -343,7 +343,7 @@ AutotileEditor::AutotileEditor(EditorNode *p_editor) {
split->add_child(property_editor);
helper = memnew(AutotileEditorHelper(this));
- property_editor->edit(helper);
+ property_editor->call_deferred("edit", helper);
// Editor
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index eed1efaf9c..b187a9ae9d 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -70,7 +70,7 @@ void EditorResourceConversionPlugin::_bind_methods() {
mi.name = "_handles";
mi.return_val = PropertyInfo(Variant::BOOL, "");
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "_converts_to"));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_converts_to"));
}
String EditorResourceConversionPlugin::converts_to() const {
@@ -430,24 +430,19 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
} else if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || hint == PROPERTY_HINT_LAYERS_2D_RENDER || hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || hint == PROPERTY_HINT_LAYERS_3D_RENDER) {
- String title;
String basename;
switch (hint) {
case PROPERTY_HINT_LAYERS_2D_RENDER:
basename = "layer_names/2d_render";
- title = "2D Render Layers";
break;
case PROPERTY_HINT_LAYERS_2D_PHYSICS:
basename = "layer_names/2d_physics";
- title = "2D Physics Layers";
break;
case PROPERTY_HINT_LAYERS_3D_RENDER:
basename = "layer_names/3d_render";
- title = "3D Render Layers";
break;
case PROPERTY_HINT_LAYERS_3D_PHYSICS:
basename = "layer_names/3d_physics";
- title = "3D Physics Layers";
break;
}
@@ -469,11 +464,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
show();
- value_label[0]->set_text(title);
- value_label[0]->show();
- value_label[0]->set_position(Vector2(4, 4) * EDSCALE);
-
- checks20gc->set_position(Vector2(4, 4) * EDSCALE + Vector2(0, value_label[0]->get_size().height + 4 * EDSCALE));
+ checks20gc->set_position(Vector2(4, 4) * EDSCALE);
checks20gc->set_size(checks20gc->get_minimum_size());
set_size(Vector2(4, 4) * EDSCALE + checks20gc->get_position() + checks20gc->get_size());
@@ -656,7 +647,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
}
}
- if (type)
+ if (type != Variant::NIL)
property_select->select_property_from_basic_type(type, v);
updating = false;
@@ -1948,6 +1939,7 @@ CustomPropertyEditor::CustomPropertyEditor() {
type_button->get_popup()->connect("id_pressed", this, "_type_create_selected");
menu = memnew(PopupMenu);
+ menu->set_pass_on_modal_close_click(false);
add_child(menu);
menu->connect("id_pressed", this, "_menu_option");
@@ -2811,13 +2803,12 @@ void PropertyEditor::update_tree() {
TreeItem *sep = tree->create_item(root);
current_category = sep;
String type = p.name;
- //*
+
if (has_icon(type, "EditorIcons"))
sep->set_icon(0, get_icon(type, "EditorIcons"));
else
sep->set_icon(0, get_icon("Object", "EditorIcons"));
- //*/
sep->set_text(0, type);
sep->set_expand_right(0, true);
sep->set_selectable(0, false);
@@ -2943,38 +2934,36 @@ void PropertyEditor::update_tree() {
}
if (use_doc_hints) {
- StringName setter;
- StringName type;
- if (ClassDB::get_setter_and_type_for_property(obj->get_class_name(), p.name, type, setter)) {
- String descr;
- bool found = false;
- Map<StringName, Map<StringName, String> >::Element *E = descr_cache.find(type);
- if (E) {
+ StringName classname = obj->get_class_name();
+ StringName propname = p.name;
+ String descr;
+ bool found = false;
- Map<StringName, String>::Element *F = E->get().find(setter);
- if (F) {
- found = true;
- descr = F->get();
- }
+ Map<StringName, Map<StringName, String> >::Element *E = descr_cache.find(classname);
+ if (E) {
+ Map<StringName, String>::Element *F = E->get().find(propname);
+ if (F) {
+ found = true;
+ descr = F->get();
}
- if (!found) {
+ }
- DocData *dd = EditorHelp::get_doc_data();
- Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(type);
- if (E) {
- for (int i = 0; i < E->get().methods.size(); i++) {
- if (E->get().methods[i].name == setter.operator String()) {
- descr = E->get().methods[i].description.strip_edges().word_wrap(80);
- }
+ if (!found) {
+ DocData *dd = EditorHelp::get_doc_data();
+ Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(classname);
+ if (E) {
+ for (int i = 0; i < E->get().properties.size(); i++) {
+ if (E->get().properties[i].name == propname.operator String()) {
+ descr = E->get().properties[i].description.strip_edges().word_wrap(80);
}
}
-
- descr_cache[type][setter] = descr;
}
- item->set_tooltip(0, TTR("Property:") + " " + p.name + "\n\n" + descr);
+ descr_cache[classname][propname] = descr;
}
+
+ item->set_tooltip(0, TTR("Property:") + " " + p.name + "\n\n" + descr);
}
Dictionary d;
@@ -4288,6 +4277,7 @@ PropertyEditor::PropertyEditor() {
set_physics_process(true);
custom_editor = memnew(CustomPropertyEditor);
+ custom_editor->set_pass_on_modal_close_click(false);
add_child(custom_editor);
tree->connect("custom_popup_edited", this, "_custom_editor_request");
@@ -4374,7 +4364,7 @@ class SectionedPropertyEditorFilter : public Object {
PropertyInfo pi = E->get();
int sp = pi.name.find("/");
- if (pi.name == "resource_path" || pi.name == "resource_name" || pi.name.begins_with("script/")) //skip resource stuff
+ if (pi.name == "resource_path" || pi.name == "resource_name" || pi.name == "resource_local_to_scene" || pi.name.begins_with("script/")) //skip resource stuff
continue;
if (sp == -1) {
@@ -4524,7 +4514,7 @@ void SectionedPropertyEditor::update_category_list() {
else if (!(pi.usage & PROPERTY_USAGE_EDITOR))
continue;
- if (pi.name.find(":") != -1 || pi.name == "script" || pi.name == "resource_name" || pi.name == "resource_path")
+ if (pi.name.find(":") != -1 || pi.name == "script" || pi.name == "resource_name" || pi.name == "resource_path" || pi.name == "resource_local_to_scene")
continue;
if (search_box && search_box->get_text() != String() && pi.name.findn(search_box->get_text()) == -1)
diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp
index 86de7c56e1..77b73e4635 100644
--- a/editor/property_selector.cpp
+++ b/editor/property_selector.cpp
@@ -363,23 +363,6 @@ void PropertySelector::_item_selected() {
at_class = ClassDB::get_parent_class(at_class);
}
-
- if (text == String()) {
-
- StringName setter;
- StringName type;
- if (ClassDB::get_setter_and_type_for_property(class_type, name, type, setter)) {
- Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(type);
- if (E) {
- for (int i = 0; i < E->get().methods.size(); i++) {
- if (E->get().methods[i].name == setter.operator String()) {
- text = E->get().methods[i].description;
- }
- }
- }
- }
- }
-
} else {
String at_class = class_type;
@@ -516,6 +499,7 @@ void PropertySelector::select_property_from_script(const Ref<Script> &p_script,
search_box->grab_focus();
_update_search();
}
+
void PropertySelector::select_property_from_basic_type(Variant::Type p_type, const String &p_current) {
ERR_FAIL_COND(p_type == Variant::NIL);
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index 2c0981ca30..25924212fd 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -484,7 +484,8 @@ void SceneTreeEditor::_selected_changed() {
void SceneTreeEditor::_deselect_items() {
// Clear currently elected items in scene tree dock.
- editor_selection->clear();
+ if (editor_selection)
+ editor_selection->clear();
}
void SceneTreeEditor::_cell_multi_selected(Object *p_object, int p_cell, bool p_selected) {
diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp
index c44e78a621..f785b3e198 100644
--- a/editor/spatial_editor_gizmos.cpp
+++ b/editor/spatial_editor_gizmos.cpp
@@ -1316,6 +1316,34 @@ void SkeletonSpatialGizmo::redraw() {
Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/skeleton");
Ref<Material> material = create_material("skeleton_material", gizmo_color);
+ SpatialMaterial *sm = Object::cast_to<SpatialMaterial>(material.ptr());
+
+ { // Reset
+ Color c(sm->get_albedo());
+ c.a = 1;
+ sm->set_albedo(c);
+ }
+ if (sm) {
+ switch (SpatialEditor::get_singleton()->get_skeleton_visibility_state()) {
+ case 0: {
+ // Hidden
+ Color c(sm->get_albedo());
+ c.a = 0;
+ sm->set_albedo(c);
+ sm->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
+ } break;
+ case 1:
+ // Visible
+ sm->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, false);
+ sm->set_render_priority(SpatialMaterial::RENDER_PRIORITY_MIN);
+ sm->set_flag(SpatialMaterial::FLAG_DISABLE_DEPTH_TEST, false);
+ break;
+ case 2:
+ // x-ray
+ sm->set_on_top_of_alpha();
+ break;
+ }
+ }
Ref<SurfaceTool> surface_tool(memnew(SurfaceTool));
diff --git a/main/input_default.cpp b/main/input_default.cpp
index 7cc7521686..8c91a1a5de 100644
--- a/main/input_default.cpp
+++ b/main/input_default.cpp
@@ -540,20 +540,62 @@ static const char *s_ControllerMappings[] = {
"00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
"00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
"02200090000000000000504944564944,8Bitdo NES30 PRO USB,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+ "03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,",
+ "0d0f1100000000000000504944564944,REAL ARCADE PRO.3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,",
+ "0d0f2200000000000000504944564944,REAL ARCADE Pro.V3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "0d0f2700000000000000504944564944,FIGHTING STICK V3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,",
+ "0d0f4000000000000000504944564944,Hori Fighting Stick Mini 3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b5,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b4,righttrigger:b6,",
"0d0f4900000000000000504944564944,Hatsune Miku Sho Controller,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "0d0f4d00000000000000504944564944,HORIPAD3 A,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "0d0f5e00000000000000504944564944,Fighting Commander 4,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b5,rightshoulder:b4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a4,righttrigger:a3,",
+ "0d0f5f00000000000000504944564944,Fighting Commander 4,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "0d0f6a00000000000000504944564944,Real Arcade Pro.4,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,",
+ "0d0f6b00000000000000504944564944,Real Arcade Pro.4,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
"0d0f6e00000000000000504944564944,HORIPAD 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "0d0f7000000000000000504944564944,REAL ARCADE PRO.4 VLX,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,",
+ "0d0f8400000000000000504944564944,Fighting Commander 5,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,",
+ "0d0f8500000000000000504944564944,Fighting Commander 2016 PS3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "0d0f8700000000000000504944564944,Fighting Stick mini 4,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,",
+ "0d0f8800000000000000504944564944,Fighting Stick mini 4,a:b1,b:b2,x:b0,y:b3,back:b9,guide:b12,start:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,",
+ "0d0f8a00000000000000504944564944,Real Arcade Pro.4,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,",
+ "0d0f8b00000000000000504944564944,Real Arcade Pro.4,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "10008200000000000000504944564944,PS360+ v1.66,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:h0.4,lefttrigger:b6,righttrigger:b7,",
"10080100000000000000504944564944,PS1 USB,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,",
"100801e5000000000000504944564944,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,",
"10080300000000000000504944564944,PS2 USB,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5,",
"10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,y:b3,x:b4,start:b11,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,",
+ "120cf60e000000000000504944564944,P4 Wired Gamepad,a:b1,b:b2,x:b0,y:b3,back:b12,guide:b8,start:b9,leftshoulder:b5,rightshoulder:b4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:h0.0,lefttrigger:b7,righttrigger:b6,",
"20380900000000000000504944564944,8Bitdo NES30 PRO Wireless,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+ "222c0020000000000000504944564944,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:a3,righttrigger:a4,",
+ "222c0023000000000000504944564944,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,x:b0,y:b3,back:b13,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,",
+ "222c0223000000000000504944564944,Qanba Obsidian Arcade Joystick PS3 Mode,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "25090017000000000000504944564944,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b5,rightshoulder:b7,leftx:a0,lefty:a1,lefttrigger:b4,righttrigger:b6,",
+ "25090128000000000000504944564944,Mayflash Arcade Stick,a:b1,b:b2,x:b5,y:b6,back:b8,start:b9,leftshoulder:b0,rightshoulder:b3,leftx:a0,lefty:a1,rightx:h0.4,righty:h0.0,lefttrigger:b4,righttrigger:b7,",
"25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,",
"2509e803000000000000504944564944,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
"28040140000000000000504944564944,GamePad Pro USB,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,",
+ "300f0011000000000000504944564944,QanBa Arcade JoyStick 1008,x:b0,a:b1,b:b2,y:b3,back:b8,start:b10,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,",
"300f1001000000000000504944564944,Saitek P480 Rumble Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,",
+ "300f1201000000000000504944564944,Saitek Dual Analog Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,",
+ "300f1210000000000000504944564944,QanBa Joystick Plus,a:b0,b:b1,x:b2,y:b3,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,",
+ "300f1611000000000000504944564944,QanBa Arcade JoyStick 4018,a:b1,b:b2,x:b0,y:b3,back:b10,guide:b9,start:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,",
+ "341a0104000000000000504944564944,QanBa Joystick Q4RAF,a:b5,b:b6,x:b1,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b0,rightshoulder:b3,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,lefttrigger:b4,righttrigger:b7,",
"341a0108000000000000504944564944,EXEQ RF USB Gamepad 8206,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,leftstick:b8,rightstick:b7,back:b8,start:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
"341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"36280100000000000000504944564944,OUYA Controller,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13,",
+ "38071888000000000000504944564944,MadCatz SFIV FightStick PS3,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b5,rightshoulder:b4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b7,righttrigger:b6,",
+ "38073888000000000000504944564944,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "38075032000000000000504944564944,Mad Catz FightPad PRO PS3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "38075082000000000000504944564944,Mad Catz FightPad PRO PS4,x:b0,a:b1,b:b2,y:b3,back:b13,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,",
+ "38076652000000000000504944564944,UnKnown,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
+ "38078034000000000000504944564944,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "38078084000000000000504944564944,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,",
+ "38078134000000000000504944564944,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b7,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b4,",
+ "38078184000000000000504944564944,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b5,rightshoulder:b4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a4,righttrigger:b7,",
+ "38078433000000000000504944564944,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,",
+ "38078483000000000000504944564944,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:b6,",
+ "38078532000000000000504944564944,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "45130010000000000000504944564944,Generic USB Joystick,a:b0,b:b1,x:b2,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
"49190204000000000000504944564944,Ipega PG-9023,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,",
"4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftstick:a0,rightstick:a2,leftshoulder:a3,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:h0.6,lefty:h0.12,rightx:h0.9,righty:h0.4,lefttrigger:b6,righttrigger:b7,",
"4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
@@ -563,28 +605,37 @@ static const char *s_ControllerMappings[] = {
"4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,",
"4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
"4f0423b3000000000000504944564944,Dual Trigger 3-in-1,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,",
+ "5e048e02000000000000504944564944,Controller (XBOX 360 For Windows),x:b2,a:b0,b:b1,y:b3,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,righttrigger:a2,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
"63252305000000000000504944564944,USB Vibration Joystick (BM),x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "66660488000000000000504944564944,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:b12,dpdown:b14,dpleft:b15,dpright:b13,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,",
"6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
"6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"6f0e1e01000000000000504944564944,Rock Candy Gamepad for PS3,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,",
+ "6f0e2401000000000000504944564944,INJUSTICE FightStick for PS3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2",
"79000018000000000000504944564944,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
"79000600000000000000504944564944,G-Shark GS-GP702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,",
- "79000600000000000000504944564944,NGS Phantom,a:b2,b:b3,y:b1,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,",
+ "79001100000000000000504944564944,Sega Saturn Gamepad,a:b1,b:b2,x:b4,y:b5,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a4,lefttrigger:b3,righttrigger:b0,",
+ "79001b18000000000000504944564944,Venom Arcade Joystick,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,",
"79004318000000000000504944564944,Mayflash GameCube Controller Adapter,a:b1,b:b2,x:b0,y:b3,back:b0,start:b9,guide:b0,leftshoulder:b4,rightshoulder:b7,leftstick:b0,rightstick:b0,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,",
- "79000600000000000000504944564944,Generic Speedlink,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,",
"83056020000000000000504944564944,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,",
"88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,",
"8f0e0300000000000000504944564944,Piranha xtreme,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
"8f0e0d31000000000000504944564944,Multilaser JS071 USB,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "8f0e1030000000000000504944564944,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,x:b3,y:b4,start:b9,leftshoulder:b6,rightshoulder:b2,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b5,righttrigger:b7,",
"8f0e1200000000000000504944564944,Acme,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
"9000318000000000000504944564944,Mayflash Wiimote PC Adapter,a:b2,b:h0.4,x:b0,y:b1,back:b4,start:b5,guide:b11,leftshoulder:b6,rightshoulder:b3,leftx:a0,lefty:a1,",
+ "9b280500000000000000504944564944,Saturn_Adapter_2.0,a:b1,b:b2,x:b0,y:b3,start:b9,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,lefttrigger:b4,righttrigger:b5,",
"a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,y:b1,x:b0,start:b4,guide:b10,back:b5,leftstick:b8,rightstick:b9,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "bd1215d0000000000000504944564944,Nintendo Retrolink USB Super SNES Classic Controller,y:b0,b:b1,a:b2,x:b3,leftshoulder:b4,rightshoulder:b5,start:b9,back:b8,leftx:a0,lefty:a1,",
"c0111352000000000000504944564944,Battalife Joystick,x:b4,a:b6,b:b7,y:b5,back:b2,start:b3,leftshoulder:b0,rightshoulder:b1,leftx:a0,lefty:a1,",
"c911f055000000000000504944564944,GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "d8140862000000000000504944564944,HitBox Edition Cthulhu+,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b5,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b4,righttrigger:b6,",
+ "d81d0b00000000000000504944564944,BUFFALO BSGP1601 Series ,x:b4,a:b5,b:b3,y:b2,back:b12,start:b13,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b6,rightshoulder:b9,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "d81d0f00000000000000504944564944,iBUFFALO BSGP1204 Series,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "d81d1000000000000000504944564944,iBUFFALO BSGP1204P Series,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
"ff113133000000000000504944564944,Gembird JPD-DualForce,a:b2,b:b3,x:b0,y:b1,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,leftstick:b10,rightstick:b11,",
- "ff113133000000000000504944564944,SVEN X-PAD,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9,",
"ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"__XINPUT_DEVICE__,XInput Gamepad,a:b12,b:b13,x:b14,y:b15,start:b4,back:b5,leftstick:b6,rightstick:b7,leftshoulder:b8,rightshoulder:b9,dpup:b0,dpdown:b1,dpleft:b2,dpright:b3,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,",
#endif
@@ -595,10 +646,12 @@ static const char *s_ControllerMappings[] = {
"050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,x:b18,y:b17,back:b7,guide:b8,start:b6,leftstick:b23,rightstick:b24,leftshoulder:b19,rightshoulder:b20,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b21,righttrigger:b22,",
"0d0f0000000000004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
"0d0f0000000000006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:a4,",
+ "10080000000000000100000000000000,Twin USB Joystick,a:b4,b:b2,x:b6,y:b0,back:b16,start:b18,leftstick:b20,rightstick:b22,leftshoulder:b12,rightshoulder:b14,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a2,rightx:a6,righty:a4,lefttrigger:b8,righttrigger:b10,",
"10280000000000000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
"2509000000000000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
"351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
"4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
+ "4c05000000000000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,",
"4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"4c05000000000000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,",
"4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,",
@@ -607,9 +660,9 @@ static const char *s_ControllerMappings[] = {
"5e04000000000000dd02000000000000,Xbox One Wired Controller,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
"5e04000000000000e002000000000000,Xbox Wireless Controller,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b10,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
"5e04000000000000ea02000000000000,Xbox Wireless Controller,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
- "6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
+ "6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
- "6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* This includes F710 in DInput mode and the "Logitech Cordless RumblePad 2", at the very least. */
+ "6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
"79000000000000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,x:b0,y:b12,back:b32,start:b36,leftstick:b40,rightstick:b44,leftshoulder:b16,rightshoulder:b20,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a4,rightx:a8,righty:a12,lefttrigger:b24,righttrigger:b28,",
"79000000000000000600000000000000,G-Shark GP-702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b6,righttrigger:b7,",
@@ -618,6 +671,7 @@ static const char *s_ControllerMappings[] = {
"83050000000000006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,",
"891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
"8f0e0000000000000300000000000000,Piranha xtreme,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
+ "AD1B00000000000001F9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
"ad1b00000000000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
"b4040000000000000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,x:b3,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
"bd1200000000000015d0000000000000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,",
@@ -629,7 +683,7 @@ static const char *s_ControllerMappings[] = {
"0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
"0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
"030000000d0f00000d00000000010000,hori,a:b0,b:b6,y:b2,x:b1,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,start:b9,guide:b10,back:b8,leftshoulder:b3,rightshoulder:b7,leftx:b4,lefty:b5,",
- "030000000d0f00001000000011010000,HORI CO.,LTD. FIGHTING STICK 3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7",
+ "030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7",
"030000000d0f00002200000011010000,HORI CO.,LTD. REAL ARCADE Pro.V3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,",
"030000000d0f00004d00000011010000,HORI Gem Pad 3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
"03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,",
@@ -638,13 +692,16 @@ static const char *s_ControllerMappings[] = {
"03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,",
"03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,",
"03000000280400000140000000010000,Gravis GamePad Pro USB ,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,",
+ "03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,x:b0,a:b2,b:b3,y:b1,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
"03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,y:b3,x:b0,start:b9,guide:,back:,leftstick:,rightstick:,leftshoulder:,dpleft:b15,dpdown:b14,dpright:b13,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,rightshoulder:b7,dpup:b12,",
"03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
+ "03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,",
"030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
"030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,",
"030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,",
"030000004c050000c405000011810000,Sony Computer Entertainment Wireless Controller,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:h0.1,rightshoulder:b5,rightx:a3,start:b9,righty:a4,dpleft:h0.8,lefttrigger:a2,x:b3,dpup:h0.1,back:b8,leftstick:b11,leftshoulder:b4,y:b2,a:b0,dpright:h0.2,righttrigger:a5,b:b1,",
"030000004c050000cc09000011010000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,",
+ "030000004c050000cc09000011810000,Sony DualShock 4 (CUH-ZCT2U) (USB),a:b0,b:b1,y:b2,x:b3,leftshoulder:b4,rightshoulder:b5,back:b8,start:b9,guide:b10,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,lefttrigger:a2,rightx:a3,righty:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,",
"030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,",
"030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
@@ -684,14 +741,15 @@ static const char *s_ControllerMappings[] = {
"030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
"030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
"030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,guide:b8,leftstick:b9,rightstick:b10,lefttrigger:a2,righttrigger:a5,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
+ "03000000780000000600000010010000,Microntek USB Joystick,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftx:a0,lefty:a1,",
"03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
"03000000790000001100000010010000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,",
- "03000000790000001100000010010000,RetroLink Saturn Classic Controller,x:b3,a:b0,b:b1,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
"03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,",
"030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
"030000008916000001fd000024010000,Razer Onza Classic Edition,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
"030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
"030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
+ "030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,x:b1,a:b0,b:b4,y:b5,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
"03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,y:b1,x:b0,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b6,righttrigger:b7,",
"03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,",
"03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
@@ -701,7 +759,9 @@ static const char *s_ControllerMappings[] = {
"03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,lefttrigger:a2,righttrigger:a5,",
"03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,",
"03000000bd12000015d0000010010000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,",
- "03000000c9110000f055000011010000,HJC Game GAMEPAD,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b4,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,x:b13,y:b11,back:b4,start:b5,leftstick:b14,rightstick:b15,leftshoulder:b9,rightshoulder:b8,dpup:b0,dpdown:b2,dpleft:b3,dpright:b1,leftx:a1,lefty:a0,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,y:b0,x:b1,b:b3,a:b4,leftshoulder:b2,rightshoulder:b5,back:b6,start:b7,guide:b9,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftx:a0,lefty:a1,",
+ "03000000c9110000f055000011010000,HJC Game GAMEPAD,x:b2,a:b0,b:b1,y:b3,back:b4,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux,",
"03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,",
"03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,leftx:a0,lefty:a1,",
"03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
@@ -709,6 +769,7 @@ static const char *s_ControllerMappings[] = {
"03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,y:b1,x:b0,start:b7,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,",
"03000000fd0500002a26000000010000,3dfx InterAct HammerHead FX,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b5,rightshoulder:b7,rightx:a2,start:b11,righty:a3,dpleft:h0.8,lefttrigger:b8,x:b0,dpup:h0.1,back:b10,leftstick:b2,leftshoulder:b6,y:b1,a:b3,dpright:h0.2,righttrigger:b9,b:b4,",
"03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "03000000ff1100004133000010010000,GreenAsia Inc.USB Joystick,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
"05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,y:b3,x:b2,start:b9,guide:b10,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
"05000000102800000900000000010000,8Bitdo SFC30 GamePad,x:b4,a:b1,b:b0,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
"05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,",
@@ -719,11 +780,15 @@ static const char *s_ControllerMappings[] = {
"050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,",
"050000004c050000c405000000010000,PS4 Controller (Bluetooth),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"050000004c050000cc09000000010000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,",
+ "050000004c050000cc09000000810000,Sony DualShock 4 (CUH-ZCT2U) (Bluetooth),a:b0,b:b1,y:b2,x:b3,leftshoulder:b4,rightshoulder:b5,back:b8,start:b9,guide:b10,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,lefttrigger:a2,rightx:a3,righty:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+ "05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,",
+ "050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"050000007e0500003003000001000000,Nintendo Wii U Pro Controller,a:b0,b:b1,x:b3,y:b2,back:b8,start:b9,guide:b10,leftshoulder:b4,rightshoulder:b5,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:b13,dpleft:b15,dpdown:b14,dpright:b16,",
"05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
"05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,x:b2,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,",
"05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,",
"060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,",
+ "06000000adde0000efbe000002010000,Hidromancer Game Controller,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
#endif
#if defined(__ANDROID__)
diff --git a/main/main.cpp b/main/main.cpp
index b2f091e76a..1328807121 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -819,7 +819,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", false);
}
- use_vsync = GLOBAL_DEF("display/window/vsync/use_vsync", true);
+ video_mode.use_vsync = GLOBAL_DEF("display/window/vsync/use_vsync", true);
GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation", 2);
GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation.mobile", 3);
@@ -993,8 +993,6 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
// also init our arvr_server from here
arvr_server = memnew(ARVRServer);
- OS::get_singleton()->set_use_vsync(use_vsync);
-
register_core_singletons();
MAIN_PRINT("Main: Setup Logo");
diff --git a/main/splash_sponsors.png b/main/splash_sponsors.png
new file mode 100644
index 0000000000..d8677f1749
--- /dev/null
+++ b/main/splash_sponsors.png
Binary files differ
diff --git a/misc/hooks/pre-commit-clang-format b/misc/hooks/pre-commit-clang-format
index d2d65a7428..8ef4e27748 100755
--- a/misc/hooks/pre-commit-clang-format
+++ b/misc/hooks/pre-commit-clang-format
@@ -31,7 +31,7 @@ PARSE_EXTS=true
# File types to parse. Only effective when PARSE_EXTS is true.
# FILE_EXTS=".c .h .cpp .hpp"
-FILE_EXTS=".c .h .cpp .hpp .cc .hh .cxx .m .mm .inc"
+FILE_EXTS=".c .h .cpp .hpp .cc .hh .cxx .m .mm .inc *.java"
# Use pygmentize instead of cat to parse diff with highlighting.
# Install it with `pip install pygments` (Linux) or `easy_install Pygments` (Mac)
diff --git a/misc/travis/clang-format.sh b/misc/travis/clang-format.sh
index 2b30cf5ada..d1e37cc10e 100755
--- a/misc/travis/clang-format.sh
+++ b/misc/travis/clang-format.sh
@@ -11,7 +11,7 @@ else
RANGE=HEAD
fi
-FILES=$(git diff-tree --no-commit-id --name-only -r $RANGE | grep -v thirdparty/ | grep -E "\.(c|h|cpp|hpp|cc|hh|cxx|m|mm|inc)$")
+FILES=$(git diff-tree --no-commit-id --name-only -r $RANGE | grep -v thirdparty/ | grep -E "\.(c|h|cpp|hpp|cc|hh|cxx|m|mm|inc|java)$")
echo "Checking files:\n$FILES"
# create a random filename to store our generated patch
diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp
index 26c879fddb..b233edc0d4 100644
--- a/modules/bullet/bullet_physics_server.cpp
+++ b/modules/bullet/bullet_physics_server.cpp
@@ -723,16 +723,16 @@ void BulletPhysicsServer::body_set_axis_velocity(RID p_body, const Vector3 &p_ax
body->set_linear_velocity(v);
}
-void BulletPhysicsServer::body_set_axis_lock(RID p_body, PhysicsServer::BodyAxisLock p_lock) {
+void BulletPhysicsServer::body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) {
RigidBodyBullet *body = rigid_body_owner.get(p_body);
ERR_FAIL_COND(!body);
- body->set_axis_lock(p_lock);
+ body->set_axis_lock(p_axis, p_lock);
}
-PhysicsServer::BodyAxisLock BulletPhysicsServer::body_get_axis_lock(RID p_body) const {
+bool BulletPhysicsServer::body_is_axis_locked(RID p_body, BodyAxis p_axis) const {
const RigidBodyBullet *body = rigid_body_owner.get(p_body);
- ERR_FAIL_COND_V(!body, BODY_AXIS_LOCK_DISABLED);
- return body->get_axis_lock();
+ ERR_FAIL_COND_V(!body, 0);
+ return body->is_axis_locked(p_axis);
}
void BulletPhysicsServer::body_add_collision_exception(RID p_body, RID p_body_b) {
diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h
index ad8137ee2f..8a10c87fc6 100644
--- a/modules/bullet/bullet_physics_server.h
+++ b/modules/bullet/bullet_physics_server.h
@@ -226,8 +226,8 @@ public:
virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse);
virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity);
- virtual void body_set_axis_lock(RID p_body, BodyAxisLock p_lock);
- virtual BodyAxisLock body_get_axis_lock(RID p_body) const;
+ virtual void body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock);
+ virtual bool body_is_axis_locked(RID p_body, BodyAxis p_axis) const;
virtual void body_add_collision_exception(RID p_body, RID p_body_b);
virtual void body_remove_collision_exception(RID p_body, RID p_body_b);
diff --git a/modules/bullet/godot_result_callbacks.h b/modules/bullet/godot_result_callbacks.h
index 5750dc2acd..9d2fb1fce4 100644
--- a/modules/bullet/godot_result_callbacks.h
+++ b/modules/bullet/godot_result_callbacks.h
@@ -50,14 +50,21 @@ struct GodotFilterCallback : public btOverlapFilterCallback {
struct GodotClosestRayResultCallback : public btCollisionWorld::ClosestRayResultCallback {
const Set<RID> *m_exclude;
bool m_pickRay;
+ int m_shapeId;
public:
GodotClosestRayResultCallback(const btVector3 &rayFromWorld, const btVector3 &rayToWorld, const Set<RID> *p_exclude) :
btCollisionWorld::ClosestRayResultCallback(rayFromWorld, rayToWorld),
m_exclude(p_exclude),
- m_pickRay(false) {}
+ m_pickRay(false),
+ m_shapeId(0) {}
virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
+
+ virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult &rayResult, bool normalInWorldSpace) {
+ m_shapeId = rayResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID
+ return btCollisionWorld::ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
+ }
};
// store all colliding object
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index b9621a0585..669b2c3f0c 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -256,6 +256,7 @@ void RigidBodyBullet::KinematicUtilities::just_delete_shapes(int new_size) {
RigidBodyBullet::RigidBodyBullet() :
RigidCollisionObjectBullet(CollisionObjectBullet::TYPE_RIGID_BODY),
kinematic_utilities(NULL),
+ locked_axis(0),
gravity_scale(1),
mass(1),
linearDamp(0),
@@ -280,7 +281,7 @@ RigidBodyBullet::RigidBodyBullet() :
setupBulletCollisionObject(btBody);
set_mode(PhysicsServer::BODY_MODE_RIGID);
- set_axis_lock(PhysicsServer::BODY_AXIS_LOCK_DISABLED);
+ reload_axis_lock();
areasWhereIam.resize(maxAreasWhereIam);
for (int i = areasWhereIam.size() - 1; 0 <= i; --i) {
@@ -501,25 +502,25 @@ void RigidBodyBullet::set_mode(PhysicsServer::BodyMode p_mode) {
switch (p_mode) {
case PhysicsServer::BODY_MODE_KINEMATIC:
mode = PhysicsServer::BODY_MODE_KINEMATIC;
- set_axis_lock(axis_lock); // Reload axis lock
+ reload_axis_lock();
_internal_set_mass(0);
init_kinematic_utilities();
break;
case PhysicsServer::BODY_MODE_STATIC:
mode = PhysicsServer::BODY_MODE_STATIC;
- set_axis_lock(axis_lock); // Reload axis lock
+ reload_axis_lock();
_internal_set_mass(0);
break;
case PhysicsServer::BODY_MODE_RIGID: {
mode = PhysicsServer::BODY_MODE_RIGID;
- set_axis_lock(axis_lock); // Reload axis lock
+ reload_axis_lock();
_internal_set_mass(0 == mass ? 1 : mass);
scratch_space_override_modificator();
break;
}
case PhysicsServer::BODY_MODE_CHARACTER: {
mode = PhysicsServer::BODY_MODE_CHARACTER;
- set_axis_lock(axis_lock); // Reload axis lock
+ reload_axis_lock();
_internal_set_mass(0 == mass ? 1 : mass);
scratch_space_override_modificator();
break;
@@ -658,39 +659,28 @@ Vector3 RigidBodyBullet::get_applied_torque() const {
return gTotTorq;
}
-void RigidBodyBullet::set_axis_lock(PhysicsServer::BodyAxisLock p_lock) {
- axis_lock = p_lock;
-
- if (PhysicsServer::BODY_AXIS_LOCK_DISABLED == axis_lock) {
- btBody->setLinearFactor(btVector3(1., 1., 1.));
- btBody->setAngularFactor(btVector3(1., 1., 1.));
- } else if (PhysicsServer::BODY_AXIS_LOCK_X == axis_lock) {
- btBody->setLinearFactor(btVector3(0., 1., 1.));
- btBody->setAngularFactor(btVector3(1., 0., 0.));
- } else if (PhysicsServer::BODY_AXIS_LOCK_Y == axis_lock) {
- btBody->setLinearFactor(btVector3(1., 0., 1.));
- btBody->setAngularFactor(btVector3(0., 1., 0.));
- } else if (PhysicsServer::BODY_AXIS_LOCK_Z == axis_lock) {
- btBody->setLinearFactor(btVector3(1., 1., 0.));
- btBody->setAngularFactor(btVector3(0., 0., 1.));
+void RigidBodyBullet::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock) {
+ if (lock) {
+ locked_axis |= p_axis;
+ } else {
+ locked_axis &= ~p_axis;
}
- if (PhysicsServer::BODY_MODE_CHARACTER == mode) {
- /// When character lock angular
- btBody->setAngularFactor(btVector3(0., 0., 0.));
- }
+ reload_axis_lock();
}
-PhysicsServer::BodyAxisLock RigidBodyBullet::get_axis_lock() const {
- btVector3 vec = btBody->getLinearFactor();
- if (0. == vec.x()) {
- return PhysicsServer::BODY_AXIS_LOCK_X;
- } else if (0. == vec.y()) {
- return PhysicsServer::BODY_AXIS_LOCK_Y;
- } else if (0. == vec.z()) {
- return PhysicsServer::BODY_AXIS_LOCK_Z;
+bool RigidBodyBullet::is_axis_locked(PhysicsServer::BodyAxis p_axis) const {
+ return locked_axis & p_axis;
+}
+
+void RigidBodyBullet::reload_axis_lock() {
+
+ btBody->setLinearFactor(btVector3(!is_axis_locked(PhysicsServer::BODY_AXIS_LINEAR_X), !is_axis_locked(PhysicsServer::BODY_AXIS_LINEAR_Y), !is_axis_locked(PhysicsServer::BODY_AXIS_LINEAR_Z)));
+ if (PhysicsServer::BODY_MODE_CHARACTER == mode) {
+ /// When character angular is always locked
+ btBody->setAngularFactor(btVector3(0., 0., 0.));
} else {
- return PhysicsServer::BODY_AXIS_LOCK_DISABLED;
+ btBody->setAngularFactor(btVector3(!is_axis_locked(PhysicsServer::BODY_AXIS_ANGULAR_X), !is_axis_locked(PhysicsServer::BODY_AXIS_ANGULAR_Y), !is_axis_locked(PhysicsServer::BODY_AXIS_ANGULAR_Z)));
}
}
diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h
index c54b5784b5..c0eb148e24 100644
--- a/modules/bullet/rigid_body_bullet.h
+++ b/modules/bullet/rigid_body_bullet.h
@@ -184,9 +184,9 @@ private:
KinematicUtilities *kinematic_utilities;
PhysicsServer::BodyMode mode;
- PhysicsServer::BodyAxisLock axis_lock;
GodotMotionState *godotMotionState;
btRigidBody *btBody;
+ uint16_t locked_axis;
real_t mass;
real_t gravity_scale;
real_t linearDamp;
@@ -269,8 +269,9 @@ public:
void set_applied_torque(const Vector3 &p_torque);
Vector3 get_applied_torque() const;
- void set_axis_lock(PhysicsServer::BodyAxisLock p_lock);
- PhysicsServer::BodyAxisLock get_axis_lock() const;
+ void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock);
+ bool is_axis_locked(PhysicsServer::BodyAxis p_axis) const;
+ void reload_axis_lock();
/// Doc:
/// http://www.bulletphysics.org/mediawiki-1.5.8/index.php?title=Anti_tunneling_by_Motion_Clamping
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index c1f6e81734..3ce4b294db 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -97,7 +97,7 @@ bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const V
B_TO_G(btResult.m_hitNormalWorld.normalize(), r_result.normal);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btResult.m_collisionObject->getUserPointer());
if (gObj) {
- r_result.shape = 0;
+ r_result.shape = btResult.m_shapeId;
r_result.rid = gObj->get_self();
r_result.collider_id = gObj->get_instance_id();
r_result.collider = 0 == r_result.collider_id ? NULL : ObjectDB::get_instance(r_result.collider_id);
diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp
index 365def75bc..1cb35ec006 100644
--- a/modules/gdnative/register_types.cpp
+++ b/modules/gdnative/register_types.cpp
@@ -99,12 +99,16 @@ static Set<String> get_gdnative_singletons(EditorFileSystemDirectory *p_dir) {
}
static void actual_discoverer_handler() {
+
EditorFileSystemDirectory *dir = EditorFileSystem::get_singleton()->get_filesystem();
Set<String> file_paths = get_gdnative_singletons(dir);
bool changed = false;
- Array current_files = ProjectSettings::get_singleton()->get("gdnative/singletons");
+ Array current_files;
+ if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) {
+ current_files = ProjectSettings::get_singleton()->get("gdnative/singletons");
+ }
Array files;
files.resize(file_paths.size());
int i = 0;
@@ -128,7 +132,6 @@ static void actual_discoverer_handler() {
if (changed) {
ProjectSettings::get_singleton()->set("gdnative/singletons", files);
-
ProjectSettings::get_singleton()->save();
}
}
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index d2ce318f82..ee23f0ea0f 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -515,7 +515,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
} else {
v = "of type '" + _get_var_type(index) + "'";
}
- err_text = "Invalid set index " + v + " (on base: '" + _get_var_type(dst) + "') with value of type '"+_get_var_type(value)+"'";
+ err_text = "Invalid set index " + v + " (on base: '" + _get_var_type(dst) + "') with value of type '" + _get_var_type(value) + "'";
OPCODE_BREAK;
}
#endif
@@ -574,7 +574,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#ifdef DEBUG_ENABLED
if (!valid) {
String err_type;
- err_text = "Invalid set index '" + String(*index) + "' (on base: '" + _get_var_type(dst) + "') with value of type '"+_get_var_type(value)+"'.";
+ err_text = "Invalid set index '" + String(*index) + "' (on base: '" + _get_var_type(dst) + "') with value of type '" + _get_var_type(value) + "'.";
OPCODE_BREAK;
}
#endif
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index e48b03968b..599f204184 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -3389,6 +3389,10 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
_set_error("Can't export null type.");
return;
}
+ if (type == Variant::OBJECT) {
+ _set_error("Can't export raw object type.");
+ return;
+ }
current_export.type = type;
current_export.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE;
tokenizer->advance();
diff --git a/modules/thekla_unwrap/SCsub b/modules/thekla_unwrap/SCsub
index 2b1349a15f..1d4b086848 100644
--- a/modules/thekla_unwrap/SCsub
+++ b/modules/thekla_unwrap/SCsub
@@ -47,7 +47,8 @@ if env['builtin_thekla_atlas']:
"nvmesh/param/SingleFaceMap.cpp",
"nvmesh/param/Util.cpp",
"nvmesh/weld/VertexWeld.cpp",
- "nvmesh/weld/Snap.cpp"
+ "nvmesh/weld/Snap.cpp",
+ "thekla/thekla_atlas.cpp"
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
diff --git a/modules/thekla_unwrap/register_types.cpp b/modules/thekla_unwrap/register_types.cpp
index 8a9f8341e8..01b834f8cb 100644
--- a/modules/thekla_unwrap/register_types.cpp
+++ b/modules/thekla_unwrap/register_types.cpp
@@ -28,7 +28,88 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "register_types.h"
+#include "thirdparty/thekla_atlas/thekla/thekla_atlas.h"
+#include <stdio.h>
+#include <stdlib.h>
+extern bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y);
-void register_thekla_unwrap_types() {}
+bool thekla_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y) {
-void unregister_thekla_unwrap_types() {}
+ //set up input mesh
+ Thekla::Atlas_Input_Mesh input_mesh;
+ input_mesh.face_array = new Thekla::Atlas_Input_Face[p_index_count / 3];
+ for (int i = 0; i < p_index_count / 3; i++) {
+ input_mesh.face_array[i].vertex_index[0] = p_indices[i * 3 + 0];
+ input_mesh.face_array[i].vertex_index[1] = p_indices[i * 3 + 1];
+ input_mesh.face_array[i].vertex_index[2] = p_indices[i * 3 + 2];
+ printf("face %i - %i, %i, %i - mat %i\n", i, input_mesh.face_array[i].vertex_index[0], input_mesh.face_array[i].vertex_index[1], input_mesh.face_array[i].vertex_index[2], p_face_materials[i]);
+ input_mesh.face_array[i].material_index = p_face_materials[i];
+ }
+ input_mesh.vertex_array = new Thekla::Atlas_Input_Vertex[p_vertex_count];
+ for (int i = 0; i < p_vertex_count; i++) {
+ input_mesh.vertex_array[i].first_colocal = i; //wtf
+ for (int j = 0; j < 3; j++) {
+ input_mesh.vertex_array[i].position[j] = p_vertices[i * 3 + j];
+ input_mesh.vertex_array[i].normal[j] = p_normals[i * 3 + j];
+ }
+ input_mesh.vertex_array[i].uv[0] = 0;
+ input_mesh.vertex_array[i].uv[1] = 0;
+ printf("vertex %i - %f, %f, %f\n", i, input_mesh.vertex_array[i].position[0], input_mesh.vertex_array[i].position[1], input_mesh.vertex_array[i].position[2]);
+ printf("normal %i - %f, %f, %f\n", i, input_mesh.vertex_array[i].normal[0], input_mesh.vertex_array[i].normal[1], input_mesh.vertex_array[i].normal[2]);
+ }
+ input_mesh.face_count = p_index_count / 3;
+ input_mesh.vertex_count = p_vertex_count;
+
+ //set up options
+ Thekla::Atlas_Options options;
+ Thekla::atlas_set_default_options(&options);
+ options.packer_options.witness.packing_quality = 1;
+ options.packer_options.witness.texel_area = 1.0 / p_texel_size;
+
+ //generate
+ Thekla::Atlas_Error err;
+ Thekla::Atlas_Output_Mesh *output = atlas_generate(&input_mesh, &options, &err);
+
+ delete[] input_mesh.face_array;
+ delete[] input_mesh.vertex_array;
+
+ if (err != Thekla::Atlas_Error_Success) {
+ printf("error with atlas\n");
+ } else {
+ *r_vertex = (int *)malloc(sizeof(int) * output->vertex_count);
+ *r_uv = (float *)malloc(sizeof(float) * output->vertex_count * 3);
+ *r_index = (int *)malloc(sizeof(int) * output->index_count);
+
+ // printf("w: %i, h: %i\n", output->atlas_width, output->atlas_height);
+ for (int i = 0; i < output->vertex_count; i++) {
+ (*r_vertex)[i] = output->vertex_array[i].xref;
+ (*r_uv)[i * 2 + 0] = output->vertex_array[i].uv[0] / output->atlas_width;
+ (*r_uv)[i * 2 + 1] = output->vertex_array[i].uv[1] / output->atlas_height;
+ // printf("uv: %f,%f\n", (*r_uv)[i * 2 + 0], (*r_uv)[i * 2 + 1]);
+ }
+ *r_vertex_count = output->vertex_count;
+
+ for (int i = 0; i < output->index_count; i++) {
+ (*r_index)[i] = output->index_array[i];
+ }
+
+ *r_index_count = output->index_count;
+
+ *r_size_hint_x = output->atlas_height;
+ *r_size_hint_y = output->atlas_width;
+ }
+
+ if (output) {
+ atlas_free(output);
+ }
+
+ return err == Thekla::Atlas_Error_Success;
+}
+
+void register_thekla_unwrap_types() {
+
+ array_mesh_lightmap_unwrap_callback = thekla_mesh_lightmap_unwrap_callback;
+}
+
+void unregister_thekla_unwrap_types() {
+}
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index bb6c32e9e0..53d93798d9 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -2047,6 +2047,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
function.argument_count = func_node->get_argument_count();
function.max_stack += function.argument_count;
function.flow_stack_size = func_node->is_stack_less() ? 0 : func_node->get_stack_size();
+ max_input_args = MAX(max_input_args, function.argument_count);
}
//multiple passes are required to set up this complex thing..
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 67e00f4952..255413bf2c 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -1557,12 +1557,15 @@ public:
encode_uint32(cl.size(), &clf[0]);
for (int i = 0; i < cl.size(); i++) {
+ print_line(itos(i) + " param: " + cl[i]);
CharString txt = cl[i].utf8();
int base = clf.size();
- clf.resize(base + 4 + txt.length());
- encode_uint32(txt.length(), &clf[base]);
- copymem(&clf[base + 4], txt.ptr(), txt.length());
- print_line(itos(i) + " param: " + cl[i]);
+ int length = txt.length();
+ if (!length)
+ continue;
+ clf.resize(base + 4 + length);
+ encode_uint32(length, &clf[base]);
+ copymem(&clf[base + 4], txt.ptr(), length);
}
zip_fileinfo zipfi = get_zip_fileinfo();
diff --git a/platform/android/java/src/org/godotengine/godot/Dictionary.java b/platform/android/java/src/org/godotengine/godot/Dictionary.java
index ed91fedd85..2bc9c083aa 100644
--- a/platform/android/java/src/org/godotengine/godot/Dictionary.java
+++ b/platform/android/java/src/org/godotengine/godot/Dictionary.java
@@ -32,7 +32,6 @@ package org.godotengine.godot;
import java.util.HashMap;
import java.util.Set;
-
public class Dictionary extends HashMap<String, Object> {
protected String[] keys_cache;
@@ -40,7 +39,7 @@ public class Dictionary extends HashMap<String, Object> {
public String[] get_keys() {
String[] ret = new String[size()];
- int i=0;
+ int i = 0;
Set<String> keys = keySet();
for (String key : keys) {
@@ -54,7 +53,7 @@ public class Dictionary extends HashMap<String, Object> {
public Object[] get_values() {
Object[] ret = new Object[size()];
- int i=0;
+ int i = 0;
Set<String> keys = keySet();
for (String key : keys) {
@@ -71,7 +70,7 @@ public class Dictionary extends HashMap<String, Object> {
public void set_values(Object[] vals) {
- int i=0;
+ int i = 0;
for (String key : keys_cache) {
put(key, vals[i]);
i++;
diff --git a/platform/android/java/src/org/godotengine/godot/Godot.java b/platform/android/java/src/org/godotengine/godot/Godot.java
index 4daf06142d..3939ceb2e7 100644
--- a/platform/android/java/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/src/org/godotengine/godot/Godot.java
@@ -90,35 +90,34 @@ import android.os.Bundle;
import android.os.Messenger;
import android.os.SystemClock;
-
-public class Godot extends Activity implements SensorEventListener, IDownloaderClient
-{
+public class Godot extends Activity implements SensorEventListener, IDownloaderClient {
static final int MAX_SINGLETONS = 64;
private IStub mDownloaderClientStub;
- private IDownloaderService mRemoteService;
- private TextView mStatusText;
- private TextView mProgressFraction;
- private TextView mProgressPercent;
- private TextView mAverageSpeed;
- private TextView mTimeRemaining;
- private ProgressBar mPB;
-
- private View mDashboard;
- private View mCellMessage;
-
- private Button mPauseButton;
- private Button mWiFiSettingsButton;
-
- private boolean use_32_bits=false;
- private boolean use_immersive=false;
- private boolean mStatePaused;
- private int mState;
- private boolean keep_screen_on=true;
+ private IDownloaderService mRemoteService;
+ private TextView mStatusText;
+ private TextView mProgressFraction;
+ private TextView mProgressPercent;
+ private TextView mAverageSpeed;
+ private TextView mTimeRemaining;
+ private ProgressBar mPB;
+
+ private View mDashboard;
+ private View mCellMessage;
+
+ private Button mPauseButton;
+ private Button mWiFiSettingsButton;
+
+ private boolean use_32_bits = false;
+ private boolean use_immersive = false;
+ private boolean mStatePaused;
+ private int mState;
+ private boolean keep_screen_on = true;
static private Intent mCurrentIntent;
- @Override public void onNewIntent(Intent intent) {
+ @Override
+ public void onNewIntent(Intent intent) {
mCurrentIntent = intent;
}
@@ -127,43 +126,43 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
}
private void setState(int newState) {
- if (mState != newState) {
- mState = newState;
- mStatusText.setText(Helpers.getDownloaderStringResourceIDFromState(newState));
- }
- }
-
- private void setButtonPausedState(boolean paused) {
- mStatePaused = paused;
- int stringResourceID = paused ? com.godot.game.R.string.text_button_resume :
- com.godot.game.R.string.text_button_pause;
- mPauseButton.setText(stringResourceID);
- }
+ if (mState != newState) {
+ mState = newState;
+ mStatusText.setText(Helpers.getDownloaderStringResourceIDFromState(newState));
+ }
+ }
+
+ private void setButtonPausedState(boolean paused) {
+ mStatePaused = paused;
+ int stringResourceID = paused ? com.godot.game.R.string.text_button_resume :
+ com.godot.game.R.string.text_button_pause;
+ mPauseButton.setText(stringResourceID);
+ }
static public class SingletonBase {
protected void registerClass(String p_name, String[] p_methods) {
- GodotLib.singleton(p_name,this);
+ GodotLib.singleton(p_name, this);
Class clazz = getClass();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
- boolean found=false;
- Log.d("XXX","METHOD: %s\n" + method.getName());
+ boolean found = false;
+ Log.d("XXX", "METHOD: %s\n" + method.getName());
for (String s : p_methods) {
- Log.d("XXX", "METHOD CMP WITH: %s\n" + s);
+ Log.d("XXX", "METHOD CMP WITH: %s\n" + s);
if (s.equals(method.getName())) {
- found=true;
- Log.d("XXX","METHOD CMP VALID");
+ found = true;
+ Log.d("XXX", "METHOD CMP VALID");
break;
}
}
if (!found)
continue;
- Log.d("XXX","METHOD FOUND: %s\n" + method.getName());
+ Log.d("XXX", "METHOD FOUND: %s\n" + method.getName());
List<String> ptr = new ArrayList<String>();
@@ -175,17 +174,13 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
String[] pt = new String[ptr.size()];
ptr.toArray(pt);
- GodotLib.method(p_name,method.getName(),method.getReturnType().getName(),pt);
-
-
+ GodotLib.method(p_name, method.getName(), method.getReturnType().getName(), pt);
}
- Godot.singletons[Godot.singleton_count++]=this;
+ Godot.singletons[Godot.singleton_count++] = this;
}
protected void onMainActivityResult(int requestCode, int resultCode, Intent data) {
-
-
}
protected void onMainPause() {}
@@ -200,22 +195,20 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
public void registerMethods() {}
}
-/*
+ /*
protected List<SingletonBase> singletons = new ArrayList<SingletonBase>();
protected void instanceSingleton(SingletonBase s) {
s.registerMethods();
singletons.add(s);
}
-
-*/
+ */
private String[] command_line;
private boolean use_apk_expansion;
public GodotView mView;
- private boolean godot_initialized=false;
-
+ private boolean godot_initialized = false;
private SensorManager mSensorManager;
private Sensor mAccelerometer;
@@ -226,36 +219,34 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
public FrameLayout layout;
public RelativeLayout adLayout;
-
static public GodotIO io;
public static void setWindowTitle(String title) {
//setTitle(title);
}
-
static SingletonBase singletons[] = new SingletonBase[MAX_SINGLETONS];
- static int singleton_count=0;
-
+ static int singleton_count = 0;
public interface ResultCallback {
public void callback(int requestCode, int resultCode, Intent data);
- };
+ }
public ResultCallback result_callback;
private PaymentsManager mPaymentsManager = null;
- @Override protected void onActivityResult (int requestCode, int resultCode, Intent data) {
- if(requestCode == PaymentsManager.REQUEST_CODE_FOR_PURCHASE){
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == PaymentsManager.REQUEST_CODE_FOR_PURCHASE) {
mPaymentsManager.processPurchaseResponse(resultCode, data);
- }else if (result_callback != null) {
+ } else if (result_callback != null) {
result_callback.callback(requestCode, resultCode, data);
result_callback = null;
};
- for(int i=0;i<singleton_count;i++) {
+ for (int i = 0; i < singleton_count; i++) {
- singletons[i].onMainActivityResult(requestCode,resultCode,data);
+ singletons[i].onMainActivityResult(requestCode, resultCode, data);
}
};
@@ -265,38 +256,38 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
//setContentView(mView);
layout = new FrameLayout(this);
- layout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
+ layout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
setContentView(layout);
// GodotEditText layout
GodotEditText edittext = new GodotEditText(this);
- edittext.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
- // ...add to FrameLayout
- layout.addView(edittext);
+ edittext.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
+ // ...add to FrameLayout
+ layout.addView(edittext);
- mView = new GodotView(getApplication(),io,use_gl2,use_32_bits, this);
- layout.addView(mView,new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
+ mView = new GodotView(getApplication(), io, use_gl2, use_32_bits, this);
+ layout.addView(mView, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
edittext.setView(mView);
io.setEdit(edittext);
final Godot godot = this;
mView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
- @Override
- public void onGlobalLayout() {
- Point fullSize = new Point();
- godot.getWindowManager().getDefaultDisplay().getSize(fullSize);
- Rect gameSize = new Rect();
- godot.mView.getWindowVisibleDisplayFrame(gameSize);
-
- final int keyboardHeight = fullSize.y - gameSize.bottom;
- Log.d("GODOT", "setVirtualKeyboardHeight: " + keyboardHeight);
- GodotLib.setVirtualKeyboardHeight(keyboardHeight);
- }
+ @Override
+ public void onGlobalLayout() {
+ Point fullSize = new Point();
+ godot.getWindowManager().getDefaultDisplay().getSize(fullSize);
+ Rect gameSize = new Rect();
+ godot.mView.getWindowVisibleDisplayFrame(gameSize);
+
+ final int keyboardHeight = fullSize.y - gameSize.bottom;
+ Log.d("GODOT", "setVirtualKeyboardHeight: " + keyboardHeight);
+ GodotLib.setVirtualKeyboardHeight(keyboardHeight);
+ }
});
// Ad layout
adLayout = new RelativeLayout(this);
- adLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
+ adLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
layout.addView(adLayout);
final String[] current_command_line = command_line;
@@ -313,12 +304,11 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
});
}
});
-
}
public void setKeepScreenOn(final boolean p_enabled) {
keep_screen_on = p_enabled;
- if (mView != null){
+ if (mView != null) {
runOnUiThread(new Runnable() {
@Override
public void run() {
@@ -335,12 +325,12 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
AlertDialog.Builder builder = new AlertDialog.Builder(getInstance());
builder.setMessage(message).setTitle(title);
builder.setPositiveButton(
- "OK",
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- dialog.cancel();
- }
- });
+ "OK",
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.cancel();
+ }
+ });
AlertDialog dialog = builder.create();
dialog.show();
}
@@ -349,91 +339,86 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
private static Godot _self;
- public static Godot getInstance(){
+ public static Godot getInstance() {
return Godot._self;
}
-
private String[] getCommandLine() {
- InputStream is;
- try {
- is = getAssets().open("_cl_");
- byte[] len = new byte[4];
- int r = is.read(len);
- if (r<4) {
- Log.d("XXX","**ERROR** Wrong cmdline length.\n");
- Log.d("GODOT", "**ERROR** Wrong cmdline length.\n");
- return new String[0];
- }
- int argc=((int)(len[3]&0xFF)<<24) | ((int)(len[2]&0xFF)<<16) | ((int)(len[1]&0xFF)<<8) | ((int)(len[0]&0xFF));
- String[] cmdline = new String[argc];
-
- for(int i=0;i<argc;i++) {
- r = is.read(len);
- if (r<4) {
-
- Log.d("GODOT", "**ERROR** Wrong cmdline param length.\n");
- return new String[0];
- }
- int strlen=((int)(len[3]&0xFF)<<24) | ((int)(len[2]&0xFF)<<16) | ((int)(len[1]&0xFF)<<8) | ((int)(len[0]&0xFF));
- if (strlen>65535) {
- Log.d("GODOT", "**ERROR** Wrong command len\n");
- return new String[0];
- }
- byte[] arg = new byte[strlen];
- r = is.read(arg);
- if (r==strlen) {
- cmdline[i]=new String(arg,"UTF-8");
- }
+ InputStream is;
+ try {
+ is = getAssets().open("_cl_");
+ byte[] len = new byte[4];
+ int r = is.read(len);
+ if (r < 4) {
+ Log.d("XXX", "**ERROR** Wrong cmdline length.\n");
+ Log.d("GODOT", "**ERROR** Wrong cmdline length.\n");
+ return new String[0];
+ }
+ int argc = ((int)(len[3] & 0xFF) << 24) | ((int)(len[2] & 0xFF) << 16) | ((int)(len[1] & 0xFF) << 8) | ((int)(len[0] & 0xFF));
+ String[] cmdline = new String[argc];
+
+ for (int i = 0; i < argc; i++) {
+ r = is.read(len);
+ if (r < 4) {
+
+ Log.d("GODOT", "**ERROR** Wrong cmdline param length.\n");
+ return new String[0];
+ }
+ int strlen = ((int)(len[3] & 0xFF) << 24) | ((int)(len[2] & 0xFF) << 16) | ((int)(len[1] & 0xFF) << 8) | ((int)(len[0] & 0xFF));
+ if (strlen > 65535) {
+ Log.d("GODOT", "**ERROR** Wrong command len\n");
+ return new String[0];
+ }
+ byte[] arg = new byte[strlen];
+ r = is.read(arg);
+ if (r == strlen) {
+ cmdline[i] = new String(arg, "UTF-8");
+ }
}
return cmdline;
} catch (Exception e) {
- e.printStackTrace();
- Log.d("GODOT", "**ERROR** Exception " + e.getClass().getName() + ":" + e.getMessage());
+ e.printStackTrace();
+ Log.d("GODOT", "**ERROR** Exception " + e.getClass().getName() + ":" + e.getMessage());
return new String[0];
}
-
-
}
-
String expansion_pack_path;
-
private void initializeGodot() {
- if (expansion_pack_path!=null) {
+ if (expansion_pack_path != null) {
String[] new_cmdline;
- int cll=0;
- if (command_line!=null) {
- Log.d("GODOT", "initializeGodot: command_line: is not null" );
- new_cmdline = new String[ command_line.length + 2 ];
- cll=command_line.length;
- for(int i=0;i<command_line.length;i++) {
- new_cmdline[i]=command_line[i];
+ int cll = 0;
+ if (command_line != null) {
+ Log.d("GODOT", "initializeGodot: command_line: is not null");
+ new_cmdline = new String[command_line.length + 2];
+ cll = command_line.length;
+ for (int i = 0; i < command_line.length; i++) {
+ new_cmdline[i] = command_line[i];
}
} else {
- Log.d("GODOT", "initializeGodot: command_line: is null" );
- new_cmdline = new String[ 2 ];
+ Log.d("GODOT", "initializeGodot: command_line: is null");
+ new_cmdline = new String[2];
}
- new_cmdline[cll]="--main_pack";
- new_cmdline[cll+1]=expansion_pack_path;
- command_line=new_cmdline;
+ new_cmdline[cll] = "--main_pack";
+ new_cmdline[cll + 1] = expansion_pack_path;
+ command_line = new_cmdline;
}
io = new GodotIO(this);
io.unique_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
- GodotLib.io=io;
- Log.d("GODOT", "command_line is null? " + ((command_line == null)?"yes":"no"));
+ GodotLib.io = io;
+ Log.d("GODOT", "command_line is null? " + ((command_line == null) ? "yes" : "no"));
/*if(command_line != null){
Log.d("GODOT", "Command Line:");
for(int w=0;w <command_line.length;w++){
Log.d("GODOT"," " + command_line[w]);
}
}*/
- mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
+ mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
mGravity = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
@@ -449,18 +434,15 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
mPaymentsManager = PaymentsManager.createManager(this).initService();
- godot_initialized=true;
-
+ godot_initialized = true;
}
@Override
public void onServiceConnected(Messenger m) {
- mRemoteService = DownloaderServiceMarshaller.CreateProxy(m);
- mRemoteService.onClientUpdated(mDownloaderClientStub.getMessenger());
+ mRemoteService = DownloaderServiceMarshaller.CreateProxy(m);
+ mRemoteService.onClientUpdated(mDownloaderClientStub.getMessenger());
}
-
-
@Override
protected void onCreate(Bundle icicle) {
@@ -474,59 +456,58 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
//check for apk expansion API
if (true) {
- boolean md5mismatch = false;
+ boolean md5mismatch = false;
command_line = getCommandLine();
- String main_pack_md5=null;
- String main_pack_key=null;
+ String main_pack_md5 = null;
+ String main_pack_key = null;
List<String> new_args = new LinkedList<String>();
+ for (int i = 0; i < command_line.length; i++) {
- for(int i=0;i<command_line.length;i++) {
-
- boolean has_extra = i< command_line.length -1;
+ boolean has_extra = i < command_line.length - 1;
if (command_line[i].equals("--use_depth_32")) {
- use_32_bits=true;
+ use_32_bits = true;
} else if (command_line[i].equals("--use_immersive")) {
- use_immersive=true;
- if(Build.VERSION.SDK_INT >= 19.0){ // check if the application runs on an android 4.4+
+ use_immersive = true;
+ if (Build.VERSION.SDK_INT >= 19.0) { // check if the application runs on an android 4.4+
window.getDecorView().setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
- | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
- | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | // hide nav bar
+ View.SYSTEM_UI_FLAG_FULLSCREEN | // hide status bar
+ View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
UiChangeListener();
}
} else if (command_line[i].equals("--use_apk_expansion")) {
- use_apk_expansion=true;
+ use_apk_expansion = true;
} else if (has_extra && command_line[i].equals("--apk_expansion_md5")) {
- main_pack_md5=command_line[i+1];
+ main_pack_md5 = command_line[i + 1];
i++;
} else if (has_extra && command_line[i].equals("--apk_expansion_key")) {
- main_pack_key=command_line[i+1];
+ main_pack_key = command_line[i + 1];
SharedPreferences prefs = getSharedPreferences("app_data_keys", MODE_PRIVATE);
Editor editor = prefs.edit();
editor.putString("store_public_key", main_pack_key);
editor.commit();
i++;
- } else if (command_line[i].trim().length()!=0){
+ } else if (command_line[i].trim().length() != 0) {
new_args.add(command_line[i]);
}
}
- if (new_args.isEmpty()){
- command_line=null;
- }else{
+ if (new_args.isEmpty()) {
+ command_line = null;
+ } else {
command_line = new_args.toArray(new String[new_args.size()]);
- }
- if (use_apk_expansion && main_pack_md5!=null && main_pack_key!=null) {
+ }
+ if (use_apk_expansion && main_pack_md5 != null && main_pack_key != null) {
//check that environment is ok!
- if (!Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED )) {
+ if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
Log.d("GODOT", "**ERROR! No media mounted!");
//show popup and die
}
@@ -534,7 +515,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
// Build the full path to the app's expansion files
try {
expansion_pack_path = Helpers.getSaveFilePath(getApplicationContext());
- expansion_pack_path+="/"+"main."+getPackageManager().getPackageInfo(getPackageName(), 0).versionCode+"."+this.getPackageName()+".obb";
+ expansion_pack_path += "/main." + getPackageManager().getPackageInfo(getPackageName(), 0).versionCode + "." + this.getPackageName() + ".obb";
} catch (Exception e) {
e.printStackTrace();
}
@@ -542,20 +523,20 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
File f = new File(expansion_pack_path);
boolean pack_valid = true;
- Log.d("GODOT","**PACK** - Path "+expansion_pack_path);
+ Log.d("GODOT", "**PACK** - Path " + expansion_pack_path);
if (!f.exists()) {
- pack_valid=false;
- Log.d("GODOT","**PACK** - File does not exist");
+ pack_valid = false;
+ Log.d("GODOT", "**PACK** - File does not exist");
- } else if( obbIsCorrupted(expansion_pack_path, main_pack_md5)){
+ } else if (obbIsCorrupted(expansion_pack_path, main_pack_md5)) {
Log.d("GODOT", "**PACK** - Expansion pack (obb) is corrupted");
pack_valid = false;
- try{
- f.delete();
- }catch(Exception e){
- Log.d("GODOT", "**PACK** - Error deleting corrupted expansion pack (obb)");
+ try {
+ f.delete();
+ } catch (Exception e) {
+ Log.d("GODOT", "**PACK** - Error deleting corrupted expansion pack (obb)");
}
}
@@ -564,12 +545,12 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
Intent notifierIntent = new Intent(this, this.getClass());
notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
- Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ Intent.FLAG_ACTIVITY_CLEAR_TOP);
- PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
- notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
+ notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT);
- int startResult;
+ int startResult;
try {
Log.d("GODOT", "INITIALIZING DOWNLOAD");
startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(
@@ -578,36 +559,34 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
GodotDownloaderService.class);
Log.d("GODOT", "DOWNLOAD SERVICE FINISHED:" + startResult);
- if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
- Log.d("GODOT", "DOWNLOAD REQUIRED");
- // This is where you do set up to display the download
- // progress (next step)
- mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this,
- GodotDownloaderService.class);
-
- setContentView(com.godot.game.R.layout.downloading_expansion);
- mPB = (ProgressBar) findViewById(com.godot.game.R.id.progressBar);
- mStatusText = (TextView) findViewById(com.godot.game.R.id.statusText);
- mProgressFraction = (TextView) findViewById(com.godot.game.R.id.progressAsFraction);
- mProgressPercent = (TextView) findViewById(com.godot.game.R.id.progressAsPercentage);
- mAverageSpeed = (TextView) findViewById(com.godot.game.R.id.progressAverageSpeed);
- mTimeRemaining = (TextView) findViewById(com.godot.game.R.id.progressTimeRemaining);
- mDashboard = findViewById(com.godot.game.R.id.downloaderDashboard);
- mCellMessage = findViewById(com.godot.game.R.id.approveCellular);
- mPauseButton = (Button) findViewById(com.godot.game.R.id.pauseButton);
- mWiFiSettingsButton = (Button) findViewById(com.godot.game.R.id.wifiSettingsButton);
-
- return;
- } else{
- Log.d("GODOT", "NO DOWNLOAD REQUIRED");
- }
+ if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
+ Log.d("GODOT", "DOWNLOAD REQUIRED");
+ // This is where you do set up to display the download
+ // progress (next step)
+ mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this,
+ GodotDownloaderService.class);
+
+ setContentView(com.godot.game.R.layout.downloading_expansion);
+ mPB = (ProgressBar)findViewById(com.godot.game.R.id.progressBar);
+ mStatusText = (TextView)findViewById(com.godot.game.R.id.statusText);
+ mProgressFraction = (TextView)findViewById(com.godot.game.R.id.progressAsFraction);
+ mProgressPercent = (TextView)findViewById(com.godot.game.R.id.progressAsPercentage);
+ mAverageSpeed = (TextView)findViewById(com.godot.game.R.id.progressAverageSpeed);
+ mTimeRemaining = (TextView)findViewById(com.godot.game.R.id.progressTimeRemaining);
+ mDashboard = findViewById(com.godot.game.R.id.downloaderDashboard);
+ mCellMessage = findViewById(com.godot.game.R.id.approveCellular);
+ mPauseButton = (Button)findViewById(com.godot.game.R.id.pauseButton);
+ mWiFiSettingsButton = (Button)findViewById(com.godot.game.R.id.wifiSettingsButton);
+
+ return;
+ } else {
+ Log.d("GODOT", "NO DOWNLOAD REQUIRED");
+ }
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
Log.d("GODOT", "Error downloading expansion package:" + e.getMessage());
}
-
}
-
}
}
@@ -615,28 +594,26 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
initializeGodot();
-
//instanceSingleton( new GodotFacebook(this) );
-
-
}
+ @Override
+ protected void onDestroy() {
- @Override protected void onDestroy(){
-
- if(mPaymentsManager != null ) mPaymentsManager.destroy();
- for(int i=0;i<singleton_count;i++) {
+ if (mPaymentsManager != null) mPaymentsManager.destroy();
+ for (int i = 0; i < singleton_count; i++) {
singletons[i].onMainDestroy();
}
super.onDestroy();
}
- @Override protected void onPause() {
+ @Override
+ protected void onPause() {
super.onPause();
- if (!godot_initialized){
+ if (!godot_initialized) {
if (null != mDownloaderClientStub) {
- mDownloaderClientStub.disconnect(this);
- }
+ mDownloaderClientStub.disconnect(this);
+ }
return;
}
mView.onPause();
@@ -648,17 +625,18 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
});
mSensorManager.unregisterListener(this);
- for(int i=0;i<singleton_count;i++) {
+ for (int i = 0; i < singleton_count; i++) {
singletons[i].onMainPause();
}
}
- @Override protected void onResume() {
+ @Override
+ protected void onResume() {
super.onResume();
- if (!godot_initialized){
+ if (!godot_initialized) {
if (null != mDownloaderClientStub) {
- mDownloaderClientStub.connect(this);
- }
+ mDownloaderClientStub.connect(this);
+ }
return;
}
@@ -674,59 +652,58 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME);
- if(use_immersive && Build.VERSION.SDK_INT >= 19.0){ // check if the application runs on an android 4.4+
+ if (use_immersive && Build.VERSION.SDK_INT >= 19.0) { // check if the application runs on an android 4.4+
Window window = getWindow();
window.getDecorView().setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
- | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
- | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | // hide nav bar
+ View.SYSTEM_UI_FLAG_FULLSCREEN | // hide status bar
+ View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
- for(int i=0;i<singleton_count;i++) {
+ for (int i = 0; i < singleton_count; i++) {
singletons[i].onMainResume();
}
-
-
-
}
public void UiChangeListener() {
final View decorView = getWindow().getDecorView();
- decorView.setOnSystemUiVisibilityChangeListener (new View.OnSystemUiVisibilityChangeListener() {
+ decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
decorView.setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_FULLSCREEN
- | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
+ View.SYSTEM_UI_FLAG_FULLSCREEN |
+ View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}
});
}
- @Override public void onSensorChanged(SensorEvent event) {
- Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
int displayRotation = display.getRotation();
float[] adjustedValues = new float[3];
final int axisSwap[][] = {
- { 1, -1, 0, 1 }, // ROTATION_0
- {-1, -1, 1, 0 }, // ROTATION_90
- {-1, 1, 0, 1 }, // ROTATION_180
- { 1, 1, 1, 0 } }; // ROTATION_270
+ { 1, -1, 0, 1 }, // ROTATION_0
+ { -1, -1, 1, 0 }, // ROTATION_90
+ { -1, 1, 0, 1 }, // ROTATION_180
+ { 1, 1, 1, 0 }
+ }; // ROTATION_270
final int[] as = axisSwap[displayRotation];
- adjustedValues[0] = (float)as[0] * event.values[ as[2] ];
- adjustedValues[1] = (float)as[1] * event.values[ as[3] ];
- adjustedValues[2] = event.values[2];
+ adjustedValues[0] = (float)as[0] * event.values[as[2]];
+ adjustedValues[1] = (float)as[1] * event.values[as[3]];
+ adjustedValues[2] = event.values[2];
final float x = adjustedValues[0];
final float y = adjustedValues[1];
@@ -738,27 +715,28 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
@Override
public void run() {
if (typeOfSensor == Sensor.TYPE_ACCELEROMETER) {
- GodotLib.accelerometer(-x,y,-z);
+ GodotLib.accelerometer(-x, y, -z);
}
if (typeOfSensor == Sensor.TYPE_GRAVITY) {
- GodotLib.gravity(-x,y,-z);
+ GodotLib.gravity(-x, y, -z);
}
if (typeOfSensor == Sensor.TYPE_MAGNETIC_FIELD) {
- GodotLib.magnetometer(-x,y,-z);
+ GodotLib.magnetometer(-x, y, -z);
}
if (typeOfSensor == Sensor.TYPE_GYROSCOPE) {
- GodotLib.gyroscope(x,-y,z);
+ GodotLib.gyroscope(x, -y, z);
}
}
});
}
}
- @Override public final void onAccuracyChanged(Sensor sensor, int accuracy) {
+ @Override
+ public final void onAccuracyChanged(Sensor sensor, int accuracy) {
// Do something here if sensor accuracy changes.
}
-/*
+ /*
@Override public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
@@ -772,12 +750,13 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
return false;
}
-*/
+ */
- @Override public void onBackPressed() {
+ @Override
+ public void onBackPressed() {
boolean shouldQuit = true;
- for(int i=0;i<singleton_count;i++) {
+ for (int i = 0; i < singleton_count; i++) {
if (singletons[i].onMainBackPressed()) {
shouldQuit = false;
}
@@ -799,71 +778,68 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
System.exit(0);
}
+ private boolean obbIsCorrupted(String f, String main_pack_md5) {
+ try {
- private boolean obbIsCorrupted(String f, String main_pack_md5){
-
- try {
-
- InputStream fis = new FileInputStream(f);
+ InputStream fis = new FileInputStream(f);
- // Create MD5 Hash
- byte[] buffer = new byte[16384];
-
- MessageDigest complete = MessageDigest.getInstance("MD5");
- int numRead;
- do {
- numRead = fis.read(buffer);
- if (numRead > 0) {
- complete.update(buffer, 0, numRead);
- }
- } while (numRead != -1);
+ // Create MD5 Hash
+ byte[] buffer = new byte[16384];
+ MessageDigest complete = MessageDigest.getInstance("MD5");
+ int numRead;
+ do {
+ numRead = fis.read(buffer);
+ if (numRead > 0) {
+ complete.update(buffer, 0, numRead);
+ }
+ } while (numRead != -1);
- fis.close();
- byte[] messageDigest = complete.digest();
+ fis.close();
+ byte[] messageDigest = complete.digest();
- // Create Hex String
- StringBuffer hexString = new StringBuffer();
- for (int i=0; i<messageDigest.length; i++) {
- String s = Integer.toHexString(0xFF & messageDigest[i]);
+ // Create Hex String
+ StringBuffer hexString = new StringBuffer();
+ for (int i = 0; i < messageDigest.length; i++) {
+ String s = Integer.toHexString(0xFF & messageDigest[i]);
- if (s.length()==1) {
- s="0"+s;
- }
- hexString.append(s);
- }
- String md5str = hexString.toString();
+ if (s.length() == 1) {
+ s = "0" + s;
+ }
+ hexString.append(s);
+ }
+ String md5str = hexString.toString();
- //Log.d("GODOT","**PACK** - My MD5: "+hexString+" - APK md5: "+main_pack_md5);
- if (!md5str.equals(main_pack_md5)) {
- Log.d("GODOT","**PACK MD5 MISMATCH???** - MD5 Found: "+md5str+" "+Integer.toString(md5str.length())+" - MD5 Expected: "+main_pack_md5+" "+Integer.toString(main_pack_md5.length()));
- return true;
- }
- return false;
- } catch (Exception e) {
- e.printStackTrace();
- Log.d("GODOT","**PACK FAIL**");
- return true;
- }
+ //Log.d("GODOT","**PACK** - My MD5: "+hexString+" - APK md5: "+main_pack_md5);
+ if (!md5str.equals(main_pack_md5)) {
+ Log.d("GODOT", "**PACK MD5 MISMATCH???** - MD5 Found: " + md5str + " " + Integer.toString(md5str.length()) + " - MD5 Expected: " + main_pack_md5 + " " + Integer.toString(main_pack_md5.length()));
+ return true;
+ }
+ return false;
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.d("GODOT", "**PACK FAIL**");
+ return true;
+ }
}
//@Override public boolean dispatchTouchEvent (MotionEvent event) {
public boolean gotTouchEvent(final MotionEvent event) {
super.onTouchEvent(event);
- final int evcount=event.getPointerCount();
- if (evcount==0)
+ final int evcount = event.getPointerCount();
+ if (evcount == 0)
return true;
if (mView != null) {
- final int[] arr = new int[event.getPointerCount()*3];
+ final int[] arr = new int[event.getPointerCount() * 3];
- for(int i=0;i<event.getPointerCount();i++) {
+ for (int i = 0; i < event.getPointerCount(); i++) {
- arr[i*3+0]=(int)event.getPointerId(i);
- arr[i*3+1]=(int)event.getX(i);
- arr[i*3+2]=(int)event.getY(i);
+ arr[i * 3 + 0] = (int)event.getPointerId(i);
+ arr[i * 3 + 1] = (int)event.getX(i);
+ arr[i * 3 + 2] = (int)event.getY(i);
}
//System.out.printf("gaction: %d\n",event.getAction());
@@ -871,13 +847,13 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
mView.queueEvent(new Runnable() {
@Override
public void run() {
- switch(action) {
+ switch (action) {
case MotionEvent.ACTION_DOWN: {
- GodotLib.touch(0,0,evcount,arr);
+ GodotLib.touch(0, 0, evcount, arr);
//System.out.printf("action down at: %f,%f\n", event.getX(),event.getY());
} break;
case MotionEvent.ACTION_MOVE: {
- GodotLib.touch(1,0,evcount,arr);
+ GodotLib.touch(1, 0, evcount, arr);
/*
for(int i=0;i<event.getPointerCount();i++) {
System.out.printf("%d - moved to: %f,%f\n",i, event.getX(i),event.getY(i));
@@ -887,17 +863,17 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
case MotionEvent.ACTION_POINTER_UP: {
final int indexPointUp = event.getActionIndex();
final int pointer_idx = event.getPointerId(indexPointUp);
- GodotLib.touch(4,pointer_idx,evcount,arr);
+ GodotLib.touch(4, pointer_idx, evcount, arr);
//System.out.printf("%d - s.up at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
} break;
case MotionEvent.ACTION_POINTER_DOWN: {
int pointer_idx = event.getActionIndex();
- GodotLib.touch(3,pointer_idx,evcount,arr);
+ GodotLib.touch(3, pointer_idx, evcount, arr);
//System.out.printf("%d - s.down at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
} break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
- GodotLib.touch(2,0,evcount,arr);
+ GodotLib.touch(2, 0, evcount, arr);
/*
for(int i=0;i<event.getPointerCount();i++) {
System.out.printf("%d - up! %f,%f\n",i, event.getX(i),event.getY(i));
@@ -911,14 +887,16 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
return true;
}
- @Override public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) {
+ @Override
+ public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) {
String s = event.getCharacters();
if (s == null || s.length() == 0)
return super.onKeyMultiple(inKeyCode, repeatCount, event);
final char[] cc = s.toCharArray();
int cnt = 0;
- for (int i = cc.length; --i >= 0; cnt += cc[i] != 0 ? 1 : 0);
+ for (int i = cc.length; --i >= 0; cnt += cc[i] != 0 ? 1 : 0)
+ ;
if (cnt == 0) return super.onKeyMultiple(inKeyCode, repeatCount, event);
final Activity me = this;
queueEvent(new Runnable() {
@@ -939,7 +917,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
private void queueEvent(Runnable runnable) {
// TODO Auto-generated method stub
-
}
public PaymentsManager getPaymentsManager() {
@@ -952,7 +929,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
}
*/
-
// Audio
/**
@@ -960,110 +936,106 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
* to show the state as being indeterminate at times. This sample can be
* considered a guideline.
*/
- @Override
- public void onDownloadStateChanged(int newState) {
- Log.d("GODOT", "onDownloadStateChanged:" + newState);
- setState(newState);
- boolean showDashboard = true;
- boolean showCellMessage = false;
- boolean paused;
- boolean indeterminate;
- switch (newState) {
- case IDownloaderClient.STATE_IDLE:
- Log.d("GODOT", "DOWNLOAD STATE IDLE");
- // STATE_IDLE means the service is listening, so it's
- // safe to start making calls via mRemoteService.
- paused = false;
- indeterminate = true;
- break;
- case IDownloaderClient.STATE_CONNECTING:
- case IDownloaderClient.STATE_FETCHING_URL:
- Log.d("GODOT", "DOWNLOAD STATE CONNECTION / FETCHING URL");
- showDashboard = true;
- paused = false;
- indeterminate = true;
- break;
- case IDownloaderClient.STATE_DOWNLOADING:
- Log.d("GODOT", "DOWNLOAD STATE DOWNLOADING");
- paused = false;
- showDashboard = true;
- indeterminate = false;
- break;
-
- case IDownloaderClient.STATE_FAILED_CANCELED:
- case IDownloaderClient.STATE_FAILED:
- case IDownloaderClient.STATE_FAILED_FETCHING_URL:
- case IDownloaderClient.STATE_FAILED_UNLICENSED:
- Log.d("GODOT", "DOWNLOAD STATE: FAILED, CANCELLED, UNLICENSED OR FAILED TO FETCH URL");
- paused = true;
- showDashboard = false;
- indeterminate = false;
- break;
- case IDownloaderClient.STATE_PAUSED_NEED_CELLULAR_PERMISSION:
- case IDownloaderClient.STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION:
- Log.d("GODOT", "DOWNLOAD STATE: PAUSED BY MISSING CELLULAR PERMISSION");
- showDashboard = false;
- paused = true;
- indeterminate = false;
- showCellMessage = true;
- break;
-
- case IDownloaderClient.STATE_PAUSED_BY_REQUEST:
- Log.d("GODOT", "DOWNLOAD STATE: PAUSED BY USER");
- paused = true;
- indeterminate = false;
- break;
- case IDownloaderClient.STATE_PAUSED_ROAMING:
- case IDownloaderClient.STATE_PAUSED_SDCARD_UNAVAILABLE:
- Log.d("GODOT", "DOWNLOAD STATE: PAUSED BY ROAMING OR SDCARD UNAVAILABLE");
- paused = true;
- indeterminate = false;
- break;
- case IDownloaderClient.STATE_COMPLETED:
- Log.d("GODOT", "DOWNLOAD STATE: COMPLETED");
- showDashboard = false;
- paused = false;
- indeterminate = false;
-// validateXAPKZipFiles();
- initializeGodot();
- return;
- default:
- Log.d("GODOT", "DOWNLOAD STATE: DEFAULT");
- paused = true;
- indeterminate = true;
- showDashboard = true;
- }
- int newDashboardVisibility = showDashboard ? View.VISIBLE : View.GONE;
- if (mDashboard.getVisibility() != newDashboardVisibility) {
- mDashboard.setVisibility(newDashboardVisibility);
- }
- int cellMessageVisibility = showCellMessage ? View.VISIBLE : View.GONE;
- if (mCellMessage.getVisibility() != cellMessageVisibility) {
- mCellMessage.setVisibility(cellMessageVisibility);
- }
-
- mPB.setIndeterminate(indeterminate);
- setButtonPausedState(paused);
- }
+ @Override
+ public void onDownloadStateChanged(int newState) {
+ Log.d("GODOT", "onDownloadStateChanged:" + newState);
+ setState(newState);
+ boolean showDashboard = true;
+ boolean showCellMessage = false;
+ boolean paused;
+ boolean indeterminate;
+ switch (newState) {
+ case IDownloaderClient.STATE_IDLE:
+ Log.d("GODOT", "DOWNLOAD STATE IDLE");
+ // STATE_IDLE means the service is listening, so it's
+ // safe to start making calls via mRemoteService.
+ paused = false;
+ indeterminate = true;
+ break;
+ case IDownloaderClient.STATE_CONNECTING:
+ case IDownloaderClient.STATE_FETCHING_URL:
+ Log.d("GODOT", "DOWNLOAD STATE CONNECTION / FETCHING URL");
+ showDashboard = true;
+ paused = false;
+ indeterminate = true;
+ break;
+ case IDownloaderClient.STATE_DOWNLOADING:
+ Log.d("GODOT", "DOWNLOAD STATE DOWNLOADING");
+ paused = false;
+ showDashboard = true;
+ indeterminate = false;
+ break;
+
+ case IDownloaderClient.STATE_FAILED_CANCELED:
+ case IDownloaderClient.STATE_FAILED:
+ case IDownloaderClient.STATE_FAILED_FETCHING_URL:
+ case IDownloaderClient.STATE_FAILED_UNLICENSED:
+ Log.d("GODOT", "DOWNLOAD STATE: FAILED, CANCELLED, UNLICENSED OR FAILED TO FETCH URL");
+ paused = true;
+ showDashboard = false;
+ indeterminate = false;
+ break;
+ case IDownloaderClient.STATE_PAUSED_NEED_CELLULAR_PERMISSION:
+ case IDownloaderClient.STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION:
+ Log.d("GODOT", "DOWNLOAD STATE: PAUSED BY MISSING CELLULAR PERMISSION");
+ showDashboard = false;
+ paused = true;
+ indeterminate = false;
+ showCellMessage = true;
+ break;
+
+ case IDownloaderClient.STATE_PAUSED_BY_REQUEST:
+ Log.d("GODOT", "DOWNLOAD STATE: PAUSED BY USER");
+ paused = true;
+ indeterminate = false;
+ break;
+ case IDownloaderClient.STATE_PAUSED_ROAMING:
+ case IDownloaderClient.STATE_PAUSED_SDCARD_UNAVAILABLE:
+ Log.d("GODOT", "DOWNLOAD STATE: PAUSED BY ROAMING OR SDCARD UNAVAILABLE");
+ paused = true;
+ indeterminate = false;
+ break;
+ case IDownloaderClient.STATE_COMPLETED:
+ Log.d("GODOT", "DOWNLOAD STATE: COMPLETED");
+ showDashboard = false;
+ paused = false;
+ indeterminate = false;
+ // validateXAPKZipFiles();
+ initializeGodot();
+ return;
+ default:
+ Log.d("GODOT", "DOWNLOAD STATE: DEFAULT");
+ paused = true;
+ indeterminate = true;
+ showDashboard = true;
+ }
+ int newDashboardVisibility = showDashboard ? View.VISIBLE : View.GONE;
+ if (mDashboard.getVisibility() != newDashboardVisibility) {
+ mDashboard.setVisibility(newDashboardVisibility);
+ }
+ int cellMessageVisibility = showCellMessage ? View.VISIBLE : View.GONE;
+ if (mCellMessage.getVisibility() != cellMessageVisibility) {
+ mCellMessage.setVisibility(cellMessageVisibility);
+ }
+ mPB.setIndeterminate(indeterminate);
+ setButtonPausedState(paused);
+ }
@Override
public void onDownloadProgress(DownloadProgressInfo progress) {
mAverageSpeed.setText(getString(com.godot.game.R.string.kilobytes_per_second,
- Helpers.getSpeedString(progress.mCurrentSpeed)));
- mTimeRemaining.setText(getString(com.godot.game.R.string.time_remaining,
- Helpers.getTimeRemaining(progress.mTimeRemaining)));
-
- progress.mOverallTotal = progress.mOverallTotal;
- mPB.setMax((int) (progress.mOverallTotal >> 8));
- mPB.setProgress((int) (progress.mOverallProgress >> 8));
- mProgressPercent.setText(Long.toString(progress.mOverallProgress
- * 100 /
- progress.mOverallTotal) + "%");
- mProgressFraction.setText(Helpers.getDownloadProgressString
- (progress.mOverallProgress,
- progress.mOverallTotal));
-
+ Helpers.getSpeedString(progress.mCurrentSpeed)));
+ mTimeRemaining.setText(getString(com.godot.game.R.string.time_remaining,
+ Helpers.getTimeRemaining(progress.mTimeRemaining)));
+
+ progress.mOverallTotal = progress.mOverallTotal;
+ mPB.setMax((int)(progress.mOverallTotal >> 8));
+ mPB.setProgress((int)(progress.mOverallProgress >> 8));
+ mProgressPercent.setText(Long.toString(progress.mOverallProgress * 100 /
+ progress.mOverallTotal) +
+ "%");
+ mProgressFraction.setText(Helpers.getDownloadProgressString(progress.mOverallProgress,
+ progress.mOverallTotal));
}
-
}
diff --git a/platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java b/platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java
index 2c668dd586..568c7a4140 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java
@@ -46,14 +46,14 @@ import android.util.Log;
*/
public class GodotDownloaderAlarmReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.d("GODOT", "Alarma recivida");
- try {
- DownloaderClientMarshaller.startDownloadServiceIfRequired(context, intent, GodotDownloaderService.class);
- } catch (NameNotFoundException e) {
- e.printStackTrace();
- Log.d("GODOT", "Exception: " + e.getClass().getName() + ":" + e.getMessage());
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.d("GODOT", "Alarma recivida");
+ try {
+ DownloaderClientMarshaller.startDownloadServiceIfRequired(context, intent, GodotDownloaderService.class);
+ } catch (NameNotFoundException e) {
+ e.printStackTrace();
+ Log.d("GODOT", "Exception: " + e.getClass().getName() + ":" + e.getMessage());
+ }
}
- }
}
diff --git a/platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java b/platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java
index 97ba7826fb..b8b3b925c5 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java
@@ -40,46 +40,45 @@ import com.google.android.vending.expansion.downloader.impl.DownloaderService;
* DownloaderService from the Downloader library.
*/
public class GodotDownloaderService extends DownloaderService {
- // stuff for LVL -- MODIFY FOR YOUR APPLICATION!
- private static final String BASE64_PUBLIC_KEY = "REPLACE THIS WITH YOUR PUBLIC KEY";
- // used by the preference obfuscater
- private static final byte[] SALT = new byte[] {
- 1, 43, -12, -1, 54, 98,
- -100, -12, 43, 2, -8, -4, 9, 5, -106, -108, -33, 45, -1, 84
- };
+ // stuff for LVL -- MODIFY FOR YOUR APPLICATION!
+ private static final String BASE64_PUBLIC_KEY = "REPLACE THIS WITH YOUR PUBLIC KEY";
+ // used by the preference obfuscater
+ private static final byte[] SALT = new byte[] {
+ 1, 43, -12, -1, 54, 98,
+ -100, -12, 43, 2, -8, -4, 9, 5, -106, -108, -33, 45, -1, 84
+ };
- /**
+ /**
* This public key comes from your Android Market publisher account, and it
* used by the LVL to validate responses from Market on your behalf.
*/
- @Override
- public String getPublicKey() {
- SharedPreferences prefs = getApplicationContext().getSharedPreferences("app_data_keys", Context.MODE_PRIVATE);
- Log.d("GODOT", "getting public key:" + prefs.getString("store_public_key", null));
- return prefs.getString("store_public_key", null);
-
- //return BASE64_PUBLIC_KEY;
- }
+ @Override
+ public String getPublicKey() {
+ SharedPreferences prefs = getApplicationContext().getSharedPreferences("app_data_keys", Context.MODE_PRIVATE);
+ Log.d("GODOT", "getting public key:" + prefs.getString("store_public_key", null));
+ return prefs.getString("store_public_key", null);
- /**
+ //return BASE64_PUBLIC_KEY;
+ }
+
+ /**
* This is used by the preference obfuscater to make sure that your
* obfuscated preferences are different than the ones used by other
* applications.
*/
- @Override
- public byte[] getSALT() {
- return SALT;
- }
+ @Override
+ public byte[] getSALT() {
+ return SALT;
+ }
- /**
+ /**
* Fill this in with the class name for your alarm receiver. We do this
* because receivers must be unique across all of Android (it's a good idea
* to make sure that your receiver is in your unique package)
*/
- @Override
- public String getAlarmReceiverClassName() {
- Log.d("GODOT", "getAlarmReceiverClassName()");
- return GodotDownloaderAlarmReceiver.class.getName();
- }
-
+ @Override
+ public String getAlarmReceiverClassName() {
+ Log.d("GODOT", "getAlarmReceiverClassName()");
+ return GodotDownloaderAlarmReceiver.class.getName();
+ }
}
diff --git a/platform/android/java/src/org/godotengine/godot/GodotIO.java b/platform/android/java/src/org/godotengine/godot/GodotIO.java
index 989fd2b609..12a2467a29 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotIO.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotIO.java
@@ -56,7 +56,6 @@ import org.godotengine.godot.input.*;
public class GodotIO {
-
AssetManager am;
Godot activity;
GodotEditText edit;
@@ -64,35 +63,32 @@ public class GodotIO {
Context applicationContext;
MediaPlayer mediaPlayer;
- final int SCREEN_LANDSCAPE=0;
- final int SCREEN_PORTRAIT=1;
- final int SCREEN_REVERSE_LANDSCAPE=2;
- final int SCREEN_REVERSE_PORTRAIT=3;
- final int SCREEN_SENSOR_LANDSCAPE=4;
- final int SCREEN_SENSOR_PORTRAIT=5;
- final int SCREEN_SENSOR=6;
+ final int SCREEN_LANDSCAPE = 0;
+ final int SCREEN_PORTRAIT = 1;
+ final int SCREEN_REVERSE_LANDSCAPE = 2;
+ final int SCREEN_REVERSE_PORTRAIT = 3;
+ final int SCREEN_SENSOR_LANDSCAPE = 4;
+ final int SCREEN_SENSOR_PORTRAIT = 5;
+ final int SCREEN_SENSOR = 6;
/////////////////////////
/// FILES
/////////////////////////
- public int last_file_id=1;
+ public int last_file_id = 1;
class AssetData {
-
- public boolean eof=false;
+ public boolean eof = false;
public String path;
public InputStream is;
public int len;
public int pos;
}
+ HashMap<Integer, AssetData> streams;
- HashMap<Integer,AssetData> streams;
-
-
- public int file_open(String path,boolean write) {
+ public int file_open(String path, boolean write) {
//System.out.printf("file_open: Attempt to Open %s\n",path);
@@ -100,7 +96,6 @@ public class GodotIO {
if (write)
return -1;
-
AssetData ad = new AssetData();
try {
@@ -113,76 +108,73 @@ public class GodotIO {
}
try {
- ad.len=ad.is.available();
+ ad.len = ad.is.available();
} catch (Exception e) {
- System.out.printf("Exception availabling on file_open: %s\n",path);
+ System.out.printf("Exception availabling on file_open: %s\n", path);
return -1;
}
- ad.path=path;
- ad.pos=0;
+ ad.path = path;
+ ad.pos = 0;
++last_file_id;
- streams.put(last_file_id,ad);
+ streams.put(last_file_id, ad);
return last_file_id;
}
public int file_get_size(int id) {
if (!streams.containsKey(id)) {
- System.out.printf("file_get_size: Invalid file id: %d\n",id);
+ System.out.printf("file_get_size: Invalid file id: %d\n", id);
return -1;
}
return streams.get(id).len;
-
}
- public void file_seek(int id,int bytes) {
+ public void file_seek(int id, int bytes) {
if (!streams.containsKey(id)) {
- System.out.printf("file_get_size: Invalid file id: %d\n",id);
+ System.out.printf("file_get_size: Invalid file id: %d\n", id);
return;
}
//seek sucks
AssetData ad = streams.get(id);
- if (bytes>ad.len)
- bytes=ad.len;
- if (bytes<0)
- bytes=0;
+ if (bytes > ad.len)
+ bytes = ad.len;
+ if (bytes < 0)
+ bytes = 0;
try {
- if (bytes > (int)ad.pos) {
- int todo=bytes-(int)ad.pos;
- while(todo>0) {
- todo-=ad.is.skip(todo);
- }
- ad.pos=bytes;
- } else if (bytes<(int)ad.pos) {
+ if (bytes > (int)ad.pos) {
+ int todo = bytes - (int)ad.pos;
+ while (todo > 0) {
+ todo -= ad.is.skip(todo);
+ }
+ ad.pos = bytes;
+ } else if (bytes < (int)ad.pos) {
- ad.is=am.open(ad.path);
+ ad.is = am.open(ad.path);
- ad.pos=bytes;
- int todo=bytes;
- while(todo>0) {
- todo-=ad.is.skip(todo);
+ ad.pos = bytes;
+ int todo = bytes;
+ while (todo > 0) {
+ todo -= ad.is.skip(todo);
+ }
}
- }
- ad.eof=false;
+ ad.eof = false;
} catch (IOException e) {
- System.out.printf("Exception on file_seek: %s\n",e);
+ System.out.printf("Exception on file_seek: %s\n", e);
return;
}
-
-
}
public int file_tell(int id) {
if (!streams.containsKey(id)) {
- System.out.printf("file_read: Can't tell eof for invalid file id: %d\n",id);
+ System.out.printf("file_read: Can't tell eof for invalid file id: %d\n", id);
return 0;
}
@@ -192,7 +184,7 @@ public class GodotIO {
public boolean file_eof(int id) {
if (!streams.containsKey(id)) {
- System.out.printf("file_read: Can't check eof for invalid file id: %d\n",id);
+ System.out.printf("file_read: Can't check eof for invalid file id: %d\n", id);
return false;
}
@@ -203,73 +195,65 @@ public class GodotIO {
public byte[] file_read(int id, int bytes) {
if (!streams.containsKey(id)) {
- System.out.printf("file_read: Can't read invalid file id: %d\n",id);
+ System.out.printf("file_read: Can't read invalid file id: %d\n", id);
return new byte[0];
}
-
AssetData ad = streams.get(id);
if (ad.pos + bytes > ad.len) {
- bytes=ad.len-ad.pos;
- ad.eof=true;
+ bytes = ad.len - ad.pos;
+ ad.eof = true;
}
-
- if (bytes==0) {
+ if (bytes == 0) {
return new byte[0];
}
-
-
- byte[] buf1=new byte[bytes];
- int r=0;
+ byte[] buf1 = new byte[bytes];
+ int r = 0;
try {
r = ad.is.read(buf1);
} catch (IOException e) {
- System.out.printf("Exception on file_read: %s\n",e);
+ System.out.printf("Exception on file_read: %s\n", e);
return new byte[bytes];
}
- if (r==0) {
+ if (r == 0) {
return new byte[0];
}
- ad.pos+=r;
+ ad.pos += r;
- if (r<bytes) {
+ if (r < bytes) {
- byte[] buf2=new byte[r];
- for(int i=0;i<r;i++)
- buf2[i]=buf1[i];
+ byte[] buf2 = new byte[r];
+ for (int i = 0; i < r; i++)
+ buf2[i] = buf1[i];
return buf2;
} else {
return buf1;
}
-
}
public void file_close(int id) {
if (!streams.containsKey(id)) {
- System.out.printf("file_close: Can't close invalid file id: %d\n",id);
+ System.out.printf("file_close: Can't close invalid file id: %d\n", id);
return;
}
streams.remove(id);
-
}
-
/////////////////////////
/// DIRECTORIES
/////////////////////////
-
class AssetDir {
public String[] files;
@@ -277,49 +261,48 @@ public class GodotIO {
public String path;
}
- public int last_dir_id=1;
+ public int last_dir_id = 1;
- HashMap<Integer,AssetDir> dirs;
+ HashMap<Integer, AssetDir> dirs;
public int dir_open(String path) {
AssetDir ad = new AssetDir();
- ad.current=0;
- ad.path=path;
+ ad.current = 0;
+ ad.path = path;
try {
ad.files = am.list(path);
// no way to find path is directory or file exactly.
// but if ad.files.length==0, then it's an empty directory or file.
- if (ad.files.length==0) {
+ if (ad.files.length == 0) {
return -1;
}
} catch (IOException e) {
- System.out.printf("Exception on dir_open: %s\n",e);
+ System.out.printf("Exception on dir_open: %s\n", e);
return -1;
}
//System.out.printf("Opened dir: %s\n",path);
++last_dir_id;
- dirs.put(last_dir_id,ad);
+ dirs.put(last_dir_id, ad);
return last_dir_id;
-
}
public boolean dir_is_dir(int id) {
if (!dirs.containsKey(id)) {
- System.out.printf("dir_next: invalid dir id: %d\n",id);
+ System.out.printf("dir_next: invalid dir id: %d\n", id);
return false;
}
AssetDir ad = dirs.get(id);
//System.out.printf("go next: %d,%d\n",ad.current,ad.files.length);
int idx = ad.current;
- if (idx>0)
+ if (idx > 0)
idx--;
- if (idx>=ad.files.length)
+ if (idx >= ad.files.length)
return false;
String fname = ad.files[idx];
@@ -327,7 +310,7 @@ public class GodotIO {
if (ad.path.equals(""))
am.open(fname);
else
- am.open(ad.path+"/"+fname);
+ am.open(ad.path + "/" + fname);
return false;
} catch (Exception e) {
return true;
@@ -337,46 +320,41 @@ public class GodotIO {
public String dir_next(int id) {
if (!dirs.containsKey(id)) {
- System.out.printf("dir_next: invalid dir id: %d\n",id);
+ System.out.printf("dir_next: invalid dir id: %d\n", id);
return "";
}
AssetDir ad = dirs.get(id);
//System.out.printf("go next: %d,%d\n",ad.current,ad.files.length);
- if (ad.current>=ad.files.length) {
+ if (ad.current >= ad.files.length) {
ad.current++;
return "";
}
String r = ad.files[ad.current];
ad.current++;
return r;
-
}
public void dir_close(int id) {
if (!dirs.containsKey(id)) {
- System.out.printf("dir_close: invalid dir id: %d\n",id);
+ System.out.printf("dir_close: invalid dir id: %d\n", id);
return;
}
dirs.remove(id);
}
-
-
GodotIO(Godot p_activity) {
- am=p_activity.getAssets();
- activity=p_activity;
- streams=new HashMap<Integer,AssetData>();
- dirs=new HashMap<Integer,AssetDir>();
+ am = p_activity.getAssets();
+ activity = p_activity;
+ streams = new HashMap<Integer, AssetData>();
+ dirs = new HashMap<Integer, AssetDir>();
applicationContext = activity.getApplicationContext();
-
}
-
/////////////////////////
// AUDIO
/////////////////////////
@@ -400,7 +378,7 @@ public class GodotIO {
desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize);
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
- channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);
+ channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);
audioStartThread();
@@ -412,10 +390,10 @@ public class GodotIO {
public void audioStartThread() {
mAudioThread = new Thread(new Runnable() {
- public void run() {
- mAudioTrack.play();
- GodotLib.audio();
- }
+ public void run() {
+ mAudioTrack.play();
+ GodotLib.audio();
+ }
});
// I'd take REALTIME if I could get it!
@@ -424,15 +402,15 @@ public class GodotIO {
}
public void audioWriteShortBuffer(short[] buffer) {
- for (int i = 0; i < buffer.length; ) {
+ for (int i = 0; i < buffer.length;) {
int result = mAudioTrack.write(buffer, i, buffer.length - i);
if (result > 0) {
i += result;
} else if (result == 0) {
try {
- Thread.sleep(1);
- } catch(InterruptedException e) {
- // Nom nom
+ Thread.sleep(1);
+ } catch (InterruptedException e) {
+ // Nom nom
}
} else {
Log.w("Godot", "Godot audio: error return from write(short)");
@@ -441,18 +419,16 @@ public class GodotIO {
}
}
-
-
public void audioQuit() {
if (mAudioThread != null) {
try {
mAudioThread.join();
- } catch(Exception e) {
+ } catch (Exception e) {
Log.v("Godot", "Problem stopping audio thread: " + e);
}
mAudioThread = null;
- //Log.v("Godot", "Finished waiting for audio thread");
+ //Log.v("Godot", "Finished waiting for audio thread");
}
if (mAudioTrack != null) {
@@ -473,20 +449,18 @@ public class GodotIO {
// MISCELLANEOUS OS IO
/////////////////////////
-
-
public int openURI(String p_uri) {
try {
Log.v("MyApp", "TRYING TO OPEN URI: " + p_uri);
String path = p_uri;
- String type="";
+ String type = "";
if (path.startsWith("/")) {
//absolute path to filesystem, prepend file://
- path="file://"+path;
+ path = "file://" + path;
if (p_uri.endsWith(".png") || p_uri.endsWith(".jpg") || p_uri.endsWith(".gif") || p_uri.endsWith(".webp")) {
- type="image/*";
+ type = "image/*";
}
}
@@ -531,7 +505,7 @@ public class GodotIO {
}
public void showKeyboard(String p_existing_text) {
- if(edit != null)
+ if (edit != null)
edit.showKeyboard(p_existing_text);
//InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
@@ -539,21 +513,21 @@ public class GodotIO {
};
public void hideKeyboard() {
- if(edit != null)
+ if (edit != null)
edit.hideKeyboard();
- InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
- View v = activity.getCurrentFocus();
- if (v != null) {
- inputMgr.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
- } else {
- inputMgr.hideSoftInputFromWindow(new View(activity).getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
- }
+ InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
+ View v = activity.getCurrentFocus();
+ if (v != null) {
+ inputMgr.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
+ } else {
+ inputMgr.hideSoftInputFromWindow(new View(activity).getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
+ }
};
public void setScreenOrientation(int p_orientation) {
- switch(p_orientation) {
+ switch (p_orientation) {
case SCREEN_LANDSCAPE: {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
@@ -576,16 +550,14 @@ public class GodotIO {
case SCREEN_SENSOR: {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
} break;
-
}
};
-
+
public void setEdit(GodotEditText _edit) {
edit = _edit;
}
- public void playVideo(String p_path)
- {
+ public void playVideo(String p_path) {
Uri filePath = Uri.parse(p_path);
mediaPlayer = new MediaPlayer();
@@ -594,11 +566,9 @@ public class GodotIO {
mediaPlayer.setDataSource(applicationContext, filePath);
mediaPlayer.prepare();
mediaPlayer.start();
+ } catch (IOException e) {
+ System.out.println("IOError while playing video");
}
- catch(IOException e)
- {
- System.out.println("IOError while playing video");
- }
}
public boolean isVideoPlaying() {
@@ -621,49 +591,47 @@ public class GodotIO {
}
}
-
- public static final int SYSTEM_DIR_DESKTOP=0;
- public static final int SYSTEM_DIR_DCIM=1;
- public static final int SYSTEM_DIR_DOCUMENTS=2;
- public static final int SYSTEM_DIR_DOWNLOADS=3;
- public static final int SYSTEM_DIR_MOVIES=4;
- public static final int SYSTEM_DIR_MUSIC=5;
- public static final int SYSTEM_DIR_PICTURES=6;
- public static final int SYSTEM_DIR_RINGTONES=7;
-
+ public static final int SYSTEM_DIR_DESKTOP = 0;
+ public static final int SYSTEM_DIR_DCIM = 1;
+ public static final int SYSTEM_DIR_DOCUMENTS = 2;
+ public static final int SYSTEM_DIR_DOWNLOADS = 3;
+ public static final int SYSTEM_DIR_MOVIES = 4;
+ public static final int SYSTEM_DIR_MUSIC = 5;
+ public static final int SYSTEM_DIR_PICTURES = 6;
+ public static final int SYSTEM_DIR_RINGTONES = 7;
public String getSystemDir(int idx) {
- String what="";
- switch(idx) {
+ String what = "";
+ switch (idx) {
case SYSTEM_DIR_DESKTOP: {
//what=Environment.DIRECTORY_DOCUMENTS;
- what=Environment.DIRECTORY_DOWNLOADS;
+ what = Environment.DIRECTORY_DOWNLOADS;
} break;
case SYSTEM_DIR_DCIM: {
- what=Environment.DIRECTORY_DCIM;
+ what = Environment.DIRECTORY_DCIM;
} break;
case SYSTEM_DIR_DOCUMENTS: {
- what=Environment.DIRECTORY_DOWNLOADS;
+ what = Environment.DIRECTORY_DOWNLOADS;
//what=Environment.DIRECTORY_DOCUMENTS;
} break;
case SYSTEM_DIR_DOWNLOADS: {
- what=Environment.DIRECTORY_DOWNLOADS;
+ what = Environment.DIRECTORY_DOWNLOADS;
} break;
case SYSTEM_DIR_MOVIES: {
- what=Environment.DIRECTORY_MOVIES;
+ what = Environment.DIRECTORY_MOVIES;
} break;
case SYSTEM_DIR_MUSIC: {
- what=Environment.DIRECTORY_MUSIC;
+ what = Environment.DIRECTORY_MUSIC;
} break;
case SYSTEM_DIR_PICTURES: {
- what=Environment.DIRECTORY_PICTURES;
+ what = Environment.DIRECTORY_PICTURES;
} break;
case SYSTEM_DIR_RINGTONES: {
- what=Environment.DIRECTORY_RINGTONES;
+ what = Environment.DIRECTORY_RINGTONES;
} break;
}
@@ -676,10 +644,9 @@ public class GodotIO {
protected static final String PREFS_FILE = "device_id.xml";
protected static final String PREFS_DEVICE_ID = "device_id";
- public static String unique_id="";
+ public static String unique_id = "";
public String getUniqueID() {
- return unique_id;
+ return unique_id;
}
-
}
diff --git a/platform/android/java/src/org/godotengine/godot/GodotLib.java b/platform/android/java/src/org/godotengine/godot/GodotLib.java
index 6b84ad6555..873d30eb34 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotLib.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotLib.java
@@ -33,43 +33,41 @@ package org.godotengine.godot;
public class GodotLib {
+ public static GodotIO io;
- public static GodotIO io;
+ static {
+ System.loadLibrary("godot_android");
+ }
- static {
- System.loadLibrary("godot_android");
- }
-
- /**
+ /**
* @param width the current view width
* @param height the current view height
*/
- public static native void initialize(Godot p_instance,boolean need_reload_hook,Object p_asset_manager, boolean use_apk_expansion);
- public static native void setup(String[] p_cmdline);
- public static native void resize(int width, int height,boolean reload);
- public static native void newcontext(boolean p_32_bits);
- public static native void back();
- public static native void step();
- public static native void touch(int what,int pointer,int howmany, int[] arr);
- public static native void accelerometer(float x, float y, float z);
- public static native void gravity(float x, float y, float z);
- public static native void magnetometer(float x, float y, float z);
- public static native void gyroscope(float x, float y, float z);
- public static native void key(int p_scancode, int p_unicode_char, boolean p_pressed);
- public static native void joybutton(int p_device, int p_but, boolean p_pressed);
- public static native void joyaxis(int p_device, int p_axis, float p_value);
- public static native void joyhat(int p_device, int p_hat_x, int p_hat_y);
- public static native void joyconnectionchanged(int p_device, boolean p_connected, String p_name);
- public static native void focusin();
- public static native void focusout();
- public static native void audio();
- public static native void singleton(String p_name,Object p_object);
- public static native void method(String p_sname,String p_name,String p_ret,String[] p_params);
- public static native String getGlobal(String p_key);
+ public static native void initialize(Godot p_instance, boolean need_reload_hook, Object p_asset_manager, boolean use_apk_expansion);
+ public static native void setup(String[] p_cmdline);
+ public static native void resize(int width, int height, boolean reload);
+ public static native void newcontext(boolean p_32_bits);
+ public static native void back();
+ public static native void step();
+ public static native void touch(int what, int pointer, int howmany, int[] arr);
+ public static native void accelerometer(float x, float y, float z);
+ public static native void gravity(float x, float y, float z);
+ public static native void magnetometer(float x, float y, float z);
+ public static native void gyroscope(float x, float y, float z);
+ public static native void key(int p_scancode, int p_unicode_char, boolean p_pressed);
+ public static native void joybutton(int p_device, int p_but, boolean p_pressed);
+ public static native void joyaxis(int p_device, int p_axis, float p_value);
+ public static native void joyhat(int p_device, int p_hat_x, int p_hat_y);
+ public static native void joyconnectionchanged(int p_device, boolean p_connected, String p_name);
+ public static native void focusin();
+ public static native void focusout();
+ public static native void audio();
+ public static native void singleton(String p_name, Object p_object);
+ public static native void method(String p_sname, String p_name, String p_ret, String[] p_params);
+ public static native String getGlobal(String p_key);
public static native void callobject(int p_ID, String p_method, Object[] p_params);
public static native void calldeferred(int p_ID, String p_method, Object[] p_params);
public static native void setVirtualKeyboardHeight(int p_height);
-
}
diff --git a/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java b/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java
index 8fe79fdfc7..61d10ed9e4 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java
@@ -40,7 +40,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-
public class GodotPaymentV3 extends Godot.SingletonBase {
private Godot activity;
@@ -67,8 +66,8 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
public GodotPaymentV3(Activity p_activity) {
- registerClass("GodotPayments", new String[]{"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix", "setTransactionId", "getSignature", "consumeUnconsumedPurchases", "requestPurchased", "setAutoConsume", "consume", "querySkuDetails"});
- activity = (Godot) p_activity;
+ registerClass("GodotPayments", new String[] { "purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix", "setTransactionId", "getSignature", "consumeUnconsumedPurchases", "requestPurchased", "setAutoConsume", "consume", "querySkuDetails" });
+ activity = (Godot)p_activity;
mPaymentManager = activity.getPaymentsManager();
mPaymentManager.setBaseSingleton(this);
}
@@ -89,32 +88,32 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
}
public void callbackSuccess(String ticket, String signature, String sku) {
- GodotLib.calldeferred(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature, sku});
+ GodotLib.calldeferred(purchaseCallbackId, "purchase_success", new Object[] { ticket, signature, sku });
}
public void callbackSuccessProductMassConsumed(String ticket, String signature, String sku) {
Log.d(this.getClass().getName(), "callbackSuccessProductMassConsumed > " + ticket + "," + signature + "," + sku);
- GodotLib.calldeferred(purchaseCallbackId, "consume_success", new Object[]{ticket, signature, sku});
+ GodotLib.calldeferred(purchaseCallbackId, "consume_success", new Object[] { ticket, signature, sku });
}
public void callbackSuccessNoUnconsumedPurchases() {
- GodotLib.calldeferred(purchaseCallbackId, "consume_not_required", new Object[]{});
+ GodotLib.calldeferred(purchaseCallbackId, "consume_not_required", new Object[] {});
}
public void callbackFailConsume() {
- GodotLib.calldeferred(purchaseCallbackId, "consume_fail", new Object[]{});
+ GodotLib.calldeferred(purchaseCallbackId, "consume_fail", new Object[] {});
}
public void callbackFail() {
- GodotLib.calldeferred(purchaseCallbackId, "purchase_fail", new Object[]{});
+ GodotLib.calldeferred(purchaseCallbackId, "purchase_fail", new Object[] {});
}
public void callbackCancel() {
- GodotLib.calldeferred(purchaseCallbackId, "purchase_cancel", new Object[]{});
+ GodotLib.calldeferred(purchaseCallbackId, "purchase_cancel", new Object[] {});
}
public void callbackAlreadyOwned(String sku) {
- GodotLib.calldeferred(purchaseCallbackId, "purchase_owned", new Object[]{sku});
+ GodotLib.calldeferred(purchaseCallbackId, "purchase_owned", new Object[] { sku });
}
public int getPurchaseCallbackId() {
@@ -161,7 +160,7 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
// callback for requestPurchased()
public void callbackPurchased(String receipt, String signature, String sku) {
- GodotLib.calldeferred(purchaseCallbackId, "has_purchased", new Object[]{receipt, signature, sku});
+ GodotLib.calldeferred(purchaseCallbackId, "has_purchased", new Object[] { receipt, signature, sku });
}
// consume item automatically after purchase. default is true.
@@ -210,10 +209,10 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
}
public void completeSkuDetail() {
- GodotLib.calldeferred(purchaseCallbackId, "sku_details_complete", new Object[]{mSkuDetails});
+ GodotLib.calldeferred(purchaseCallbackId, "sku_details_complete", new Object[] { mSkuDetails });
}
public void errorSkuDetail(String errorMessage) {
- GodotLib.calldeferred(purchaseCallbackId, "sku_details_error", new Object[]{errorMessage});
+ GodotLib.calldeferred(purchaseCallbackId, "sku_details_error", new Object[] { errorMessage });
}
}
diff --git a/platform/android/java/src/org/godotengine/godot/GodotView.java b/platform/android/java/src/org/godotengine/godot/GodotView.java
index b807b952d4..b762aa021a 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotView.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotView.java
@@ -77,20 +77,19 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
private static Context ctx;
private static GodotIO io;
- private static boolean firsttime=true;
- private static boolean use_gl3=false;
- private static boolean use_32=false;
+ private static boolean firsttime = true;
+ private static boolean use_gl3 = false;
+ private static boolean use_32 = false;
private Godot activity;
-
private InputManagerCompat mInputManager;
- public GodotView(Context context,GodotIO p_io,boolean p_use_gl3, boolean p_use_32_bits, Godot p_activity) {
+ public GodotView(Context context, GodotIO p_io, boolean p_use_gl3, boolean p_use_32_bits, Godot p_activity) {
super(context);
- ctx=context;
- io=p_io;
- use_gl3=p_use_gl3;
- use_32=p_use_32_bits;
+ ctx = context;
+ io = p_io;
+ use_gl3 = p_use_gl3;
+ use_32 = p_use_32_bits;
activity = p_activity;
@@ -101,14 +100,15 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
mInputManager = InputManagerCompat.Factory.getInputManager(this.getContext());
mInputManager.registerInputDeviceListener(this, null);
init(false, 16, 0);
- }
+ }
- public GodotView(Context context, boolean translucent, int depth, int stencil) {
+ public GodotView(Context context, boolean translucent, int depth, int stencil) {
super(context);
init(translucent, depth, stencil);
- }
+ }
- @Override public boolean onTouchEvent (MotionEvent event) {
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
return activity.gotTouchEvent(event);
};
@@ -196,16 +196,17 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
ArrayList<joystick> joy_devices = new ArrayList<joystick>();
private int find_joy_device(int device_id) {
- for (int i=0; i<joy_devices.size(); i++) {
+ for (int i = 0; i < joy_devices.size(); i++) {
if (joy_devices.get(i).device_id == device_id) {
- return i;
+ return i;
}
}
onInputDeviceAdded(device_id);
return joy_devices.size() - 1;
}
- @Override public void onInputDeviceAdded(int deviceId) {
+ @Override
+ public void onInputDeviceAdded(int deviceId) {
joystick joy = new joystick();
joy.device_id = deviceId;
final int id = joy_devices.size();
@@ -219,8 +220,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
for (InputDevice.MotionRange range : ranges) {
if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {
joy.hats.add(range);
- }
- else {
+ } else {
joy.axes.add(range);
}
}
@@ -231,9 +231,10 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
GodotLib.joyconnectionchanged(id, true, name);
}
});
- }
+ }
- @Override public void onInputDeviceRemoved(int deviceId) {
+ @Override
+ public void onInputDeviceRemoved(int deviceId) {
final int id = find_joy_device(deviceId);
joy_devices.remove(id);
queueEvent(new Runnable() {
@@ -244,10 +245,11 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
});
}
- @Override public void onInputDeviceChanged(int deviceId) {
-
+ @Override
+ public void onInputDeviceChanged(int deviceId) {
}
- @Override public boolean onKeyUp(final int keyCode, KeyEvent event) {
+ @Override
+ public boolean onKeyUp(final int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
return true;
@@ -282,7 +284,8 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
return super.onKeyUp(keyCode, event);
};
- @Override public boolean onKeyDown(final int keyCode, KeyEvent event) {
+ @Override
+ public boolean onKeyDown(final int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
activity.onBackPressed();
@@ -326,7 +329,8 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
return super.onKeyDown(keyCode, event);
}
- @Override public boolean onGenericMotionEvent(MotionEvent event) {
+ @Override
+ public boolean onGenericMotionEvent(MotionEvent event) {
if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE) {
@@ -335,7 +339,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
for (int i = 0; i < joy.axes.size(); i++) {
InputDevice.MotionRange range = joy.axes.get(i);
- final float value = (event.getAxisValue(range.getAxis()) - range.getMin() ) / range.getRange() * 2.0f - 1.0f;
+ final float value = (event.getAxisValue(range.getAxis()) - range.getMin()) / range.getRange() * 2.0f - 1.0f;
//Log.e(TAG, String.format("axis event: %d, value %f", i, value));
final int idx = i;
queueEvent(new Runnable() {
@@ -346,9 +350,9 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
});
}
- for (int i = 0; i < joy.hats.size(); i+=2) {
+ for (int i = 0; i < joy.hats.size(); i += 2) {
final int hatX = Math.round(event.getAxisValue(joy.hats.get(i).getAxis()));
- final int hatY = Math.round(event.getAxisValue(joy.hats.get(i+1).getAxis()));
+ final int hatY = Math.round(event.getAxisValue(joy.hats.get(i + 1).getAxis()));
//Log.e(TAG, String.format("HAT EVENT %d, %d", hatX, hatY));
queueEvent(new Runnable() {
@Override
@@ -363,8 +367,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
return super.onGenericMotionEvent(event);
};
-
- private void init(boolean translucent, int depth, int stencil) {
+ private void init(boolean translucent, int depth, int stencil) {
this.setFocusableInTouchMode(true);
/* By default, GLSurfaceView() creates a RGB_565 opaque surface.
@@ -388,14 +391,14 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
*/
if (use_32) {
- setEGLConfigChooser( translucent ?
- new FallbackConfigChooser(8, 8, 8, 8, 24, stencil, new ConfigChooser(8, 8, 8, 8, 16, stencil)) :
- new FallbackConfigChooser(8, 8, 8, 8, 24, stencil, new ConfigChooser(5, 6, 5, 0, 16, stencil)) );
+ setEGLConfigChooser(translucent ?
+ new FallbackConfigChooser(8, 8, 8, 8, 24, stencil, new ConfigChooser(8, 8, 8, 8, 16, stencil)) :
+ new FallbackConfigChooser(8, 8, 8, 8, 24, stencil, new ConfigChooser(5, 6, 5, 0, 16, stencil)));
} else {
- setEGLConfigChooser( translucent ?
- new ConfigChooser(8, 8, 8, 8, 16, stencil) :
- new ConfigChooser(5, 6, 5, 0, 16, stencil) );
+ setEGLConfigChooser(translucent ?
+ new ConfigChooser(8, 8, 8, 8, 16, stencil) :
+ new ConfigChooser(5, 6, 5, 0, 16, stencil));
}
/* Set the renderer responsible for frame rendering */
@@ -403,33 +406,33 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
}
private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
- private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
- public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
- if (use_gl3)
- Log.w(TAG, "creating OpenGL ES 3.0 context :");
- else
- Log.w(TAG, "creating OpenGL ES 2.0 context :");
-
- checkEglError("Before eglCreateContext", egl);
- int[] attrib_list2 = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
- int[] attrib_list3 = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL10.EGL_NONE };
- EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, use_gl3?attrib_list3:attrib_list2);
- checkEglError("After eglCreateContext", egl);
- return context;
- }
+ private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+ public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
+ if (use_gl3)
+ Log.w(TAG, "creating OpenGL ES 3.0 context :");
+ else
+ Log.w(TAG, "creating OpenGL ES 2.0 context :");
+
+ checkEglError("Before eglCreateContext", egl);
+ int[] attrib_list2 = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
+ int[] attrib_list3 = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL10.EGL_NONE };
+ EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, use_gl3 ? attrib_list3 : attrib_list2);
+ checkEglError("After eglCreateContext", egl);
+ return context;
+ }
- public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
- egl.eglDestroyContext(display, context);
+ public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
+ egl.eglDestroyContext(display, context);
+ }
}
- }
- private static void checkEglError(String prompt, EGL10 egl) {
- int error;
- while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
- Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));
+ private static void checkEglError(String prompt, EGL10 egl) {
+ int error;
+ while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
+ Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));
+ }
}
- }
- /* Fallback if 32bit View is not supported*/
+ /* Fallback if 32bit View is not supported*/
private static class FallbackConfigChooser extends ConfigChooser {
private ConfigChooser fallback;
@@ -438,17 +441,17 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
this.fallback = fallback;
}
- @Override
+ @Override
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs) {
EGLConfig ec = super.chooseConfig(egl, display, configs);
if (ec == null) {
- Log.w(TAG, "Trying ConfigChooser fallback");
- ec = fallback.chooseConfig(egl, display, configs);
- use_32=false;
+ Log.w(TAG, "Trying ConfigChooser fallback");
+ ec = fallback.chooseConfig(egl, display, configs);
+ use_32 = false;
}
return ec;
- }
- }
+ }
+ }
private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
@@ -467,46 +470,46 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
*/
private static int EGL_OPENGL_ES2_BIT = 4;
private static int[] s_configAttribs2 =
- {
- EGL10.EGL_RED_SIZE, 4,
- EGL10.EGL_GREEN_SIZE, 4,
- EGL10.EGL_BLUE_SIZE, 4,
- // EGL10.EGL_DEPTH_SIZE, 16,
- // EGL10.EGL_STENCIL_SIZE, EGL10.EGL_DONT_CARE,
- EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL10.EGL_NONE
- };
+ {
+ EGL10.EGL_RED_SIZE, 4,
+ EGL10.EGL_GREEN_SIZE, 4,
+ EGL10.EGL_BLUE_SIZE, 4,
+ // EGL10.EGL_DEPTH_SIZE, 16,
+ // EGL10.EGL_STENCIL_SIZE, EGL10.EGL_DONT_CARE,
+ EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL10.EGL_NONE
+ };
private static int[] s_configAttribs3 =
- {
- EGL10.EGL_RED_SIZE, 4,
- EGL10.EGL_GREEN_SIZE, 4,
- EGL10.EGL_BLUE_SIZE, 4,
- // EGL10.EGL_DEPTH_SIZE, 16,
- // EGL10.EGL_STENCIL_SIZE, EGL10.EGL_DONT_CARE,
- EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, //apparently there is no EGL_OPENGL_ES3_BIT
- EGL10.EGL_NONE
- };
+ {
+ EGL10.EGL_RED_SIZE, 4,
+ EGL10.EGL_GREEN_SIZE, 4,
+ EGL10.EGL_BLUE_SIZE, 4,
+ // EGL10.EGL_DEPTH_SIZE, 16,
+ // EGL10.EGL_STENCIL_SIZE, EGL10.EGL_DONT_CARE,
+ EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, //apparently there is no EGL_OPENGL_ES3_BIT
+ EGL10.EGL_NONE
+ };
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
/* Get the number of minimally matching EGL configurations
*/
int[] num_config = new int[1];
- egl.eglChooseConfig(display, use_gl3?s_configAttribs3:s_configAttribs2, null, 0, num_config);
+ egl.eglChooseConfig(display, use_gl3 ? s_configAttribs3 : s_configAttribs2, null, 0, num_config);
int numConfigs = num_config[0];
if (numConfigs <= 0) {
- throw new IllegalArgumentException("No configs match configSpec");
+ throw new IllegalArgumentException("No configs match configSpec");
}
/* Allocate then read the array of minimally matching EGL configs
*/
EGLConfig[] configs = new EGLConfig[numConfigs];
- egl.eglChooseConfig(display, use_gl3?s_configAttribs3:s_configAttribs2, configs, numConfigs, num_config);
+ egl.eglChooseConfig(display, use_gl3 ? s_configAttribs3 : s_configAttribs2, configs, numConfigs, num_config);
if (DEBUG) {
- printConfigs(egl, display, configs);
+ printConfigs(egl, display, configs);
}
/* Now return the "best" one
*/
@@ -514,54 +517,54 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
}
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
- EGLConfig[] configs) {
- for(EGLConfig config : configs) {
- int d = findConfigAttrib(egl, display, config,
- EGL10.EGL_DEPTH_SIZE, 0);
- int s = findConfigAttrib(egl, display, config,
- EGL10.EGL_STENCIL_SIZE, 0);
-
- // We need at least mDepthSize and mStencilSize bits
- if (d < mDepthSize || s < mStencilSize)
- continue;
-
- // We want an *exact* match for red/green/blue/alpha
- int r = findConfigAttrib(egl, display, config,
- EGL10.EGL_RED_SIZE, 0);
- int g = findConfigAttrib(egl, display, config,
- EGL10.EGL_GREEN_SIZE, 0);
- int b = findConfigAttrib(egl, display, config,
- EGL10.EGL_BLUE_SIZE, 0);
- int a = findConfigAttrib(egl, display, config,
- EGL10.EGL_ALPHA_SIZE, 0);
-
- if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize)
- return config;
+ EGLConfig[] configs) {
+ for (EGLConfig config : configs) {
+ int d = findConfigAttrib(egl, display, config,
+ EGL10.EGL_DEPTH_SIZE, 0);
+ int s = findConfigAttrib(egl, display, config,
+ EGL10.EGL_STENCIL_SIZE, 0);
+
+ // We need at least mDepthSize and mStencilSize bits
+ if (d < mDepthSize || s < mStencilSize)
+ continue;
+
+ // We want an *exact* match for red/green/blue/alpha
+ int r = findConfigAttrib(egl, display, config,
+ EGL10.EGL_RED_SIZE, 0);
+ int g = findConfigAttrib(egl, display, config,
+ EGL10.EGL_GREEN_SIZE, 0);
+ int b = findConfigAttrib(egl, display, config,
+ EGL10.EGL_BLUE_SIZE, 0);
+ int a = findConfigAttrib(egl, display, config,
+ EGL10.EGL_ALPHA_SIZE, 0);
+
+ if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize)
+ return config;
}
return null;
}
private int findConfigAttrib(EGL10 egl, EGLDisplay display,
- EGLConfig config, int attribute, int defaultValue) {
+ EGLConfig config, int attribute, int defaultValue) {
if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
- return mValue[0];
+ return mValue[0];
}
return defaultValue;
}
private void printConfigs(EGL10 egl, EGLDisplay display,
- EGLConfig[] configs) {
+ EGLConfig[] configs) {
int numConfigs = configs.length;
Log.w(TAG, String.format("%d configurations", numConfigs));
for (int i = 0; i < numConfigs; i++) {
- Log.w(TAG, String.format("Configuration %d:\n", i));
- printConfig(egl, display, configs[i]);
+ Log.w(TAG, String.format("Configuration %d:\n", i));
+ printConfig(egl, display, configs[i]);
}
}
private void printConfig(EGL10 egl, EGLDisplay display,
- EGLConfig config) {
+ EGLConfig config) {
int[] attributes = {
EGL10.EGL_BUFFER_SIZE,
EGL10.EGL_ALPHA_SIZE,
@@ -634,14 +637,15 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
};
int[] value = new int[1];
for (int i = 0; i < attributes.length; i++) {
- int attribute = attributes[i];
- String name = names[i];
- if ( egl.eglGetConfigAttrib(display, config, attribute, value)) {
- Log.w(TAG, String.format(" %s: %d\n", name, value[0]));
- } else {
- // Log.w(TAG, String.format(" %s: failed\n", name));
- while (egl.eglGetError() != EGL10.EGL_SUCCESS);
- }
+ int attribute = attributes[i];
+ String name = names[i];
+ if (egl.eglGetConfigAttrib(display, config, attribute, value)) {
+ Log.w(TAG, String.format(" %s: %d\n", name, value[0]));
+ } else {
+ // Log.w(TAG, String.format(" %s: failed\n", name));
+ while (egl.eglGetError() != EGL10.EGL_SUCCESS)
+ ;
+ }
}
}
@@ -657,19 +661,18 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
private static class Renderer implements GLSurfaceView.Renderer {
-
public void onDrawFrame(GL10 gl) {
GodotLib.step();
- for(int i=0;i<Godot.singleton_count;i++) {
+ for (int i = 0; i < Godot.singleton_count; i++) {
Godot.singletons[i].onGLDrawFrame(gl);
}
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
- GodotLib.resize(width, height,!firsttime);
- firsttime=false;
- for(int i=0;i<Godot.singleton_count;i++) {
+ GodotLib.resize(width, height, !firsttime);
+ firsttime = false;
+ for (int i = 0; i < Godot.singleton_count; i++) {
Godot.singletons[i].onGLSurfaceChanged(gl, width, height);
}
}
diff --git a/platform/android/java/src/org/godotengine/godot/input/GodotEditText.java b/platform/android/java/src/org/godotengine/godot/input/GodotEditText.java
index d8a3ac5591..9e062d89c6 100644
--- a/platform/android/java/src/org/godotengine/godot/input/GodotEditText.java
+++ b/platform/android/java/src/org/godotengine/godot/input/GodotEditText.java
@@ -70,42 +70,37 @@ public class GodotEditText extends EditText {
super(context, attrs, defStyle);
this.initView();
}
-
+
protected void initView() {
- this.setPadding(0, 0, 0, 0);
+ this.setPadding(0, 0, 0, 0);
this.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
-
+
sHandler = new Handler() {
@Override
public void handleMessage(final Message msg) {
switch (msg.what) {
- case HANDLER_OPEN_IME_KEYBOARD:
- {
- GodotEditText edit = (GodotEditText) msg.obj;
- String text = edit.mOriginText;
- if (edit.requestFocus())
- {
- edit.removeTextChangedListener(edit.mInputWrapper);
- edit.setText("");
- edit.append(text);
- edit.mInputWrapper.setOriginText(text);
- edit.addTextChangedListener(edit.mInputWrapper);
- final InputMethodManager imm = (InputMethodManager) mView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.showSoftInput(edit, 0);
- }
+ case HANDLER_OPEN_IME_KEYBOARD: {
+ GodotEditText edit = (GodotEditText)msg.obj;
+ String text = edit.mOriginText;
+ if (edit.requestFocus()) {
+ edit.removeTextChangedListener(edit.mInputWrapper);
+ edit.setText("");
+ edit.append(text);
+ edit.mInputWrapper.setOriginText(text);
+ edit.addTextChangedListener(edit.mInputWrapper);
+ final InputMethodManager imm = (InputMethodManager)mView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(edit, 0);
}
- break;
-
- case HANDLER_CLOSE_IME_KEYBOARD:
- {
- GodotEditText edit = (GodotEditText) msg.obj;
-
- edit.removeTextChangedListener(mInputWrapper);
- final InputMethodManager imm = (InputMethodManager) mView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.hideSoftInputFromWindow(edit.getWindowToken(), 0);
- edit.mView.requestFocus();
- }
- break;
+ } break;
+
+ case HANDLER_CLOSE_IME_KEYBOARD: {
+ GodotEditText edit = (GodotEditText)msg.obj;
+
+ edit.removeTextChangedListener(mInputWrapper);
+ final InputMethodManager imm = (InputMethodManager)mView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(edit.getWindowToken(), 0);
+ edit.mView.requestFocus();
+ } break;
}
}
};
@@ -116,7 +111,7 @@ public class GodotEditText extends EditText {
// ===========================================================
public void setView(final GodotView view) {
this.mView = view;
- if(mInputWrapper == null)
+ if (mInputWrapper == null)
mInputWrapper = new GodotTextInputWrapper(mView, this);
this.setOnEditorActionListener(mInputWrapper);
view.requestFocus();
@@ -125,7 +120,7 @@ public class GodotEditText extends EditText {
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
- @Override
+ @Override
public boolean onKeyDown(final int keyCode, final KeyEvent keyEvent) {
super.onKeyDown(keyCode, keyEvent);
@@ -142,7 +137,7 @@ public class GodotEditText extends EditText {
// ===========================================================
public void showKeyboard(String p_existing_text) {
this.mOriginText = p_existing_text;
-
+
final Message msg = new Message();
msg.what = HANDLER_OPEN_IME_KEYBOARD;
msg.obj = this;
@@ -155,7 +150,7 @@ public class GodotEditText extends EditText {
msg.obj = this;
sHandler.sendMessage(msg);
}
-
+
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
diff --git a/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java b/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java
index ac424ab9f8..8e34d9e9e7 100644
--- a/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java
+++ b/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java
@@ -67,7 +67,7 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
private boolean isFullScreenEdit() {
final TextView textField = this.mEdit;
- final InputMethodManager imm = (InputMethodManager) textField.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ final InputMethodManager imm = (InputMethodManager)textField.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
return imm.isFullscreenMode();
}
@@ -81,7 +81,6 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
@Override
public void afterTextChanged(final Editable s) {
-
}
@Override
diff --git a/platform/android/java/src/org/godotengine/godot/input/InputManagerCompat.java b/platform/android/java/src/org/godotengine/godot/input/InputManagerCompat.java
index 4615d2fbb5..0a876d2b7f 100644
--- a/platform/android/java/src/org/godotengine/godot/input/InputManagerCompat.java
+++ b/platform/android/java/src/org/godotengine/godot/input/InputManagerCompat.java
@@ -23,118 +23,118 @@ import android.view.InputDevice;
import android.view.MotionEvent;
public interface InputManagerCompat {
- /**
- * Gets information about the input device with the specified id.
- *
- * @param id The device id
- * @return The input device or null if not found
- */
- public InputDevice getInputDevice(int id);
+ /**
+ * Gets information about the input device with the specified id.
+ *
+ * @param id The device id
+ * @return The input device or null if not found
+ */
+ public InputDevice getInputDevice(int id);
- /**
- * Gets the ids of all input devices in the system.
- *
- * @return The input device ids.
- */
- public int[] getInputDeviceIds();
+ /**
+ * Gets the ids of all input devices in the system.
+ *
+ * @return The input device ids.
+ */
+ public int[] getInputDeviceIds();
- /**
- * Registers an input device listener to receive notifications about when
- * input devices are added, removed or changed.
- *
- * @param listener The listener to register.
- * @param handler The handler on which the listener should be invoked, or
- * null if the listener should be invoked on the calling thread's
- * looper.
- */
- public void registerInputDeviceListener(InputManagerCompat.InputDeviceListener listener,
- Handler handler);
+ /**
+ * Registers an input device listener to receive notifications about when
+ * input devices are added, removed or changed.
+ *
+ * @param listener The listener to register.
+ * @param handler The handler on which the listener should be invoked, or
+ * null if the listener should be invoked on the calling thread's
+ * looper.
+ */
+ public void registerInputDeviceListener(InputManagerCompat.InputDeviceListener listener,
+ Handler handler);
- /**
- * Unregisters an input device listener.
- *
- * @param listener The listener to unregister.
- */
- public void unregisterInputDeviceListener(InputManagerCompat.InputDeviceListener listener);
+ /**
+ * Unregisters an input device listener.
+ *
+ * @param listener The listener to unregister.
+ */
+ public void unregisterInputDeviceListener(InputManagerCompat.InputDeviceListener listener);
- /*
- * The following three calls are to simulate V16 behavior on pre-Jellybean
- * devices. If you don't call them, your callback will never be called
- * pre-API 16.
- */
+ /*
+ * The following three calls are to simulate V16 behavior on pre-Jellybean
+ * devices. If you don't call them, your callback will never be called
+ * pre-API 16.
+ */
- /**
- * Pass the motion events to the InputManagerCompat. This is used to
- * optimize for polling for controllers. If you do not pass these events in,
- * polling will cause regular object creation.
- *
- * @param event the motion event from the app
- */
- public void onGenericMotionEvent(MotionEvent event);
+ /**
+ * Pass the motion events to the InputManagerCompat. This is used to
+ * optimize for polling for controllers. If you do not pass these events in,
+ * polling will cause regular object creation.
+ *
+ * @param event the motion event from the app
+ */
+ public void onGenericMotionEvent(MotionEvent event);
- /**
- * Tell the V9 input manager that it should stop polling for disconnected
- * devices. You can call this during onPause in your activity, although you
- * might want to call it whenever your game is not active (or whenever you
- * don't care about being notified of new input devices)
- */
- public void onPause();
+ /**
+ * Tell the V9 input manager that it should stop polling for disconnected
+ * devices. You can call this during onPause in your activity, although you
+ * might want to call it whenever your game is not active (or whenever you
+ * don't care about being notified of new input devices)
+ */
+ public void onPause();
- /**
- * Tell the V9 input manager that it should start polling for disconnected
- * devices. You can call this during onResume in your activity, although you
- * might want to call it less often (only when the gameplay is actually
- * active)
- */
- public void onResume();
+ /**
+ * Tell the V9 input manager that it should start polling for disconnected
+ * devices. You can call this during onResume in your activity, although you
+ * might want to call it less often (only when the gameplay is actually
+ * active)
+ */
+ public void onResume();
- public interface InputDeviceListener {
- /**
- * Called whenever the input manager detects that a device has been
- * added. This will only be called in the V9 version when a motion event
- * is detected.
- *
- * @param deviceId The id of the input device that was added.
- */
- void onInputDeviceAdded(int deviceId);
+ public interface InputDeviceListener {
+ /**
+ * Called whenever the input manager detects that a device has been
+ * added. This will only be called in the V9 version when a motion event
+ * is detected.
+ *
+ * @param deviceId The id of the input device that was added.
+ */
+ void onInputDeviceAdded(int deviceId);
- /**
- * Called whenever the properties of an input device have changed since
- * they were last queried. This will not be called for the V9 version of
- * the API.
- *
- * @param deviceId The id of the input device that changed.
- */
- void onInputDeviceChanged(int deviceId);
+ /**
+ * Called whenever the properties of an input device have changed since
+ * they were last queried. This will not be called for the V9 version of
+ * the API.
+ *
+ * @param deviceId The id of the input device that changed.
+ */
+ void onInputDeviceChanged(int deviceId);
- /**
- * Called whenever the input manager detects that a device has been
- * removed. For the V9 version, this can take some time depending on the
- * poll rate.
- *
- * @param deviceId The id of the input device that was removed.
- */
- void onInputDeviceRemoved(int deviceId);
- }
+ /**
+ * Called whenever the input manager detects that a device has been
+ * removed. For the V9 version, this can take some time depending on the
+ * poll rate.
+ *
+ * @param deviceId The id of the input device that was removed.
+ */
+ void onInputDeviceRemoved(int deviceId);
+ }
- /**
- * Use this to construct a compatible InputManager.
- */
- public static class Factory {
+ /**
+ * Use this to construct a compatible InputManager.
+ */
+ public static class Factory {
- /**
- * Constructs and returns a compatible InputManger
- *
- * @param context the Context that will be used to get the system
- * service from
- * @return a compatible implementation of InputManager
- */
- public static InputManagerCompat getInputManager(Context context) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- return new InputManagerV16(context);
- } else {
- return new InputManagerV9();
- }
- }
- }
+ /**
+ * Constructs and returns a compatible InputManger
+ *
+ * @param context the Context that will be used to get the system
+ * service from
+ * @return a compatible implementation of InputManager
+ */
+ public static InputManagerCompat getInputManager(Context context) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ return new InputManagerV16(context);
+ } else {
+ return new InputManagerV9();
+ }
+ }
+ }
}
diff --git a/platform/android/java/src/org/godotengine/godot/input/InputManagerV16.java b/platform/android/java/src/org/godotengine/godot/input/InputManagerV16.java
index f05701f455..3b88609cc9 100644
--- a/platform/android/java/src/org/godotengine/godot/input/InputManagerV16.java
+++ b/platform/android/java/src/org/godotengine/godot/input/InputManagerV16.java
@@ -30,78 +30,74 @@ import java.util.Map;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class InputManagerV16 implements InputManagerCompat {
- private final InputManager mInputManager;
- private final Map<InputManagerCompat.InputDeviceListener, V16InputDeviceListener> mListeners;
-
- public InputManagerV16(Context context) {
- mInputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
- mListeners = new HashMap<InputManagerCompat.InputDeviceListener, V16InputDeviceListener>();
- }
-
- @Override
- public InputDevice getInputDevice(int id) {
- return mInputManager.getInputDevice(id);
- }
-
- @Override
- public int[] getInputDeviceIds() {
- return mInputManager.getInputDeviceIds();
- }
-
- static class V16InputDeviceListener implements InputManager.InputDeviceListener {
- final InputManagerCompat.InputDeviceListener mIDL;
-
- public V16InputDeviceListener(InputDeviceListener idl) {
- mIDL = idl;
- }
-
- @Override
- public void onInputDeviceAdded(int deviceId) {
- mIDL.onInputDeviceAdded(deviceId);
- }
-
- @Override
- public void onInputDeviceChanged(int deviceId) {
- mIDL.onInputDeviceChanged(deviceId);
- }
-
- @Override
- public void onInputDeviceRemoved(int deviceId) {
- mIDL.onInputDeviceRemoved(deviceId);
- }
-
- }
-
- @Override
- public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
- V16InputDeviceListener v16Listener = new V16InputDeviceListener(listener);
- mInputManager.registerInputDeviceListener(v16Listener, handler);
- mListeners.put(listener, v16Listener);
- }
-
- @Override
- public void unregisterInputDeviceListener(InputDeviceListener listener) {
- V16InputDeviceListener curListener = mListeners.remove(listener);
- if (null != curListener)
- {
- mInputManager.unregisterInputDeviceListener(curListener);
- }
-
- }
-
- @Override
- public void onGenericMotionEvent(MotionEvent event) {
- // unused in V16
- }
-
- @Override
- public void onPause() {
- // unused in V16
- }
-
- @Override
- public void onResume() {
- // unused in V16
- }
-
+ private final InputManager mInputManager;
+ private final Map<InputManagerCompat.InputDeviceListener, V16InputDeviceListener> mListeners;
+
+ public InputManagerV16(Context context) {
+ mInputManager = (InputManager)context.getSystemService(Context.INPUT_SERVICE);
+ mListeners = new HashMap<InputManagerCompat.InputDeviceListener, V16InputDeviceListener>();
+ }
+
+ @Override
+ public InputDevice getInputDevice(int id) {
+ return mInputManager.getInputDevice(id);
+ }
+
+ @Override
+ public int[] getInputDeviceIds() {
+ return mInputManager.getInputDeviceIds();
+ }
+
+ static class V16InputDeviceListener implements InputManager.InputDeviceListener {
+ final InputManagerCompat.InputDeviceListener mIDL;
+
+ public V16InputDeviceListener(InputDeviceListener idl) {
+ mIDL = idl;
+ }
+
+ @Override
+ public void onInputDeviceAdded(int deviceId) {
+ mIDL.onInputDeviceAdded(deviceId);
+ }
+
+ @Override
+ public void onInputDeviceChanged(int deviceId) {
+ mIDL.onInputDeviceChanged(deviceId);
+ }
+
+ @Override
+ public void onInputDeviceRemoved(int deviceId) {
+ mIDL.onInputDeviceRemoved(deviceId);
+ }
+ }
+
+ @Override
+ public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
+ V16InputDeviceListener v16Listener = new V16InputDeviceListener(listener);
+ mInputManager.registerInputDeviceListener(v16Listener, handler);
+ mListeners.put(listener, v16Listener);
+ }
+
+ @Override
+ public void unregisterInputDeviceListener(InputDeviceListener listener) {
+ V16InputDeviceListener curListener = mListeners.remove(listener);
+ if (null != curListener) {
+ mInputManager.unregisterInputDeviceListener(curListener);
+ }
+ }
+
+ @Override
+ public void onGenericMotionEvent(MotionEvent event) {
+ // unused in V16
+ }
+
+ @Override
+ public void onPause() {
+ // unused in V16
+ }
+
+ @Override
+ public void onResume() {
+ // unused in V16
+ }
}
diff --git a/platform/android/java/src/org/godotengine/godot/input/InputManagerV9.java b/platform/android/java/src/org/godotengine/godot/input/InputManagerV9.java
index 0334c00997..a1418c5899 100644
--- a/platform/android/java/src/org/godotengine/godot/input/InputManagerV9.java
+++ b/platform/android/java/src/org/godotengine/godot/input/InputManagerV9.java
@@ -31,181 +31,179 @@ import java.util.Map;
import java.util.Queue;
public class InputManagerV9 implements InputManagerCompat {
- private static final String LOG_TAG = "InputManagerV9";
- private static final int MESSAGE_TEST_FOR_DISCONNECT = 101;
- private static final long CHECK_ELAPSED_TIME = 3000L;
-
- private static final int ON_DEVICE_ADDED = 0;
- private static final int ON_DEVICE_CHANGED = 1;
- private static final int ON_DEVICE_REMOVED = 2;
-
- private final SparseArray<long[]> mDevices;
- private final Map<InputDeviceListener, Handler> mListeners;
- private final Handler mDefaultHandler;
-
- private static class PollingMessageHandler extends Handler {
- private final WeakReference<InputManagerV9> mInputManager;
-
- PollingMessageHandler(InputManagerV9 im) {
- mInputManager = new WeakReference<InputManagerV9>(im);
- }
-
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- switch (msg.what) {
- case MESSAGE_TEST_FOR_DISCONNECT:
- InputManagerV9 imv = mInputManager.get();
- if (null != imv) {
- long time = SystemClock.elapsedRealtime();
- int size = imv.mDevices.size();
- for (int i = 0; i < size; i++) {
- long[] lastContact = imv.mDevices.valueAt(i);
- if (null != lastContact) {
- if (time - lastContact[0] > CHECK_ELAPSED_TIME) {
- // check to see if the device has been
- // disconnected
- int id = imv.mDevices.keyAt(i);
- if (null == InputDevice.getDevice(id)) {
- // disconnected!
- imv.notifyListeners(ON_DEVICE_REMOVED, id);
- imv.mDevices.remove(id);
- } else {
- lastContact[0] = time;
- }
- }
- }
- }
- sendEmptyMessageDelayed(MESSAGE_TEST_FOR_DISCONNECT,
- CHECK_ELAPSED_TIME);
- }
- break;
- }
- }
-
- }
-
- public InputManagerV9() {
- mDevices = new SparseArray<long[]>();
- mListeners = new HashMap<InputDeviceListener, Handler>();
- mDefaultHandler = new PollingMessageHandler(this);
- // as a side-effect, populates our collection of watched
- // input devices
- getInputDeviceIds();
- }
-
- @Override
- public InputDevice getInputDevice(int id) {
- return InputDevice.getDevice(id);
- }
-
- @Override
- public int[] getInputDeviceIds() {
- // add any hitherto unknown devices to our
- // collection of watched input devices
- int[] activeDevices = InputDevice.getDeviceIds();
- long time = SystemClock.elapsedRealtime();
- for ( int id : activeDevices ) {
- long[] lastContact = mDevices.get(id);
- if ( null == lastContact ) {
- // we have a new device
- mDevices.put(id, new long[] { time });
- }
- }
- return activeDevices;
- }
-
- @Override
- public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
- mListeners.remove(listener);
- if (handler == null) {
- handler = mDefaultHandler;
- }
- mListeners.put(listener, handler);
- }
-
- @Override
- public void unregisterInputDeviceListener(InputDeviceListener listener) {
- mListeners.remove(listener);
- }
-
- private void notifyListeners(int why, int deviceId) {
- // the state of some device has changed
- if (!mListeners.isEmpty()) {
- // yes... this will cause an object to get created... hopefully
- // it won't happen very often
- for (InputDeviceListener listener : mListeners.keySet()) {
- Handler handler = mListeners.get(listener);
- DeviceEvent odc = DeviceEvent.getDeviceEvent(why, deviceId, listener);
- handler.post(odc);
- }
- }
- }
-
- private static class DeviceEvent implements Runnable {
- private int mMessageType;
- private int mId;
- private InputDeviceListener mListener;
- private static Queue<DeviceEvent> sEventQueue = new ArrayDeque<DeviceEvent>();
-
- private DeviceEvent() {
- }
-
- static DeviceEvent getDeviceEvent(int messageType, int id,
- InputDeviceListener listener) {
- DeviceEvent curChanged = sEventQueue.poll();
- if (null == curChanged) {
- curChanged = new DeviceEvent();
- }
- curChanged.mMessageType = messageType;
- curChanged.mId = id;
- curChanged.mListener = listener;
- return curChanged;
- }
-
- @Override
- public void run() {
- switch (mMessageType) {
- case ON_DEVICE_ADDED:
- mListener.onInputDeviceAdded(mId);
- break;
- case ON_DEVICE_CHANGED:
- mListener.onInputDeviceChanged(mId);
- break;
- case ON_DEVICE_REMOVED:
- mListener.onInputDeviceRemoved(mId);
- break;
- default:
- Log.e(LOG_TAG, "Unknown Message Type");
- break;
- }
- // dump this runnable back in the queue
- sEventQueue.offer(this);
- }
- }
-
- @Override
- public void onGenericMotionEvent(MotionEvent event) {
- // detect new devices
- int id = event.getDeviceId();
- long[] timeArray = mDevices.get(id);
- if (null == timeArray) {
- notifyListeners(ON_DEVICE_ADDED, id);
- timeArray = new long[1];
- mDevices.put(id, timeArray);
- }
- long time = SystemClock.elapsedRealtime();
- timeArray[0] = time;
- }
-
- @Override
- public void onPause() {
- mDefaultHandler.removeMessages(MESSAGE_TEST_FOR_DISCONNECT);
- }
-
- @Override
- public void onResume() {
- mDefaultHandler.sendEmptyMessage(MESSAGE_TEST_FOR_DISCONNECT);
- }
-
+ private static final String LOG_TAG = "InputManagerV9";
+ private static final int MESSAGE_TEST_FOR_DISCONNECT = 101;
+ private static final long CHECK_ELAPSED_TIME = 3000L;
+
+ private static final int ON_DEVICE_ADDED = 0;
+ private static final int ON_DEVICE_CHANGED = 1;
+ private static final int ON_DEVICE_REMOVED = 2;
+
+ private final SparseArray<long[]> mDevices;
+ private final Map<InputDeviceListener, Handler> mListeners;
+ private final Handler mDefaultHandler;
+
+ private static class PollingMessageHandler extends Handler {
+ private final WeakReference<InputManagerV9> mInputManager;
+
+ PollingMessageHandler(InputManagerV9 im) {
+ mInputManager = new WeakReference<InputManagerV9>(im);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ switch (msg.what) {
+ case MESSAGE_TEST_FOR_DISCONNECT:
+ InputManagerV9 imv = mInputManager.get();
+ if (null != imv) {
+ long time = SystemClock.elapsedRealtime();
+ int size = imv.mDevices.size();
+ for (int i = 0; i < size; i++) {
+ long[] lastContact = imv.mDevices.valueAt(i);
+ if (null != lastContact) {
+ if (time - lastContact[0] > CHECK_ELAPSED_TIME) {
+ // check to see if the device has been
+ // disconnected
+ int id = imv.mDevices.keyAt(i);
+ if (null == InputDevice.getDevice(id)) {
+ // disconnected!
+ imv.notifyListeners(ON_DEVICE_REMOVED, id);
+ imv.mDevices.remove(id);
+ } else {
+ lastContact[0] = time;
+ }
+ }
+ }
+ }
+ sendEmptyMessageDelayed(MESSAGE_TEST_FOR_DISCONNECT,
+ CHECK_ELAPSED_TIME);
+ }
+ break;
+ }
+ }
+ }
+
+ public InputManagerV9() {
+ mDevices = new SparseArray<long[]>();
+ mListeners = new HashMap<InputDeviceListener, Handler>();
+ mDefaultHandler = new PollingMessageHandler(this);
+ // as a side-effect, populates our collection of watched
+ // input devices
+ getInputDeviceIds();
+ }
+
+ @Override
+ public InputDevice getInputDevice(int id) {
+ return InputDevice.getDevice(id);
+ }
+
+ @Override
+ public int[] getInputDeviceIds() {
+ // add any hitherto unknown devices to our
+ // collection of watched input devices
+ int[] activeDevices = InputDevice.getDeviceIds();
+ long time = SystemClock.elapsedRealtime();
+ for (int id : activeDevices) {
+ long[] lastContact = mDevices.get(id);
+ if (null == lastContact) {
+ // we have a new device
+ mDevices.put(id, new long[] { time });
+ }
+ }
+ return activeDevices;
+ }
+
+ @Override
+ public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
+ mListeners.remove(listener);
+ if (handler == null) {
+ handler = mDefaultHandler;
+ }
+ mListeners.put(listener, handler);
+ }
+
+ @Override
+ public void unregisterInputDeviceListener(InputDeviceListener listener) {
+ mListeners.remove(listener);
+ }
+
+ private void notifyListeners(int why, int deviceId) {
+ // the state of some device has changed
+ if (!mListeners.isEmpty()) {
+ // yes... this will cause an object to get created... hopefully
+ // it won't happen very often
+ for (InputDeviceListener listener : mListeners.keySet()) {
+ Handler handler = mListeners.get(listener);
+ DeviceEvent odc = DeviceEvent.getDeviceEvent(why, deviceId, listener);
+ handler.post(odc);
+ }
+ }
+ }
+
+ private static class DeviceEvent implements Runnable {
+ private int mMessageType;
+ private int mId;
+ private InputDeviceListener mListener;
+ private static Queue<DeviceEvent> sEventQueue = new ArrayDeque<DeviceEvent>();
+
+ private DeviceEvent() {
+ }
+
+ static DeviceEvent getDeviceEvent(int messageType, int id,
+ InputDeviceListener listener) {
+ DeviceEvent curChanged = sEventQueue.poll();
+ if (null == curChanged) {
+ curChanged = new DeviceEvent();
+ }
+ curChanged.mMessageType = messageType;
+ curChanged.mId = id;
+ curChanged.mListener = listener;
+ return curChanged;
+ }
+
+ @Override
+ public void run() {
+ switch (mMessageType) {
+ case ON_DEVICE_ADDED:
+ mListener.onInputDeviceAdded(mId);
+ break;
+ case ON_DEVICE_CHANGED:
+ mListener.onInputDeviceChanged(mId);
+ break;
+ case ON_DEVICE_REMOVED:
+ mListener.onInputDeviceRemoved(mId);
+ break;
+ default:
+ Log.e(LOG_TAG, "Unknown Message Type");
+ break;
+ }
+ // dump this runnable back in the queue
+ sEventQueue.offer(this);
+ }
+ }
+
+ @Override
+ public void onGenericMotionEvent(MotionEvent event) {
+ // detect new devices
+ int id = event.getDeviceId();
+ long[] timeArray = mDevices.get(id);
+ if (null == timeArray) {
+ notifyListeners(ON_DEVICE_ADDED, id);
+ timeArray = new long[1];
+ mDevices.put(id, timeArray);
+ }
+ long time = SystemClock.elapsedRealtime();
+ timeArray[0] = time;
+ }
+
+ @Override
+ public void onPause() {
+ mDefaultHandler.removeMessages(MESSAGE_TEST_FOR_DISCONNECT);
+ }
+
+ @Override
+ public void onResume() {
+ mDefaultHandler.sendEmptyMessage(MESSAGE_TEST_FOR_DISCONNECT);
+ }
}
diff --git a/platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java b/platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java
index 8622f4ccff..d6f26e19b2 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java
@@ -39,33 +39,32 @@ import android.util.Log;
abstract public class ConsumeTask {
private Context context;
-
+
private IInAppBillingService mService;
- public ConsumeTask(IInAppBillingService mService, Context context ){
+ public ConsumeTask(IInAppBillingService mService, Context context) {
this.context = context;
this.mService = mService;
}
-
- public void consume(final String sku){
+ public void consume(final String sku) {
//Log.d("XXX", "Consuming product " + sku);
PaymentsCache pc = new PaymentsCache(context);
Boolean isBlocked = pc.getConsumableFlag("block", sku);
String _token = pc.getConsumableValue("token", sku);
- //Log.d("XXX", "token " + _token);
- if(!isBlocked && _token == null){
+ //Log.d("XXX", "token " + _token);
+ if (!isBlocked && _token == null) {
//_token = "inapp:"+context.getPackageName()+":android.test.purchased";
//Log.d("XXX", "Consuming product " + sku + " with token " + _token);
- }else if(!isBlocked){
+ } else if (!isBlocked) {
//Log.d("XXX", "It is not blocked ¿?");
return;
- }else if(_token == null){
+ } else if (_token == null) {
//Log.d("XXX", "No token available");
this.error("No token for sku:" + sku);
return;
}
final String token = _token;
- new AsyncTask<String, String, String>(){
+ new AsyncTask<String, String, String>() {
@Override
protected String doInBackground(String... params) {
@@ -73,28 +72,27 @@ abstract public class ConsumeTask {
//Log.d("XXX", "Requesting to release item.");
int response = mService.consumePurchase(3, context.getPackageName(), token);
//Log.d("XXX", "release response code: " + response);
- if(response == 0 || response == 8){
+ if (response == 0 || response == 8) {
return null;
}
} catch (RemoteException e) {
return e.getMessage();
-
}
return "Some error";
}
-
- protected void onPostExecute(String param){
- if(param == null){
- success( new PaymentsCache(context).getConsumableValue("ticket", sku) );
- }else{
+
+ protected void onPostExecute(String param) {
+ if (param == null) {
+ success(new PaymentsCache(context).getConsumableValue("ticket", sku));
+ } else {
error(param);
}
}
-
- }.execute();
+
+ }
+ .execute();
}
-
+
abstract protected void success(String ticket);
abstract protected void error(String message);
-
}
diff --git a/platform/android/java/src/org/godotengine/godot/payments/GenericConsumeTask.java b/platform/android/java/src/org/godotengine/godot/payments/GenericConsumeTask.java
index 0afe35510c..31f6396738 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/GenericConsumeTask.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/GenericConsumeTask.java
@@ -36,15 +36,12 @@ import android.os.AsyncTask;
import android.os.RemoteException;
import android.util.Log;
-abstract public class GenericConsumeTask extends AsyncTask<String, String, String>{
+abstract public class GenericConsumeTask extends AsyncTask<String, String, String> {
private Context context;
private IInAppBillingService mService;
-
-
-
- public GenericConsumeTask(Context context, IInAppBillingService mService, String sku, String receipt, String signature, String token){
+ public GenericConsumeTask(Context context, IInAppBillingService mService, String sku, String receipt, String signature, String token) {
this.context = context;
this.mService = mService;
this.sku = sku;
@@ -52,19 +49,19 @@ abstract public class GenericConsumeTask extends AsyncTask<String, String, Strin
this.signature = signature;
this.token = token;
}
-
+
private String sku;
private String receipt;
private String signature;
private String token;
-
+
@Override
protected String doInBackground(String... params) {
try {
//Log.d("godot", "Requesting to consume an item with token ." + token);
int response = mService.consumePurchase(3, context.getPackageName(), token);
//Log.d("godot", "consumePurchase response: " + response);
- if(response == 0 || response == 8){
+ if (response == 0 || response == 8) {
return null;
}
} catch (Exception e) {
@@ -72,11 +69,10 @@ abstract public class GenericConsumeTask extends AsyncTask<String, String, Strin
}
return null;
}
-
- protected void onPostExecute(String sarasa){
+
+ protected void onPostExecute(String sarasa) {
onSuccess(sku, receipt, signature, token);
}
-
- abstract public void onSuccess(String sku, String receipt, String signature, String token);
+ abstract public void onSuccess(String sku, String receipt, String signature, String token);
}
diff --git a/platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java b/platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java
index 7318ae2fc6..80f53d16c8 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java
@@ -50,28 +50,26 @@ import android.util.Log;
abstract public class HandlePurchaseTask {
private Activity context;
-
- public HandlePurchaseTask(Activity context ){
+
+ public HandlePurchaseTask(Activity context) {
this.context = context;
}
-
-
- public void handlePurchaseRequest(int resultCode, Intent data){
+
+ public void handlePurchaseRequest(int resultCode, Intent data) {
//Log.d("XXX", "Handling purchase response");
//int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
PaymentsCache pc = new PaymentsCache(context);
-
+
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
//Log.d("XXX", "Purchase data:" + purchaseData);
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
//Log.d("XXX", "Purchase signature:" + dataSignature);
-
+
if (resultCode == Activity.RESULT_OK) {
-
+
try {
//Log.d("SARLANGA", purchaseData);
-
-
+
JSONObject jo = new JSONObject(purchaseData);
//String sku = jo.getString("productId");
//alert("You have bought the " + sku + ". Excellent choice, aventurer!");
@@ -82,8 +80,8 @@ abstract public class HandlePurchaseTask {
//Integer state = jo.getInt("purchaseState");
String developerPayload = jo.getString("developerPayload");
String purchaseToken = jo.getString("purchaseToken");
-
- if(! pc.getConsumableValue("validation_hash", productId).equals(developerPayload) ) {
+
+ if (!pc.getConsumableValue("validation_hash", productId).equals(developerPayload)) {
error("Untrusted callback");
return;
}
@@ -92,13 +90,13 @@ abstract public class HandlePurchaseTask {
pc.setConsumableValue("ticket", productId, purchaseData);
pc.setConsumableFlag("block", productId, true);
pc.setConsumableValue("token", productId, purchaseToken);
-
+
success(productId, dataSignature, purchaseData);
return;
- } catch (JSONException e) {
+ } catch (JSONException e) {
error(e.getMessage());
}
- }else if( resultCode == Activity.RESULT_CANCELED){
+ } else if (resultCode == Activity.RESULT_CANCELED) {
canceled();
}
}
@@ -106,6 +104,4 @@ abstract public class HandlePurchaseTask {
abstract protected void success(String sku, String signature, String ticket);
abstract protected void error(String message);
abstract protected void canceled();
-
-
}
diff --git a/platform/android/java/src/org/godotengine/godot/payments/PaymentsCache.java b/platform/android/java/src/org/godotengine/godot/payments/PaymentsCache.java
index 69ac02e902..f9828ef77d 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/PaymentsCache.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/PaymentsCache.java
@@ -34,41 +34,38 @@ import android.content.SharedPreferences;
import android.util.Log;
public class PaymentsCache {
-
+
public Context context;
- public PaymentsCache(Context context){
+ public PaymentsCache(Context context) {
this.context = context;
}
-
-
- public void setConsumableFlag(String set, String sku, Boolean flag){
- SharedPreferences sharedPref = context.getSharedPreferences("consumables_" + set, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = sharedPref.edit();
- editor.putBoolean(sku, flag);
- editor.commit();
-}
- public boolean getConsumableFlag(String set, String sku){
- SharedPreferences sharedPref = context.getSharedPreferences(
- "consumables_" + set, Context.MODE_PRIVATE);
- return sharedPref.getBoolean(sku, false);
+ public void setConsumableFlag(String set, String sku, Boolean flag) {
+ SharedPreferences sharedPref = context.getSharedPreferences("consumables_" + set, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sharedPref.edit();
+ editor.putBoolean(sku, flag);
+ editor.commit();
}
+ public boolean getConsumableFlag(String set, String sku) {
+ SharedPreferences sharedPref = context.getSharedPreferences(
+ "consumables_" + set, Context.MODE_PRIVATE);
+ return sharedPref.getBoolean(sku, false);
+ }
- public void setConsumableValue(String set, String sku, String value){
- SharedPreferences sharedPref = context.getSharedPreferences("consumables_" + set, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = sharedPref.edit();
- editor.putString(sku, value);
+ public void setConsumableValue(String set, String sku, String value) {
+ SharedPreferences sharedPref = context.getSharedPreferences("consumables_" + set, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sharedPref.edit();
+ editor.putString(sku, value);
//Log.d("XXX", "Setting asset: consumables_" + set + ":" + sku);
- editor.commit();
+ editor.commit();
}
- public String getConsumableValue(String set, String sku){
- SharedPreferences sharedPref = context.getSharedPreferences(
- "consumables_" + set, Context.MODE_PRIVATE);
+ public String getConsumableValue(String set, String sku) {
+ SharedPreferences sharedPref = context.getSharedPreferences(
+ "consumables_" + set, Context.MODE_PRIVATE);
//Log.d("XXX", "Getting asset: consumables_" + set + ":" + sku);
- return sharedPref.getString(sku, null);
+ return sharedPref.getString(sku, null);
}
-
}
diff --git a/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java b/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java
index b327265abb..71407566e2 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java
@@ -106,7 +106,6 @@ public class PaymentsManager {
@Override
protected void error(String message) {
godotPaymentV3.callbackFail();
-
}
@Override
@@ -119,8 +118,8 @@ public class PaymentsManager {
godotPaymentV3.callbackAlreadyOwned(sku);
}
- }.purchase(sku, transactionId);
-
+ }
+ .purchase(sku, transactionId);
}
public void consumeUnconsumedPurchases() {
@@ -135,16 +134,15 @@ public class PaymentsManager {
protected void error(String message) {
Log.d("godot", "consumeUnconsumedPurchases :" + message);
godotPaymentV3.callbackFailConsume();
-
}
@Override
protected void notRequired() {
Log.d("godot", "callbackSuccessNoUnconsumedPurchases :");
godotPaymentV3.callbackSuccessNoUnconsumedPurchases();
-
}
- }.consumeItAll();
+ }
+ .consumeItAll();
}
public void requestPurchased() {
@@ -210,9 +208,9 @@ public class PaymentsManager {
@Override
protected void error(String message) {
godotPaymentV3.callbackFail();
-
}
- }.consume(sku);
+ }
+ .consume(sku);
}
}
@@ -225,7 +223,8 @@ public class PaymentsManager {
protected void canceled() {
godotPaymentV3.callbackCancel();
}
- }.handlePurchaseRequest(resultCode, data);
+ }
+ .handlePurchaseRequest(resultCode, data);
}
public void validatePurchase(String purchaseToken, final String sku) {
@@ -246,8 +245,8 @@ public class PaymentsManager {
protected void error(String message) {
godotPaymentV3.callbackFail();
}
- }.consume(sku);
-
+ }
+ .consume(sku);
}
@Override
@@ -259,7 +258,8 @@ public class PaymentsManager {
protected void canceled() {
godotPaymentV3.callbackCancel();
}
- }.validatePurchase(sku);
+ }
+ .validatePurchase(sku);
}
public void setAutoConsume(boolean autoConsume) {
@@ -278,7 +278,8 @@ public class PaymentsManager {
protected void error(String message) {
godotPaymentV3.callbackFailConsume();
}
- }.consume(sku);
+ }
+ .consume(sku);
}
// Workaround to bug where sometimes response codes come as Long instead of Integer
@@ -287,8 +288,10 @@ public class PaymentsManager {
if (o == null) {
//logDebug("Bundle with null response code, assuming OK (known issue)");
return BILLING_RESPONSE_RESULT_OK;
- } else if (o instanceof Integer) return ((Integer) o).intValue();
- else if (o instanceof Long) return (int) ((Long) o).longValue();
+ } else if (o instanceof Integer)
+ return ((Integer)o).intValue();
+ else if (o instanceof Long)
+ return (int)((Long)o).longValue();
else {
//logError("Unexpected type for bundle response code.");
//logError(o.getClass().getName());
@@ -304,25 +307,41 @@ public class PaymentsManager {
* It also includes the result code numerically.
*/
public static String getResponseDesc(int code) {
- String[] iab_msgs = ("0:OK/1:User Canceled/2:Unknown/" +
- "3:Billing Unavailable/4:Item unavailable/" +
- "5:Developer Error/6:Error/7:Item Already Owned/" +
- "8:Item not owned").split("/");
- String[] iabhelper_msgs = ("0:OK/-1001:Remote exception during initialization/" +
- "-1002:Bad response received/" +
- "-1003:Purchase signature verification failed/" +
- "-1004:Send intent failed/" +
- "-1005:User cancelled/" +
- "-1006:Unknown purchase response/" +
- "-1007:Missing token/" +
- "-1008:Unknown error/" +
- "-1009:Subscriptions not available/" +
- "-1010:Invalid consumption attempt").split("/");
+ String[] iab_msgs = ("0:OK/1:User Canceled/2:Unknown/"
+ +
+ "3:Billing Unavailable/4:Item unavailable/"
+ +
+ "5:Developer Error/6:Error/7:Item Already Owned/"
+ +
+ "8:Item not owned")
+ .split("/");
+ String[] iabhelper_msgs = ("0:OK/-1001:Remote exception during initialization/"
+ +
+ "-1002:Bad response received/"
+ +
+ "-1003:Purchase signature verification failed/"
+ +
+ "-1004:Send intent failed/"
+ +
+ "-1005:User cancelled/"
+ +
+ "-1006:Unknown purchase response/"
+ +
+ "-1007:Missing token/"
+ +
+ "-1008:Unknown error/"
+ +
+ "-1009:Subscriptions not available/"
+ +
+ "-1010:Invalid consumption attempt")
+ .split("/");
if (code <= -1000) {
int index = -1000 - code;
- if (index >= 0 && index < iabhelper_msgs.length) return iabhelper_msgs[index];
- else return String.valueOf(code) + ":Unknown IAB Helper Error";
+ if (index >= 0 && index < iabhelper_msgs.length)
+ return iabhelper_msgs[index];
+ else
+ return String.valueOf(code) + ":Unknown IAB Helper Error";
} else if (code < 0 || code >= iab_msgs.length)
return String.valueOf(code) + ":Unknown";
else
@@ -375,7 +394,7 @@ public class PaymentsManager {
ArrayList<String> responseList = skuDetails.getStringArrayList("DETAILS_LIST");
for (String thisResponse : responseList) {
- Log.d("godot", "response = "+thisResponse);
+ Log.d("godot", "response = " + thisResponse);
godotPaymentV3.addSkuDetail(thisResponse);
}
} catch (RemoteException e) {
@@ -385,7 +404,8 @@ public class PaymentsManager {
}
godotPaymentV3.completeSkuDetail();
}
- })).start();
+ }))
+ .start();
}
private GodotPaymentV3 godotPaymentV3;
@@ -393,5 +413,4 @@ public class PaymentsManager {
public void setBaseSingleton(GodotPaymentV3 godotPaymentV3) {
this.godotPaymentV3 = godotPaymentV3;
}
-
}
diff --git a/platform/android/java/src/org/godotengine/godot/payments/PurchaseTask.java b/platform/android/java/src/org/godotengine/godot/payments/PurchaseTask.java
index 6ecea0106c..e2f08345ad 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/PurchaseTask.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/PurchaseTask.java
@@ -50,17 +50,16 @@ import android.util.Log;
abstract public class PurchaseTask {
private Activity context;
-
+
private IInAppBillingService mService;
- public PurchaseTask(IInAppBillingService mService, Activity context ){
+ public PurchaseTask(IInAppBillingService mService, Activity context) {
this.context = context;
this.mService = mService;
}
-
private boolean isLooping = false;
-
- public void purchase(final String sku, final String transactionId){
+
+ public void purchase(final String sku, final String transactionId) {
Log.d("XXX", "Starting purchase for: " + sku);
PaymentsCache pc = new PaymentsCache(context);
Boolean isBlocked = pc.getConsumableFlag("block", sku);
@@ -75,7 +74,7 @@ abstract public class PurchaseTask {
Bundle buyIntentBundle;
try {
- buyIntentBundle = mService.getBuyIntent(3, context.getApplicationContext().getPackageName(), sku, "inapp", hash );
+ buyIntentBundle = mService.getBuyIntent(3, context.getApplicationContext().getPackageName(), sku, "inapp", hash);
} catch (RemoteException e) {
//Log.d("XXX", "Error: " + e.getMessage());
error(e.getMessage());
@@ -83,50 +82,45 @@ abstract public class PurchaseTask {
}
Object rc = buyIntentBundle.get("RESPONSE_CODE");
int responseCode = 0;
- if(rc == null){
+ if (rc == null) {
responseCode = PaymentsManager.BILLING_RESPONSE_RESULT_OK;
- }else if( rc instanceof Integer){
+ } else if (rc instanceof Integer) {
responseCode = ((Integer)rc).intValue();
- }else if( rc instanceof Long){
+ } else if (rc instanceof Long) {
responseCode = (int)((Long)rc).longValue();
}
//Log.d("XXX", "Buy intent response code: " + responseCode);
- if(responseCode == 1 || responseCode == 3 || responseCode == 4){
+ if (responseCode == 1 || responseCode == 3 || responseCode == 4) {
canceled();
return;
}
- if(responseCode == 7){
+ if (responseCode == 7) {
alreadyOwned();
return;
}
-
-
+
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
pc.setConsumableValue("validation_hash", sku, hash);
try {
- if(context == null){
+ if (context == null) {
//Log.d("XXX", "No context!");
}
- if(pendingIntent == null){
+ if (pendingIntent == null) {
//Log.d("XXX", "No pending intent");
}
//Log.d("XXX", "Starting activity for purchase!");
context.startIntentSenderForResult(
pendingIntent.getIntentSender(),
- PaymentsManager.REQUEST_CODE_FOR_PURCHASE,
- new Intent(),
+ PaymentsManager.REQUEST_CODE_FOR_PURCHASE,
+ new Intent(),
Integer.valueOf(0), Integer.valueOf(0),
- Integer.valueOf(0));
+ Integer.valueOf(0));
} catch (SendIntentException e) {
error(e.getMessage());
}
-
-
-
}
abstract protected void error(String message);
abstract protected void canceled();
abstract protected void alreadyOwned();
-
}
diff --git a/platform/android/java/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java b/platform/android/java/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java
index d831e45694..765906d0bb 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java
@@ -48,69 +48,63 @@ abstract public class ReleaseAllConsumablesTask {
private Context context;
private IInAppBillingService mService;
-
- public ReleaseAllConsumablesTask(IInAppBillingService mService, Context context ){
+
+ public ReleaseAllConsumablesTask(IInAppBillingService mService, Context context) {
this.context = context;
this.mService = mService;
}
-
- public void consumeItAll(){
- try{
+ public void consumeItAll() {
+ try {
//Log.d("godot", "consumeItall for " + context.getPackageName());
- Bundle bundle = mService.getPurchases(3, context.getPackageName(), "inapp",null);
-
+ Bundle bundle = mService.getPurchases(3, context.getPackageName(), "inapp", null);
+
for (String key : bundle.keySet()) {
Object value = bundle.get(key);
//Log.d("godot", String.format("%s %s (%s)", key,
//value.toString(), value.getClass().getName()));
}
-
-
- if (bundle.getInt("RESPONSE_CODE") == 0){
+
+ if (bundle.getInt("RESPONSE_CODE") == 0) {
final ArrayList<String> myPurchases = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
final ArrayList<String> mySignatures = bundle.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
-
- if (myPurchases == null || myPurchases.size() == 0){
+ if (myPurchases == null || myPurchases.size() == 0) {
//Log.d("godot", "No purchases!");
notRequired();
return;
}
-
-
+
//Log.d("godot", "# products to be consumed:" + myPurchases.size());
- for (int i=0;i<myPurchases.size();i++)
- {
-
- try{
+ for (int i = 0; i < myPurchases.size(); i++) {
+
+ try {
String receipt = myPurchases.get(i);
JSONObject inappPurchaseData = new JSONObject(receipt);
String sku = inappPurchaseData.getString("productId");
String token = inappPurchaseData.getString("purchaseToken");
String signature = mySignatures.get(i);
//Log.d("godot", "A punto de consumir un item con token:" + token + "\n" + receipt);
- new GenericConsumeTask(context, mService, sku, receipt,signature, token) {
-
+ new GenericConsumeTask(context, mService, sku, receipt, signature, token) {
+
@Override
public void onSuccess(String sku, String receipt, String signature, String token) {
ReleaseAllConsumablesTask.this.success(sku, receipt, signature, token);
}
- }.execute();
-
+ }
+ .execute();
+
} catch (JSONException e) {
}
}
-
}
- }catch(Exception e){
+ } catch (Exception e) {
Log.d("godot", "Error releasing products:" + e.getClass().getName() + ":" + e.getMessage());
}
}
-
+
abstract protected void success(String sku, String receipt, String signature, String token);
abstract protected void error(String message);
abstract protected void notRequired();
-
}
diff --git a/platform/android/java/src/org/godotengine/godot/payments/ValidateTask.java b/platform/android/java/src/org/godotengine/godot/payments/ValidateTask.java
index 6e058c140c..3e62ef282a 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/ValidateTask.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/ValidateTask.java
@@ -55,22 +55,21 @@ abstract public class ValidateTask {
private Activity context;
private GodotPaymentV3 godotPaymentsV3;
- public ValidateTask(Activity context, GodotPaymentV3 godotPaymentsV3){
+ public ValidateTask(Activity context, GodotPaymentV3 godotPaymentsV3) {
this.context = context;
this.godotPaymentsV3 = godotPaymentsV3;
}
-
- public void validatePurchase(final String sku){
- new AsyncTask<String, String, String>(){
-
+ public void validatePurchase(final String sku) {
+ new AsyncTask<String, String, String>() {
+
private ProgressDialog dialog;
@Override
- protected void onPreExecute(){
+ protected void onPreExecute() {
dialog = ProgressDialog.show(context, null, "Please wait...");
}
-
+
@Override
protected String doInBackground(String... params) {
PaymentsCache pc = new PaymentsCache(context);
@@ -90,37 +89,34 @@ abstract public class ValidateTask {
//Log.d("XXX", "Validation response:\n"+jsonResponse);
return jsonResponse;
}
-
+
@Override
- protected void onPostExecute(String response){
- if(dialog != null){
+ protected void onPostExecute(String response) {
+ if (dialog != null) {
dialog.dismiss();
}
JSONObject j;
try {
j = new JSONObject(response);
- if(j.getString("status").equals("OK")){
+ if (j.getString("status").equals("OK")) {
success();
return;
- }else if(j.getString("status") != null){
+ } else if (j.getString("status") != null) {
error(j.getString("message"));
- }else{
+ } else {
error("Connection error");
}
} catch (JSONException e) {
error(e.getMessage());
- }catch (Exception e){
+ } catch (Exception e) {
error(e.getMessage());
}
-
-
}
-
- }.execute();
+
+ }
+ .execute();
}
abstract protected void success();
abstract protected void error(String message);
abstract protected void canceled();
-
-
}
diff --git a/platform/android/java/src/org/godotengine/godot/utils/Crypt.java b/platform/android/java/src/org/godotengine/godot/utils/Crypt.java
index 2fd66553f6..35e4e430a4 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/Crypt.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/Crypt.java
@@ -34,34 +34,34 @@ import java.util.Random;
public class Crypt {
- public static String md5(String input){
- try {
- // Create MD5 Hash
- MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
- digest.update(input.getBytes());
- byte messageDigest[] = digest.digest();
-
- // Create Hex String
- StringBuffer hexString = new StringBuffer();
- for (int i=0; i<messageDigest.length; i++)
- hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
- return hexString.toString();
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- return "";
+ public static String md5(String input) {
+ try {
+ // Create MD5 Hash
+ MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
+ digest.update(input.getBytes());
+ byte messageDigest[] = digest.digest();
+
+ // Create Hex String
+ StringBuffer hexString = new StringBuffer();
+ for (int i = 0; i < messageDigest.length; i++)
+ hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
+ return hexString.toString();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return "";
}
-
- public static String createRandomHash(){
+
+ public static String createRandomHash() {
return md5(Long.toString(createRandomLong()));
}
-
- public static long createAbsRandomLong(){
+
+ public static long createAbsRandomLong() {
return Math.abs(createRandomLong());
}
-
- public static long createRandomLong(){
+
+ public static long createRandomLong() {
Random r = new Random();
return r.nextLong();
}
diff --git a/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java b/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
index 3fc8c48397..bfcf7e3b2a 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
@@ -42,30 +42,29 @@ import javax.net.ssl.TrustManagerFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
-
/**
*
* @author Luis Linietsky <luis.linietsky@gmail.com>
*/
public class CustomSSLSocketFactory extends SSLSocketFactory {
- SSLContext sslContext = SSLContext.getInstance("TLS");
+ SSLContext sslContext = SSLContext.getInstance("TLS");
- public CustomSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
- super(truststore);
+ public CustomSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+ super(truststore);
- TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
- tmf.init(truststore);
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
+ tmf.init(truststore);
- sslContext.init(null, tmf.getTrustManagers(), null);
- }
+ sslContext.init(null, tmf.getTrustManagers(), null);
+ }
- @Override
- public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
- return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
- }
+ @Override
+ public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
+ return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
+ }
- @Override
- public Socket createSocket() throws IOException {
- return sslContext.getSocketFactory().createSocket();
- }
+ @Override
+ public Socket createSocket() throws IOException {
+ return sslContext.getSocketFactory().createSocket();
+ }
}
diff --git a/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java b/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java
index 0711f30b8b..81a642af9f 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java
@@ -63,7 +63,6 @@ import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
-
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
@@ -73,155 +72,154 @@ import android.util.Log;
* @author Luis Linietsky <luis.linietsky@gmail.com>
*/
public class HttpRequester {
-
+
private Context context;
- private static final int TTL = 600000; // 10 minutos
- private long cttl=0;
-
- public HttpRequester(){
+ private static final int TTL = 600000; // 10 minutos
+ private long cttl = 0;
+
+ public HttpRequester() {
//Log.d("XXX", "Creando http request sin contexto");
}
-
- public HttpRequester(Context context){
- this.context=context;
+
+ public HttpRequester(Context context) {
+ this.context = context;
//Log.d("XXX", "Creando http request con contexto");
}
-
- public String post(RequestParams params){
- HttpPost httppost = new HttpPost(params.getUrl());
- try {
+
+ public String post(RequestParams params) {
+ HttpPost httppost = new HttpPost(params.getUrl());
+ try {
httppost.setEntity(new UrlEncodedFormEntity(params.toPairsList()));
return request(httppost);
} catch (UnsupportedEncodingException e) {
return null;
}
}
-
- public String get(RequestParams params){
+
+ public String get(RequestParams params) {
String response = getResponseFromCache(params.getUrl());
- if(response == null){
+ if (response == null) {
//Log.d("XXX", "Cache miss!");
- HttpGet httpget = new HttpGet(params.getUrl());
- long timeInit = new Date().getTime();
- response = request(httpget);
- long delay = new Date().getTime() - timeInit;
- Log.d("com.app11tt.android.utils.HttpRequest::get(url)", "Url: " + params.getUrl() + " downloaded in " + String.format("%.03f", delay/1000.0f) + " seconds");
- if(response == null || response.length() == 0){
- response = "";
- }else{
- saveResponseIntoCache(params.getUrl(), response);
- }
+ HttpGet httpget = new HttpGet(params.getUrl());
+ long timeInit = new Date().getTime();
+ response = request(httpget);
+ long delay = new Date().getTime() - timeInit;
+ Log.d("com.app11tt.android.utils.HttpRequest::get(url)", "Url: " + params.getUrl() + " downloaded in " + String.format("%.03f", delay / 1000.0f) + " seconds");
+ if (response == null || response.length() == 0) {
+ response = "";
+ } else {
+ saveResponseIntoCache(params.getUrl(), response);
+ }
}
Log.d("XXX", "Req: " + params.getUrl());
Log.d("XXX", "Resp: " + response);
- return response;
+ return response;
}
-
- private String request(HttpUriRequest request){
+
+ private String request(HttpUriRequest request) {
//Log.d("XXX", "Haciendo request a: " + request.getURI() );
- Log.d("PPP", "Haciendo request a: " + request.getURI() );
+ Log.d("PPP", "Haciendo request a: " + request.getURI());
long init = new Date().getTime();
HttpClient httpclient = getNewHttpClient();
HttpParams httpParameters = httpclient.getParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, 0);
HttpConnectionParams.setSoTimeout(httpParameters, 0);
HttpConnectionParams.setTcpNoDelay(httpParameters, true);
- try {
- HttpResponse response = httpclient.execute(request);
- Log.d("PPP", "Fin de request (" + (new Date().getTime() - init) + ") a: " + request.getURI() );
+ try {
+ HttpResponse response = httpclient.execute(request);
+ Log.d("PPP", "Fin de request (" + (new Date().getTime() - init) + ") a: " + request.getURI());
//Log.d("XXX1", "Status:" + response.getStatusLine().toString());
- if(response.getStatusLine().getStatusCode() == 200){
- String strResponse = EntityUtils.toString(response.getEntity());
+ if (response.getStatusLine().getStatusCode() == 200) {
+ String strResponse = EntityUtils.toString(response.getEntity());
//Log.d("XXX2", strResponse);
- return strResponse;
- }else{
- Log.d("XXX3", "Response status code:" + response.getStatusLine().getStatusCode() + "\n" + EntityUtils.toString(response.getEntity()));
- return null;
- }
-
- } catch (ClientProtocolException e) {
- Log.d("XXX3", e.getMessage());
- } catch (IOException e) {
- Log.d("XXX4", e.getMessage());
- }
+ return strResponse;
+ } else {
+ Log.d("XXX3", "Response status code:" + response.getStatusLine().getStatusCode() + "\n" + EntityUtils.toString(response.getEntity()));
+ return null;
+ }
+
+ } catch (ClientProtocolException e) {
+ Log.d("XXX3", e.getMessage());
+ } catch (IOException e) {
+ Log.d("XXX4", e.getMessage());
+ }
return null;
}
-
+
private HttpClient getNewHttpClient() {
- try {
- KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
- trustStore.load(null, null);
+ try {
+ KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ trustStore.load(null, null);
- SSLSocketFactory sf = new CustomSSLSocketFactory(trustStore);
- sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+ SSLSocketFactory sf = new CustomSSLSocketFactory(trustStore);
+ sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
- HttpParams params = new BasicHttpParams();
- HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
- HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
+ HttpParams params = new BasicHttpParams();
+ HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
+ HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
- SchemeRegistry registry = new SchemeRegistry();
- registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
- registry.register(new Scheme("https", sf, 443));
+ SchemeRegistry registry = new SchemeRegistry();
+ registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
+ registry.register(new Scheme("https", sf, 443));
- ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
+ ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
- return new DefaultHttpClient(ccm, params);
- } catch (Exception e) {
- return new DefaultHttpClient();
- }
+ return new DefaultHttpClient(ccm, params);
+ } catch (Exception e) {
+ return new DefaultHttpClient();
+ }
}
-
+
private static String convertStreamToString(InputStream is) {
- BufferedReader reader = new BufferedReader(new InputStreamReader(is));
- StringBuilder sb = new StringBuilder();
- String line = null;
- try {
- while ((line = reader.readLine()) != null) {
- sb.append((line + "\n"));
- }
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- is.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return sb.toString();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+ StringBuilder sb = new StringBuilder();
+ String line = null;
+ try {
+ while ((line = reader.readLine()) != null) {
+ sb.append((line + "\n"));
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ is.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return sb.toString();
}
- public void saveResponseIntoCache(String request, String response){
- if(context == null){
+ public void saveResponseIntoCache(String request, String response) {
+ if (context == null) {
//Log.d("XXX", "No context, cache failed!");
return;
}
- SharedPreferences sharedPref = context.getSharedPreferences("http_get_cache", Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = sharedPref.edit();
- editor.putString("request_" + Crypt.md5(request), response);
- editor.putLong("request_" + Crypt.md5(request) + "_ttl", new Date().getTime() + getTtl());
- editor.commit();
+ SharedPreferences sharedPref = context.getSharedPreferences("http_get_cache", Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sharedPref.edit();
+ editor.putString("request_" + Crypt.md5(request), response);
+ editor.putLong("request_" + Crypt.md5(request) + "_ttl", new Date().getTime() + getTtl());
+ editor.commit();
}
-
-
- public String getResponseFromCache(String request){
- if(context == null){
+
+ public String getResponseFromCache(String request) {
+ if (context == null) {
Log.d("XXX", "No context, cache miss");
return null;
}
- SharedPreferences sharedPref = context.getSharedPreferences( "http_get_cache", Context.MODE_PRIVATE);
- long ttl = getResponseTtl(request);
- if(ttl == 0l || (new Date().getTime() - ttl) > 0l){
- Log.d("XXX", "Cache invalid ttl:" + ttl + " vs now:" + new Date().getTime());
- return null;
- }
- return sharedPref.getString("request_" + Crypt.md5(request), null);
+ SharedPreferences sharedPref = context.getSharedPreferences("http_get_cache", Context.MODE_PRIVATE);
+ long ttl = getResponseTtl(request);
+ if (ttl == 0l || (new Date().getTime() - ttl) > 0l) {
+ Log.d("XXX", "Cache invalid ttl:" + ttl + " vs now:" + new Date().getTime());
+ return null;
+ }
+ return sharedPref.getString("request_" + Crypt.md5(request), null);
}
- public long getResponseTtl(String request){
- SharedPreferences sharedPref = context.getSharedPreferences(
- "http_get_cache", Context.MODE_PRIVATE);
- return sharedPref.getLong("request_" + Crypt.md5(request) + "_ttl", 0l);
+ public long getResponseTtl(String request) {
+ SharedPreferences sharedPref = context.getSharedPreferences(
+ "http_get_cache", Context.MODE_PRIVATE);
+ return sharedPref.getLong("request_" + Crypt.md5(request) + "_ttl", 0l);
}
public long getTtl() {
@@ -229,7 +227,6 @@ public class HttpRequester {
}
public void setTtl(long ttl) {
- this.cttl = (ttl*1000) + new Date().getTime();
+ this.cttl = (ttl * 1000) + new Date().getTime();
}
-
}
diff --git a/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java b/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java
index ded11550bb..051fed5500 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java
@@ -43,33 +43,33 @@ import org.apache.http.message.BasicNameValuePair;
*/
public class RequestParams {
- private HashMap<String,String> params;
+ private HashMap<String, String> params;
private String url;
-
- public RequestParams(){
- params = new HashMap<String,String>();
+
+ public RequestParams() {
+ params = new HashMap<String, String>();
}
-
- public void put(String key, String value){
+
+ public void put(String key, String value) {
params.put(key, value);
}
-
- public String get(String key){
+
+ public String get(String key) {
return params.get(key);
}
-
- public void remove(Object key){
+
+ public void remove(Object key) {
params.remove(key);
}
-
- public boolean has(String key){
+
+ public boolean has(String key) {
return params.containsKey(key);
}
-
- public List<NameValuePair> toPairsList(){
- List<NameValuePair> fields = new ArrayList<NameValuePair>();
- for(String key : params.keySet()){
+ public List<NameValuePair> toPairsList() {
+ List<NameValuePair> fields = new ArrayList<NameValuePair>();
+
+ for (String key : params.keySet()) {
fields.add(new BasicNameValuePair(key, this.get(key)));
}
return fields;
@@ -82,6 +82,4 @@ public class RequestParams {
public void setUrl(String url) {
this.url = url;
}
-
-
}
diff --git a/platform/haiku/os_haiku.cpp b/platform/haiku/os_haiku.cpp
index ef5a065107..f7196755af 100644
--- a/platform/haiku/os_haiku.cpp
+++ b/platform/haiku/os_haiku.cpp
@@ -105,6 +105,7 @@ void OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p_
context_gl = memnew(ContextGL_Haiku(window));
context_gl->initialize();
context_gl->make_current();
+ context_gl->set_use_vsync(current_video_mode.use_vsync);
/* Port to GLES 3 rasterizer */
//rasterizer = memnew(RasterizerGLES2);
diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm
index b591f80aa7..111cdce2de 100644
--- a/platform/iphone/app_delegate.mm
+++ b/platform/iphone/app_delegate.mm
@@ -35,21 +35,6 @@
#include "main/main.h"
#include "os_iphone.h"
-#ifdef MODULE_FACEBOOKSCORER_IOS_ENABLED
-#include "modules/FacebookScorer_ios/FacebookScorer.h"
-#endif
-
-#ifdef MODULE_GAME_ANALYTICS_ENABLED
-#import "modules/game_analytics/ios/MobileAppTracker.framework/Headers/MobileAppTracker.h"
-//#import "modules/game_analytics/ios/MobileAppTracker.h"
-#import <AdSupport/AdSupport.h>
-#endif
-
-#ifdef MODULE_PARSE_ENABLED
-#import "FBSDKCoreKit/FBSDKCoreKit.h"
-#import <Parse/Parse.h>
-#endif
-
#import "GameController/GameController.h"
#define kFilteringFactor 0.1
@@ -418,11 +403,7 @@ static int frame_count = 0;
OSIPhone::get_singleton()->set_unique_id(String::utf8([uuid UTF8String]));
}; break;
- /*
- case 1: {
- ++frame_count;
- }; break;
-*/
+
case 1: {
Main::setup2();
@@ -453,11 +434,7 @@ static int frame_count = 0;
}
}; break;
- /*
- case 3: {
- ++frame_count;
- }; break;
-*/
+
case 2: {
Main::start();
@@ -558,15 +535,11 @@ static int frame_count = 0;
};
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
-
- printf("****************** did receive memory warning!\n");
OS::get_singleton()->get_main_loop()->notification(
MainLoop::NOTIFICATION_OS_MEMORY_WARNING);
};
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
-
- printf("**************** app delegate init\n");
CGRect rect = [[UIScreen mainScreen] bounds];
[application setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
@@ -603,7 +576,7 @@ static int frame_count = 0;
if (err != 0) {
// bail, things did not go very well for us, should probably output a message on screen with our error code...
exit(0);
- return;
+ return FALSE;
};
view_controller = [[ViewController alloc] init];
@@ -641,43 +614,10 @@ static int frame_count = 0;
// prevent to stop music in another background app
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
-#ifdef MODULE_GAME_ANALYTICS_ENABLED
- printf("********************* didFinishLaunchingWithOptions\n");
- if (!ProjectSettings::get_singleton()->has("mobileapptracker/advertiser_id")) {
- return;
- }
- if (!ProjectSettings::get_singleton()->has("mobileapptracker/conversion_key")) {
- return;
- }
-
- String adid = GLOBAL_DEF("mobileapptracker/advertiser_id", "");
- String convkey = GLOBAL_DEF("mobileapptracker/conversion_key", "");
-
- NSString *advertiser_id =
- [NSString stringWithUTF8String:adid.utf8().get_data()];
- NSString *conversion_key =
- [NSString stringWithUTF8String:convkey.utf8().get_data()];
-
- // Account Configuration info - must be set
- [MobileAppTracker initializeWithMATAdvertiserId:advertiser_id
- MATConversionKey:conversion_key];
-
- // Used to pass us the IFA, enables highly accurate 1-to-1 attribution.
- // Required for many advertising networks.
- [MobileAppTracker
- setAppleAdvertisingIdentifier:[[ASIdentifierManager sharedManager]
- advertisingIdentifier]
- advertisingTrackingEnabled:[[ASIdentifierManager sharedManager]
- isAdvertisingTrackingEnabled]];
-
-#endif
return TRUE;
};
- (void)applicationWillTerminate:(UIApplication *)application {
-
- printf("********************* will terminate\n");
-
[self deinitGameControllers];
if (motionInitialised) {
@@ -692,7 +632,6 @@ static int frame_count = 0;
};
- (void)applicationDidEnterBackground:(UIApplication *)application {
- printf("********************* did enter background\n");
///@TODO maybe add pause motionManager? and where would we unpause it?
if (OS::get_singleton()->get_main_loop())
@@ -706,24 +645,17 @@ static int frame_count = 0;
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
- printf("********************* did enter foreground\n");
// OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
[view_controller.view startAnimation];
}
- (void)applicationWillResignActive:(UIApplication *)application {
- printf("********************* will resign active\n");
// OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
[view_controller.view
stopAnimation]; // FIXME: pause seems to be recommended elsewhere
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
- printf("********************* did become active\n");
-#ifdef MODULE_GAME_ANALYTICS_ENABLED
- printf("********************* mobile app tracker found\n");
- [MobileAppTracker measureSession];
-#endif
if (OS::get_singleton()->get_main_loop())
OS::get_singleton()->get_main_loop()->notification(
MainLoop::NOTIFICATION_WM_FOCUS_IN);
@@ -739,65 +671,6 @@ static int frame_count = 0;
AudioDriverCoreAudio::get_singleton()->start();
}
-- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
-#ifdef MODULE_FACEBOOKSCORER_IOS_ENABLED
- return [[[FacebookScorer sharedInstance] facebook] handleOpenURL:url];
-#else
- return false;
-#endif
-}
-
-// For 4.2+ support
-- (BOOL)application:(UIApplication *)application
- openURL:(NSURL *)url
- sourceApplication:(NSString *)sourceApplication
- annotation:(id)annotation {
-#ifdef MODULE_PARSE_ENABLED
- NSLog(@"Handling application openURL");
- return
- [[FBSDKApplicationDelegate sharedInstance] application:application
- openURL:url
- sourceApplication:sourceApplication
- annotation:annotation];
-#endif
-
-#ifdef MODULE_FACEBOOKSCORER_IOS_ENABLED
- return [[[FacebookScorer sharedInstance] facebook] handleOpenURL:url];
-#else
- return false;
-#endif
-}
-
-- (void)application:(UIApplication *)application
- didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
-#ifdef MODULE_PARSE_ENABLED
- // Store the deviceToken in the current installation and save it to Parse.
- PFInstallation *currentInstallation = [PFInstallation currentInstallation];
- // NSString* token = [[NSString alloc] initWithData:deviceToken
- // encoding:NSUTF8StringEncoding];
- NSLog(@"Device Token : %@ ", deviceToken);
- [currentInstallation setDeviceTokenFromData:deviceToken];
- [currentInstallation saveInBackground];
-#endif
-}
-
-- (void)application:(UIApplication *)application
- didReceiveRemoteNotification:(NSDictionary *)userInfo {
-#ifdef MODULE_PARSE_ENABLED
- [PFPush handlePush:userInfo];
- NSDictionary *aps =
- [userInfo objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
- NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
-
- NSLog(@"Push Notification Payload (app active) %@", aps);
- [defaults setObject:aps forKey:@"notificationInfo"];
- [defaults synchronize];
- if (application.applicationState == UIApplicationStateInactive) {
- [PFAnalytics trackAppOpenedWithRemoteNotificationPayload:userInfo];
- }
-#endif
-}
-
- (void)dealloc {
[window release];
[super dealloc];
diff --git a/platform/iphone/in_app_store.mm b/platform/iphone/in_app_store.mm
index 25f4e1e166..31d3659802 100644
--- a/platform/iphone/in_app_store.mm
+++ b/platform/iphone/in_app_store.mm
@@ -31,10 +31,6 @@
#include "in_app_store.h"
-#ifdef MODULE_FUSEBOXX_ENABLED
-#import "modules/fuseboxx/ios/FuseSDK.h"
-#endif
-
extern "C" {
#import <Foundation/Foundation.h>
#import <StoreKit/StoreKit.h>
@@ -224,10 +220,6 @@ Error InAppStore::request_product_info(Variant p_params) {
[pending_transactions setObject:transaction forKey:transaction.payment.productIdentifier];
}
-#ifdef MODULE_FUSEBOXX_ENABLED
- printf("Registering transaction on Fuseboxx!\n");
- [FuseSDK registerInAppPurchase:transaction];
-#endif
}; break;
case SKPaymentTransactionStateFailed: {
printf("status transaction failed!\n");
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 6cc8be250d..75d0bd1648 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -1089,6 +1089,8 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
[context makeCurrentContext];
+ set_use_vsync(p_desired.use_vsync);
+
[NSApp activateIgnoringOtherApps:YES];
_update_window();
diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp
index 1655caf04b..659f162724 100644
--- a/platform/uwp/os_uwp.cpp
+++ b/platform/uwp/os_uwp.cpp
@@ -241,6 +241,7 @@ void OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_aud
RasterizerGLES3::register_config();
RasterizerGLES3::make_current();
+ gl_context->set_use_vsync(vm.use_vsync);
visual_server = memnew(VisualServerRaster);
// FIXME: Reimplement threaded rendering? Or remove?
diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp
index 5301aa9e95..1b6a8f4a60 100644
--- a/platform/windows/export/export.cpp
+++ b/platform/windows/export/export.cpp
@@ -28,11 +28,135 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "editor/editor_export.h"
+#include "editor/editor_settings.h"
+#include "os/file_access.h"
+#include "os/os.h"
#include "platform/windows/logo.gen.h"
+class EditorExportPlatformWindows : public EditorExportPlatformPC {
+
+public:
+ virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
+ virtual void get_export_options(List<ExportOption> *r_options);
+};
+
+Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+ Error err = EditorExportPlatformPC::export_project(p_preset, p_debug, p_path, p_flags);
+
+ if (err != OK) {
+ return err;
+ }
+
+ String rcedit_path = EditorSettings::get_singleton()->get("export/windows/rcedit");
+
+ if (rcedit_path == String()) {
+ return OK;
+ }
+
+ if (!FileAccess::exists(rcedit_path)) {
+ ERR_PRINTS("Could not find rcedit executable at " + rcedit_path + ", aborting.");
+ return ERR_FILE_NOT_FOUND;
+ }
+
+#ifndef WINDOWS_ENABLED
+ // On non-Windows we need WINE to run rcedit
+ String wine_path = EditorSettings::get_singleton()->get("export/windows/wine");
+
+ if (wine_path != String() && !FileAccess::exists(wine_path)) {
+ ERR_PRINTS("Could not find wine executable at " + wine_path + ", aborting.");
+ return ERR_FILE_NOT_FOUND;
+ }
+
+ if (wine_path == String()) {
+ wine_path = "wine"; // try to run wine from PATH
+ }
+#endif
+
+ String icon_path = p_preset->get("application/icon");
+ String file_verion = p_preset->get("application/file_version");
+ String product_version = p_preset->get("application/product_version");
+ String company_name = p_preset->get("application/company_name");
+ String product_name = p_preset->get("application/product_name");
+ String file_description = p_preset->get("application/file_description");
+ String copyright = p_preset->get("application/copyright");
+ String trademarks = p_preset->get("application/trademarks");
+ String comments = p_preset->get("application/comments");
+
+ List<String> args;
+ args.push_back(p_path);
+ if (icon_path != String()) {
+ args.push_back("--set-icon");
+ args.push_back(icon_path);
+ }
+ if (file_verion != String()) {
+ args.push_back("--set-file-version");
+ args.push_back(file_verion);
+ }
+ if (product_version != String()) {
+ args.push_back("--set-product-version");
+ args.push_back(product_version);
+ }
+ if (company_name != String()) {
+ args.push_back("--set-version-string");
+ args.push_back("CompanyName");
+ args.push_back(company_name);
+ }
+ if (product_name != String()) {
+ args.push_back("--set-version-string");
+ args.push_back("ProductName");
+ args.push_back(product_name);
+ }
+ if (file_description != String()) {
+ args.push_back("--set-version-string");
+ args.push_back("FileDescription");
+ args.push_back(file_description);
+ }
+ if (copyright != String()) {
+ args.push_back("--set-version-string");
+ args.push_back("LegalCopyright");
+ args.push_back(copyright);
+ }
+ if (trademarks != String()) {
+ args.push_back("--set-version-string");
+ args.push_back("LegalTrademarks");
+ args.push_back(trademarks);
+ }
+
+#ifdef WINDOWS_ENABLED
+ OS::get_singleton()->execute(rcedit_path, args, true);
+#else
+ // On non-Windows we need WINE to run rcedit
+ args.push_front(rcedit_path);
+ OS::get_singleton()->execute(wine_path, args, true);
+#endif
+
+ return OK;
+}
+
+void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_options) {
+ EditorExportPlatformPC::get_export_options(r_options);
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_GLOBAL_FILE, "*.ico"), String()));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version"), String()));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version"), String()));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/company_name"), String()));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_name"), String()));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_description"), String()));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), String()));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/trademarks"), String()));
+}
+
void register_windows_exporter() {
- Ref<EditorExportPlatformPC> platform;
+ EDITOR_DEF("export/windows/rcedit", "");
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/rcedit", PROPERTY_HINT_GLOBAL_FILE, "*.exe"));
+#ifndef WINDOWS_ENABLED
+ // On non-Windows we need WINE to run rcedit
+ EDITOR_DEF("export/windows/wine", "");
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/wine", PROPERTY_HINT_GLOBAL_FILE));
+#endif
+
+ Ref<EditorExportPlatformWindows> platform;
platform.instance();
Ref<Image> img = memnew(Image(_windows_logo));
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 79a760f055..41730d33af 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -1074,6 +1074,8 @@ void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
RasterizerGLES3::register_config();
RasterizerGLES3::make_current();
+
+ gl_context->set_use_vsync(video_mode.use_vsync);
#endif
visual_server = memnew(VisualServerRaster);
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index c210a03688..b59fab7088 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -195,14 +195,13 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
XIDeviceInfo *dev = &info[i];
if (!dev->enabled)
continue;
- /*if (dev->use != XIMasterPointer)
- continue;*/
+ if (!(dev->use == XIMasterPointer || dev->use == XIFloatingSlave))
+ continue;
bool direct_touch = false;
for (int j = 0; j < dev->num_classes; j++) {
if (dev->classes[j]->type == XITouchClass && ((XITouchClassInfo *)dev->classes[j])->mode == XIDirectTouch) {
direct_touch = true;
- printf("%d) %d %s\n", i, dev->attachment, dev->name);
break;
}
}
@@ -215,7 +214,7 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
XIFreeDeviceInfo(info);
if (!touch.devices.size()) {
- fprintf(stderr, "No suitable touch device found\n");
+ fprintf(stderr, "No touch devices found\n");
}
}
}
@@ -286,6 +285,8 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
RasterizerGLES3::make_current();
+ context_gl->set_use_vsync(current_videomode.use_vsync);
+
#endif
visual_server = memnew(VisualServerRaster);
@@ -357,7 +358,7 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
// Must be alive after this block
static unsigned char mask_data[XIMaskLen(XI_LASTEVENT)] = {};
- touch.event_mask.deviceid = XIAllMasterDevices;
+ touch.event_mask.deviceid = XIAllDevices;
touch.event_mask.mask_len = sizeof(mask_data);
touch.event_mask.mask = mask_data;
@@ -368,12 +369,14 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
XISelectEvents(x11_display, x11_window, &touch.event_mask, 1);
- XIClearMask(touch.event_mask.mask, XI_TouchOwnership);
+ // Disabled by now since grabbing also blocks mouse events
+ // (they are received as extended events instead of standard events)
+ /*XIClearMask(touch.event_mask.mask, XI_TouchOwnership);
// Grab touch devices to avoid OS gesture interference
for (int i = 0; i < touch.devices.size(); ++i) {
XIGrabDevice(x11_display, touch.devices[i], x11_window, CurrentTime, None, XIGrabModeAsync, XIGrabModeAsync, False, &touch.event_mask);
- }
+ }*/
}
#endif
@@ -510,15 +513,14 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
power_manager = memnew(PowerX11);
XEvent xevent;
- while (XCheckIfEvent(x11_display, &xevent, _check_window_events, NULL)) {
- _window_changed(&xevent);
+ while (XPending(x11_display) > 0) {
+ XNextEvent(x11_display, &xevent);
+ if (xevent.type == ConfigureNotify) {
+ _window_changed(&xevent);
+ }
}
}
-int OS_X11::_check_window_events(Display *display, XEvent *event, char *arg) {
- if (event->type == ConfigureNotify) return 1;
- return 0;
-}
void OS_X11::xim_destroy_callback(::XIM im, ::XPointer client_data,
::XPointer call_data) {
@@ -1511,7 +1513,7 @@ void OS_X11::process_xevents() {
#ifdef TOUCH_ENABLED
if (XGetEventData(x11_display, &event.xcookie)) {
- if (event.xcookie.extension == touch.opcode) {
+ if (event.xcookie.type == GenericEvent && event.xcookie.extension == touch.opcode) {
XIDeviceEvent *event_data = (XIDeviceEvent *)event.xcookie.data;
int index = event_data->detail;
@@ -1520,7 +1522,8 @@ void OS_X11::process_xevents() {
switch (event_data->evtype) {
case XI_TouchBegin: // Fall-through
- XIAllowTouchEvents(x11_display, event_data->deviceid, event_data->detail, x11_window, XIAcceptTouch);
+ // Disabled hand-in-hand with the grabbing
+ //XIAllowTouchEvents(x11_display, event_data->deviceid, event_data->detail, x11_window, XIAcceptTouch);
case XI_TouchEnd: {
@@ -1566,9 +1569,8 @@ void OS_X11::process_xevents() {
} break;
}
}
-
- XFreeEventData(x11_display, &event.xcookie);
}
+ XFreeEventData(x11_display, &event.xcookie);
#endif
switch (event.type) {
@@ -1614,10 +1616,10 @@ void OS_X11::process_xevents() {
GrabModeAsync, GrabModeAsync, x11_window, None, CurrentTime);
}
#ifdef TOUCH_ENABLED
- // Grab touch devices to avoid OS gesture interference
- for (int i = 0; i < touch.devices.size(); ++i) {
+ // Grab touch devices to avoid OS gesture interference
+ /*for (int i = 0; i < touch.devices.size(); ++i) {
XIGrabDevice(x11_display, touch.devices[i], x11_window, CurrentTime, None, XIGrabModeAsync, XIGrabModeAsync, False, &touch.event_mask);
- }
+ }*/
#endif
if (xic) {
XSetICFocus(xic);
@@ -1637,9 +1639,9 @@ void OS_X11::process_xevents() {
}
#ifdef TOUCH_ENABLED
// Ungrab touch devices so input works as usual while we are unfocused
- for (int i = 0; i < touch.devices.size(); ++i) {
+ /*for (int i = 0; i < touch.devices.size(); ++i) {
XIUngrabDevice(x11_display, touch.devices[i], CurrentTime);
- }
+ }*/
// Release every pointer to avoid sticky points
for (Map<int, Vector2>::Element *E = touch.state.front(); E; E = E->next()) {
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index 84dff2e089..244c69ee2b 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -199,7 +199,6 @@ protected:
virtual void set_main_loop(MainLoop *p_main_loop);
void _window_changed(XEvent *xevent);
- static int _check_window_events(Display *display, XEvent *xevent, char *arg);
public:
virtual String get_name();
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 768d5185d7..82123d12ac 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -623,6 +623,29 @@ void CanvasItem::draw_polyline_colors(const Vector<Point2> &p_points, const Vect
VisualServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, p_colors, p_width, p_antialiased);
}
+
+void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_color, float p_width, bool p_antialiased) {
+
+ if (!drawing) {
+ ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
+ ERR_FAIL();
+ }
+
+ Vector<Color> colors;
+ colors.push_back(p_color);
+ VisualServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, colors, p_width, p_antialiased);
+}
+
+void CanvasItem::draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) {
+
+ if (!drawing) {
+ ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
+ ERR_FAIL();
+ }
+
+ VisualServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, p_colors, p_width, p_antialiased);
+}
+
void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled) {
if (!drawing) {
@@ -979,6 +1002,8 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width", "antialiased"), &CanvasItem::draw_line, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("draw_multiline", "points", "color", "width", "antialiased"), &CanvasItem::draw_multiline, DEFVAL(1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("draw_multiline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_multiline_colors, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled"), &CanvasItem::draw_rect, DEFVAL(true));
ClassDB::bind_method(D_METHOD("draw_circle", "position", "radius", "color"), &CanvasItem::draw_circle);
ClassDB::bind_method(D_METHOD("draw_texture", "texture", "position", "modulate", "normal_map"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(Variant()));
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index ccbb528d6f..2384c0f370 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -268,6 +268,8 @@ public:
void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false);
void draw_polyline(const Vector<Point2> &p_points, const Color &p_color, float p_width = 1.0, bool p_antialiased = false);
void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false);
+ void draw_multiline(const Vector<Point2> &p_points, const Color &p_color, float p_width = 1.0, bool p_antialiased = false);
+ void draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false);
void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true);
void draw_circle(const Point2 &p_pos, float p_radius, const Color &p_color);
void draw_texture(const Ref<Texture> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1), const Ref<Texture> &p_normal_map = Ref<Texture>());
diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp
index e1c7331393..4029ef137b 100644
--- a/scene/2d/path_2d.cpp
+++ b/scene/2d/path_2d.cpp
@@ -107,34 +107,56 @@ void PathFollow2D::_update_transform() {
if (!c.is_valid())
return;
- if (delta_offset == 0) {
- return;
- }
-
- float o = offset;
+ float path_length = c->get_baked_length();
+ float bounded_offset = offset;
if (loop)
- o = Math::fposmod(o, c->get_baked_length());
-
- Vector2 pos = c->interpolate_baked(o, cubic);
+ bounded_offset = Math::fposmod(bounded_offset, path_length);
+ else
+ bounded_offset = CLAMP(bounded_offset, 0, path_length);
- Vector2 displacement_offset = Vector2(h_offset, v_offset);
+ Vector2 pos = c->interpolate_baked(bounded_offset, cubic);
if (rotate) {
+ float ahead = bounded_offset + lookahead;
+
+ if (loop && ahead >= path_length) {
+ // If our lookahead will loop, we need to check if the path is closed.
+ int point_count = c->get_point_count();
+ if (point_count > 0) {
+ Vector2 start_point = c->get_point_position(0);
+ Vector2 end_point = c->get_point_position(point_count - 1);
+ if (start_point == end_point) {
+ // Since the path is closed we want to 'smooth off'
+ // the corner at the start/end.
+ // So we wrap the lookahead back round.
+ ahead = Math::fmod(ahead, path_length);
+ }
+ }
+ }
+
+ Vector2 ahead_pos = c->interpolate_baked(ahead, cubic);
- Vector2 t_prev = (pos - c->interpolate_baked(o - delta_offset, cubic)).normalized();
- Vector2 t_next = (c->interpolate_baked(o + delta_offset, cubic) - pos).normalized();
+ Vector2 tangent_to_curve;
+ if (ahead_pos == pos) {
+ // This will happen at the end of non-looping or non-closed paths.
+ // We'll try a look behind instead, in order to get a meaningful angle.
+ tangent_to_curve =
+ (pos - c->interpolate_baked(bounded_offset - lookahead, cubic)).normalized();
+ } else {
+ tangent_to_curve = (ahead_pos - pos).normalized();
+ }
- float angle = t_prev.angle_to(t_next);
+ Vector2 normal_of_curve = -tangent_to_curve.tangent();
- set_rotation(get_rotation() + angle);
+ pos += tangent_to_curve * h_offset;
+ pos += normal_of_curve * v_offset;
- Vector2 n = t_next;
- Vector2 t = -n.tangent();
- pos += n * h_offset + t * v_offset;
+ set_rotation(tangent_to_curve.angle());
} else {
- pos += displacement_offset;
+ pos.x += h_offset;
+ pos.y += v_offset;
}
set_position(pos);
@@ -185,6 +207,8 @@ bool PathFollow2D::_set(const StringName &p_name, const Variant &p_value) {
set_cubic_interpolation(p_value);
} else if (String(p_name) == "loop") {
set_loop(p_value);
+ } else if (String(p_name) == "lookahead") {
+ set_lookahead(p_value);
} else
return false;
@@ -207,6 +231,8 @@ bool PathFollow2D::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = cubic;
} else if (String(p_name) == "loop") {
r_ret = loop;
+ } else if (String(p_name) == "lookahead") {
+ r_ret = lookahead;
} else
return false;
@@ -224,6 +250,7 @@ void PathFollow2D::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::BOOL, "rotate"));
p_list->push_back(PropertyInfo(Variant::BOOL, "cubic_interp"));
p_list->push_back(PropertyInfo(Variant::BOOL, "loop"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "lookahead", PROPERTY_HINT_RANGE, "0.001,1024.0,0.001"));
}
String PathFollow2D::get_configuration_warning() const {
@@ -263,7 +290,7 @@ void PathFollow2D::_bind_methods() {
}
void PathFollow2D::set_offset(float p_offset) {
- delta_offset = p_offset - offset;
+
offset = p_offset;
if (path)
_update_transform();
@@ -314,6 +341,16 @@ float PathFollow2D::get_unit_offset() const {
return 0;
}
+void PathFollow2D::set_lookahead(float p_lookahead) {
+
+ lookahead = p_lookahead;
+}
+
+float PathFollow2D::get_lookahead() const {
+
+ return lookahead;
+}
+
void PathFollow2D::set_rotate(bool p_rotate) {
rotate = p_rotate;
@@ -338,11 +375,11 @@ bool PathFollow2D::has_loop() const {
PathFollow2D::PathFollow2D() {
offset = 0;
- delta_offset = 0;
h_offset = 0;
v_offset = 0;
path = NULL;
rotate = true;
cubic = true;
loop = true;
+ lookahead = 4;
}
diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h
index f5ba3a3d32..88a0abdea9 100644
--- a/scene/2d/path_2d.h
+++ b/scene/2d/path_2d.h
@@ -60,9 +60,9 @@ public:
private:
Path2D *path;
real_t offset;
- real_t delta_offset; // change in offset since last _update_transform
real_t h_offset;
real_t v_offset;
+ real_t lookahead;
bool cubic;
bool loop;
bool rotate;
@@ -90,6 +90,9 @@ public:
void set_unit_offset(float p_unit_offset);
float get_unit_offset() const;
+ void set_lookahead(float p_lookahead);
+ float get_lookahead() const;
+
void set_loop(bool p_loop);
bool has_loop() const;
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index c0d0a6e011..1e34372d1e 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "tile_map.h"
+
#include "io/marshalls.h"
#include "method_bind_ext.gen.inc"
#include "os/os.h"
@@ -169,10 +170,12 @@ void TileMap::set_cell_size(Size2 p_size) {
_recreate_quadrants();
emit_signal("settings_changed");
}
+
Size2 TileMap::get_cell_size() const {
return cell_size;
}
+
void TileMap::set_quadrant_size(int p_size) {
ERR_FAIL_COND(p_size < 1);
@@ -182,32 +185,12 @@ void TileMap::set_quadrant_size(int p_size) {
_recreate_quadrants();
emit_signal("settings_changed");
}
+
int TileMap::get_quadrant_size() const {
return quadrant_size;
}
-void TileMap::set_center_x(bool p_enable) {
-
- center_x = p_enable;
- _recreate_quadrants();
- emit_signal("settings_changed");
-}
-bool TileMap::get_center_x() const {
-
- return center_x;
-}
-void TileMap::set_center_y(bool p_enable) {
-
- center_y = p_enable;
- _recreate_quadrants();
- emit_signal("settings_changed");
-}
-bool TileMap::get_center_y() const {
-
- return center_y;
-}
-
void TileMap::_fix_cell_transform(Transform2D &xform, const Cell &p_cell, const Vector2 &p_offset, const Size2 &p_sc) {
Size2 s = p_sc;
@@ -513,16 +496,13 @@ void TileMap::_update_dirty_quadrants() {
}
Ref<OccluderPolygon2D> occluder;
- Vector2 occluder_ofs;
if (tile_set->tile_get_is_autotile(c.id)) {
occluder = tile_set->autotile_get_light_occluder(c.id, Vector2(c.autotile_coord_x, c.autotile_coord_y));
- occluder_ofs = tile_set->tile_get_occluder_offset(c.id);
} else {
occluder = tile_set->tile_get_light_occluder(c.id);
- occluder_ofs = Vector2();
}
if (occluder.is_valid()) {
-
+ Vector2 occluder_ofs = tile_set->tile_get_occluder_offset(c.id);
Transform2D xform;
xform.set_origin(offset.floor() + q.pos);
_fix_cell_transform(xform, c, occluder_ofs + center_ofs, s);
@@ -968,14 +948,14 @@ void TileMap::_set_tile_data(const PoolVector<int> &p_data) {
int c = p_data.size();
PoolVector<int>::Read r = p_data.read();
- int offset = (format == FORMAT_2_1_5) ? 3 : 2;
+ int offset = (format == FORMAT_2) ? 3 : 2;
clear();
for (int i = 0; i < c; i += offset) {
const uint8_t *ptr = (const uint8_t *)&r[i];
uint8_t local[12];
- for (int j = 0; j < ((format == FORMAT_2_1_5) ? 12 : 8); j++)
+ for (int j = 0; j < ((format == FORMAT_2) ? 12 : 8); j++)
local[j] = ptr[j];
#ifdef BIG_ENDIAN_ENABLED
@@ -985,7 +965,7 @@ void TileMap::_set_tile_data(const PoolVector<int> &p_data) {
SWAP(local[4], local[7]);
SWAP(local[5], local[6]);
//TODO: ask someone to check this...
- if (FORMAT == FORMAT_2_1_5) {
+ if (FORMAT == FORMAT_2) {
SWAP(local[8], local[11]);
SWAP(local[9], local[10]);
}
@@ -1000,7 +980,7 @@ void TileMap::_set_tile_data(const PoolVector<int> &p_data) {
v &= (1 << 29) - 1;
int16_t coord_x;
int16_t coord_y;
- if (format == FORMAT_2_1_5) {
+ if (format == FORMAT_2) {
coord_x = decode_uint16(&local[8]);
coord_y = decode_uint16(&local[10]);
}
@@ -1018,6 +998,8 @@ PoolVector<int> TileMap::_get_tile_data() const {
data.resize(tile_map.size() * 3);
PoolVector<int>::Write w = data.write();
+ format = FORMAT_2;
+
int idx = 0;
for (const Map<PosKey, Cell>::Element *E = tile_map.front(); E; E = E->next()) {
uint8_t *ptr = (uint8_t *)&w[idx];
@@ -1298,7 +1280,7 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
bool TileMap::_get(const StringName &p_name, Variant &r_ret) const {
if (p_name == "format") {
- r_ret = FORMAT_2_1_5;
+ r_ret = FORMAT_2;
return true;
} else if (p_name == "tile_data") {
r_ret = _get_tile_data();
@@ -1474,12 +1456,6 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_tile_origin", "origin"), &TileMap::set_tile_origin);
ClassDB::bind_method(D_METHOD("get_tile_origin"), &TileMap::get_tile_origin);
- ClassDB::bind_method(D_METHOD("set_center_x", "enable"), &TileMap::set_center_x);
- ClassDB::bind_method(D_METHOD("get_center_x"), &TileMap::get_center_x);
-
- ClassDB::bind_method(D_METHOD("set_center_y", "enable"), &TileMap::set_center_y);
- ClassDB::bind_method(D_METHOD("get_center_y"), &TileMap::get_center_y);
-
ClassDB::bind_method(D_METHOD("set_clip_uv", "enable"), &TileMap::set_clip_uv);
ClassDB::bind_method(D_METHOD("get_clip_uv"), &TileMap::get_clip_uv);
@@ -1581,8 +1557,6 @@ TileMap::TileMap() {
quadrant_order_dirty = false;
quadrant_size = 16;
cell_size = Size2(64, 64);
- center_x = false;
- center_y = false;
collision_layer = 1;
collision_mask = 1;
friction = 1;
@@ -1594,7 +1568,7 @@ TileMap::TileMap() {
y_sort_mode = false;
occluder_light_mask = 1;
clip_uv = false;
- format = FORMAT_2_1_4; //Always initialize with the lowest format
+ format = FORMAT_1; //Always initialize with the lowest format
fp_adjust = 0.00001;
tile_origin = TILE_ORIGIN_TOP_LEFT;
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index edc9de0543..e5608884c4 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -61,14 +61,13 @@ public:
private:
enum DataFormat {
- FORMAT_2_1_4 = 0,
- FORMAT_2_1_5
+ FORMAT_1 = 0,
+ FORMAT_2
};
Ref<TileSet> tile_set;
Size2i cell_size;
int quadrant_size;
- bool center_x, center_y;
Mode mode;
Transform2D custom_transform;
HalfOffset half_offset;
@@ -178,7 +177,7 @@ private:
float bounce;
uint32_t collision_layer;
uint32_t collision_mask;
- DataFormat format;
+ mutable DataFormat format;
TileOrigin tile_origin;
@@ -231,11 +230,6 @@ public:
void set_quadrant_size(int p_size);
int get_quadrant_size() const;
- void set_center_x(bool p_enable);
- bool get_center_x() const;
- void set_center_y(bool p_enable);
- bool get_center_y() const;
-
void set_cell(int p_x, int p_y, int p_tile, bool p_flip_x = false, bool p_flip_y = false, bool p_transpose = false, Vector2 p_autotile_coord = Vector2());
int get_cell(int p_x, int p_y) const;
bool is_cell_x_flipped(int p_x, int p_y) const;
diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp
index 8e2f87738a..1f2b43165e 100644
--- a/scene/3d/gi_probe.cpp
+++ b/scene/3d/gi_probe.cpp
@@ -1284,8 +1284,11 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
_create_debug_mesh(&baker);
} else {
- Ref<GIProbeData> probe_data;
- probe_data.instance();
+ Ref<GIProbeData> probe_data = get_probe_data();
+
+ if (probe_data.is_null())
+ probe_data.instance();
+
probe_data->set_bounds(AABB(-extents, extents * 2.0));
probe_data->set_cell_size(baker.po2_bounds.size[longest_axis] / baker.axis_cell_size[longest_axis]);
probe_data->set_dynamic_data(data);
diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp
index c137b7e8ff..821f1a5a78 100644
--- a/scene/3d/particles.cpp
+++ b/scene/3d/particles.cpp
@@ -1189,7 +1189,7 @@ void ParticlesMaterial::set_flag(Flags p_flag, bool p_enable) {
ERR_FAIL_INDEX(p_flag, FLAG_MAX);
flags[p_flag] = p_enable;
_queue_shader_change();
- if (p_flag==FLAG_DISABLE_Z) {
+ if (p_flag == FLAG_DISABLE_Z) {
_change_notify();
}
}
@@ -1379,7 +1379,7 @@ void ParticlesMaterial::_validate_property(PropertyInfo &property) const {
}
if (property.name.begins_with("orbit_") && !flags[FLAG_DISABLE_Z]) {
- property.usage=0;
+ property.usage = 0;
}
}
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index f2f00bb617..c5f817d317 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -734,15 +734,12 @@ bool RigidBody::is_contact_monitor_enabled() const {
return contact_monitor != NULL;
}
-void RigidBody::set_axis_lock(AxisLock p_lock) {
-
- axis_lock = p_lock;
- PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(), PhysicsServer::BodyAxisLock(axis_lock));
+void RigidBody::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock) {
+ PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock);
}
-RigidBody::AxisLock RigidBody::get_axis_lock() const {
-
- return axis_lock;
+bool RigidBody::get_axis_lock(PhysicsServer::BodyAxis p_axis) const {
+ return PhysicsServer::get_singleton()->body_is_axis_locked(get_rid(), p_axis);
}
Array RigidBody::get_colliding_bodies() const {
@@ -837,8 +834,8 @@ void RigidBody::_bind_methods() {
ClassDB::bind_method(D_METHOD("_body_enter_tree"), &RigidBody::_body_enter_tree);
ClassDB::bind_method(D_METHOD("_body_exit_tree"), &RigidBody::_body_exit_tree);
- ClassDB::bind_method(D_METHOD("set_axis_lock", "axis_lock"), &RigidBody::set_axis_lock);
- ClassDB::bind_method(D_METHOD("get_axis_lock"), &RigidBody::get_axis_lock);
+ ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &RigidBody::set_axis_lock);
+ ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &RigidBody::get_axis_lock);
ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody::get_colliding_bodies);
@@ -856,7 +853,13 @@ void RigidBody::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "axis_lock", PROPERTY_HINT_ENUM, "Disabled,Lock X,Lock Y,Lock Z"), "set_axis_lock", "get_axis_lock");
+ ADD_GROUP("Axis Lock", "axis_lock_");
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_x"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_X);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_y"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Y);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_z"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Z);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_x"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_X);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_y"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_Y);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_z"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_Z);
ADD_GROUP("Linear", "linear_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "linear_damp", PROPERTY_HINT_RANGE, "-1,128,0.01"), "set_linear_damp", "get_linear_damp");
@@ -874,11 +877,6 @@ void RigidBody::_bind_methods() {
BIND_ENUM_CONSTANT(MODE_STATIC);
BIND_ENUM_CONSTANT(MODE_CHARACTER);
BIND_ENUM_CONSTANT(MODE_KINEMATIC);
-
- BIND_ENUM_CONSTANT(AXIS_LOCK_DISABLED);
- BIND_ENUM_CONSTANT(AXIS_LOCK_X);
- BIND_ENUM_CONSTANT(AXIS_LOCK_Y);
- BIND_ENUM_CONSTANT(AXIS_LOCK_Z);
}
RigidBody::RigidBody() :
@@ -904,8 +902,6 @@ RigidBody::RigidBody() :
contact_monitor = NULL;
can_sleep = true;
- axis_lock = AXIS_LOCK_DISABLED;
-
PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
}
@@ -952,6 +948,12 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, Collision &r_colli
r_collision.local_shape = result.collision_local_shape;
}
+ for (int i = 0; i < 3; i++) {
+ if (locked_axis & (1 << i)) {
+ result.motion[i] = 0;
+ }
+ }
+
gt.origin += result.motion;
set_global_transform(gt);
@@ -960,9 +962,16 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, Collision &r_colli
Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) {
- Vector3 motion = (floor_velocity + p_linear_velocity) * get_physics_process_delta_time();
Vector3 lv = p_linear_velocity;
+ for (int i = 0; i < 3; i++) {
+ if (locked_axis & (1 << i)) {
+ lv[i] = 0;
+ }
+ }
+
+ Vector3 motion = (floor_velocity + lv) * get_physics_process_delta_time();
+
on_floor = false;
on_ceiling = false;
on_wall = false;
@@ -1008,6 +1017,12 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
motion = motion.slide(n);
lv = lv.slide(n);
+ for (int i = 0; i < 3; i++) {
+ if (locked_axis & (1 << i)) {
+ lv[i] = 0;
+ }
+ }
+
colliders.push_back(collision);
} else {
@@ -1047,6 +1062,14 @@ bool KinematicBody::test_move(const Transform &p_from, const Vector3 &p_motion)
return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion);
}
+void KinematicBody::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock) {
+ PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock);
+}
+
+bool KinematicBody::get_axis_lock(PhysicsServer::BodyAxis p_axis) const {
+ return PhysicsServer::get_singleton()->body_is_axis_locked(get_rid(), p_axis);
+}
+
void KinematicBody::set_safe_margin(float p_margin) {
margin = p_margin;
@@ -1095,12 +1118,23 @@ void KinematicBody::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_on_wall"), &KinematicBody::is_on_wall);
ClassDB::bind_method(D_METHOD("get_floor_velocity"), &KinematicBody::get_floor_velocity);
+ ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &KinematicBody::set_axis_lock);
+ ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &KinematicBody::get_axis_lock);
+
ClassDB::bind_method(D_METHOD("set_safe_margin", "pixels"), &KinematicBody::set_safe_margin);
ClassDB::bind_method(D_METHOD("get_safe_margin"), &KinematicBody::get_safe_margin);
ClassDB::bind_method(D_METHOD("get_slide_count"), &KinematicBody::get_slide_count);
ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &KinematicBody::_get_slide_collision);
+ ADD_GROUP("Axis Lock", "axis_lock_");
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_x"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_X);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_y"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Y);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_z"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Z);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_x"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_X);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_y"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_Y);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_z"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_Z);
+
ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
}
@@ -1108,7 +1142,7 @@ KinematicBody::KinematicBody() :
PhysicsBody(PhysicsServer::BODY_MODE_KINEMATIC) {
margin = 0.001;
-
+ locked_axis = 0;
on_floor = false;
on_ceiling = false;
on_wall = false;
diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h
index f88b3860dc..9d9feda0b2 100644
--- a/scene/3d/physics_body.h
+++ b/scene/3d/physics_body.h
@@ -114,13 +114,6 @@ public:
MODE_KINEMATIC,
};
- enum AxisLock {
- AXIS_LOCK_DISABLED,
- AXIS_LOCK_X,
- AXIS_LOCK_Y,
- AXIS_LOCK_Z,
- };
-
private:
bool can_sleep;
PhysicsDirectBodyState *state;
@@ -139,8 +132,6 @@ private:
bool sleeping;
bool ccd;
- AxisLock axis_lock;
-
int max_contacts_reported;
bool custom_integrator;
@@ -245,8 +236,8 @@ public:
void set_use_continuous_collision_detection(bool p_enable);
bool is_using_continuous_collision_detection() const;
- void set_axis_lock(AxisLock p_lock);
- AxisLock get_axis_lock() const;
+ void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock);
+ bool get_axis_lock(PhysicsServer::BodyAxis p_axis) const;
Array get_colliding_bodies() const;
@@ -259,7 +250,6 @@ public:
};
VARIANT_ENUM_CAST(RigidBody::Mode);
-VARIANT_ENUM_CAST(RigidBody::AxisLock);
class KinematicCollision;
@@ -281,6 +271,8 @@ public:
};
private:
+ uint16_t locked_axis;
+
float margin;
Vector3 floor_velocity;
@@ -303,6 +295,9 @@ public:
bool move_and_collide(const Vector3 &p_motion, Collision &r_collision);
bool test_move(const Transform &p_from, const Vector3 &p_motion);
+ void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock);
+ bool get_axis_lock(PhysicsServer::BodyAxis p_axis) const;
+
void set_safe_margin(float p_margin);
float get_safe_margin() const;
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index f3e750d0da..e866e665d8 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -364,6 +364,9 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
if (!nc) // no node cache for this track, skip it
continue;
+ if (!a->track_is_enabled(i))
+ continue; // do nothing if the track is disabled
+
if (a->track_get_key_count(i) == 0)
continue; // do nothing if track is empty
@@ -1325,8 +1328,6 @@ void AnimationPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("seek", "seconds", "update"), &AnimationPlayer::seek, DEFVAL(false));
ClassDB::bind_method(D_METHOD("advance", "delta"), &AnimationPlayer::advance);
- ClassDB::bind_method(D_METHOD("get_anim_position"), &AnimationPlayer::get_current_animation_position);
- ClassDB::bind_method(D_METHOD("get_anim_length"), &AnimationPlayer::get_current_animation_length);
ClassDB::bind_method(D_METHOD("find_animation", "animation"), &AnimationPlayer::find_animation);
@@ -1335,6 +1336,9 @@ void AnimationPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_animation_process_mode", "mode"), &AnimationPlayer::set_animation_process_mode);
ClassDB::bind_method(D_METHOD("get_animation_process_mode"), &AnimationPlayer::get_animation_process_mode);
+ ClassDB::bind_method(D_METHOD("get_current_animation_position"), &AnimationPlayer::get_current_animation_position);
+ ClassDB::bind_method(D_METHOD("get_current_animation_length"), &AnimationPlayer::get_current_animation_length);
+
ADD_GROUP("Playback Options", "playback_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_animation_process_mode", "get_animation_process_mode");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "playback_default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_default_blend_time", "get_default_blend_time");
@@ -1343,7 +1347,7 @@ void AnimationPlayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "autoplay"), "set_autoplay", "get_autoplay");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed_scale"), "set_speed_scale", "get_speed_scale");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "is_active");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_anim"), "set_current_anim", "get_current_anim");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_animation"), "set_current_animation", "get_current_animation");
ADD_SIGNAL(MethodInfo("animation_finished", PropertyInfo(Variant::STRING, "name")));
ADD_SIGNAL(MethodInfo("animation_changed", PropertyInfo(Variant::STRING, "old_name"), PropertyInfo(Variant::STRING, "new_name")));
diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp
index 23eccec82f..32f82fe6b8 100644
--- a/scene/animation/animation_tree_player.cpp
+++ b/scene/animation/animation_tree_player.cpp
@@ -831,7 +831,7 @@ void AnimationTreePlayer::_process_animation(float p_delta) {
for (List<AnimationNode::TrackRef>::Element *E = anim_list->tref.front(); E; E = E->next()) {
AnimationNode::TrackRef &tr = E->get();
- if (tr.track == NULL || tr.local_track < 0 || tr.weight < CMP_EPSILON)
+ if (tr.track == NULL || tr.local_track < 0 || tr.weight < CMP_EPSILON || !a->track_is_enabled(tr.local_track))
continue;
switch (a->track_get_type(tr.local_track)) {
@@ -1796,6 +1796,10 @@ void AnimationTreePlayer::_bind_methods() {
ADD_GROUP("Playback", "playback_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_animation_process_mode", "get_animation_process_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "master_player"), "set_master_player", "get_master_player");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "base_path"), "set_base_path", "get_base_path");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "is_active");
+
BIND_ENUM_CONSTANT(NODE_OUTPUT);
BIND_ENUM_CONSTANT(NODE_ANIMATION);
BIND_ENUM_CONSTANT(NODE_ONESHOT);
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index 1fa03f81f4..47977f0283 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -55,6 +55,10 @@ Size2 Button::get_minimum_size() const {
return get_stylebox("normal")->get_minimum_size() + minsize;
}
+void Button::_set_internal_margin(Margin p_margin, float p_value) {
+ _internal_margin[p_margin] = p_value;
+}
+
void Button::_notification(int p_what) {
if (p_what == NOTIFICATION_TRANSLATION_CHANGED) {
@@ -136,11 +140,11 @@ void Button::_notification(int p_what) {
Point2 icon_ofs = (!_icon.is_null()) ? Point2(_icon->get_width() + get_constant("hseparation"), 0) : Point2();
int text_clip = size.width - style->get_minimum_size().width - icon_ofs.width;
- Point2 text_ofs = (size - style->get_minimum_size() - icon_ofs - font->get_string_size(xl_text)) / 2.0;
+ Point2 text_ofs = (size - style->get_minimum_size() - icon_ofs - font->get_string_size(xl_text) - Point2(_internal_margin[MARGIN_RIGHT] - _internal_margin[MARGIN_LEFT], 0)) / 2.0;
switch (align) {
case ALIGN_LEFT: {
- text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x;
+ text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x + _internal_margin[MARGIN_LEFT] + get_constant("hseparation");
text_ofs.y += style->get_offset().y;
} break;
case ALIGN_CENTER: {
@@ -150,7 +154,11 @@ void Button::_notification(int p_what) {
text_ofs += style->get_offset();
} break;
case ALIGN_RIGHT: {
- text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size(xl_text).x;
+ if (_internal_margin[MARGIN_RIGHT] > 0) {
+ text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size(xl_text).x - _internal_margin[MARGIN_RIGHT] - get_constant("hseparation");
+ } else {
+ text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size(xl_text).x;
+ }
text_ofs.y += style->get_offset().y;
} break;
}
@@ -162,7 +170,11 @@ void Button::_notification(int p_what) {
int valign = size.height - style->get_minimum_size().y;
if (is_disabled())
color_icon.a = 0.4;
- _icon->draw(ci, style->get_offset() + Point2(0, Math::floor((valign - _icon->get_height()) / 2.0)), color_icon);
+ if (_internal_margin[MARGIN_LEFT] > 0) {
+ _icon->draw(ci, style->get_offset() + Point2(_internal_margin[MARGIN_LEFT] + get_constant("hseparation"), Math::floor((valign - _icon->get_height()) / 2.0)), color_icon);
+ } else {
+ _icon->draw(ci, style->get_offset() + Point2(0, Math::floor((valign - _icon->get_height()) / 2.0)), color_icon);
+ }
}
}
}
@@ -253,7 +265,7 @@ void Button::_bind_methods() {
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_button_icon", "get_button_icon");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat");
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "get_clip_text");
- ADD_PROPERTYNO(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_text_align", "get_text_align");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_text_align", "get_text_align");
}
Button::Button(const String &p_text) {
@@ -263,6 +275,10 @@ Button::Button(const String &p_text) {
set_mouse_filter(MOUSE_FILTER_STOP);
set_text(p_text);
align = ALIGN_CENTER;
+
+ for (int i = 0; i < 4; i++) {
+ _internal_margin[i] = 0;
+ }
}
Button::~Button() {
diff --git a/scene/gui/button.h b/scene/gui/button.h
index dd6e730b86..35488582de 100644
--- a/scene/gui/button.h
+++ b/scene/gui/button.h
@@ -53,9 +53,11 @@ private:
Ref<Texture> icon;
bool clip_text;
TextAlign align;
+ float _internal_margin[4];
protected:
virtual Size2 get_minimum_size() const;
+ void _set_internal_margin(Margin p_margin, float p_value);
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp
index 00f6153062..bf8156b92b 100644
--- a/scene/gui/check_box.cpp
+++ b/scene/gui/check_box.cpp
@@ -31,18 +31,54 @@
#include "servers/visual_server.h"
+Size2 CheckBox::get_icon_size() const {
+ Ref<Texture> checked = Control::get_icon("checked");
+ Ref<Texture> unchecked = Control::get_icon("unchecked");
+ Ref<Texture> radio_checked = Control::get_icon("radio_checked");
+ Ref<Texture> radio_unchecked = Control::get_icon("radio_unchecked");
+
+ Size2 tex_size = Size2(0, 0);
+ if (!checked.is_null())
+ tex_size = Size2(checked->get_width(), checked->get_height());
+ if (!unchecked.is_null())
+ tex_size = Size2(MAX(tex_size.width, unchecked->get_width()), MAX(tex_size.height, unchecked->get_height()));
+ if (!radio_checked.is_null())
+ tex_size = Size2(MAX(tex_size.width, radio_checked->get_width()), MAX(tex_size.height, radio_checked->get_height()));
+ if (!radio_unchecked.is_null())
+ tex_size = Size2(MAX(tex_size.width, radio_unchecked->get_width()), MAX(tex_size.height, radio_unchecked->get_height()));
+ return tex_size;
+}
+
+Size2 CheckBox::get_minimum_size() const {
+
+ Size2 minsize = Button::get_minimum_size();
+ Size2 tex_size = get_icon_size();
+ minsize.width += tex_size.width;
+ if (get_text().length() > 0) {
+ minsize.width += get_constant("hseparation");
+ }
+ Ref<StyleBox> sb = get_stylebox("normal");
+ minsize.height = MAX(minsize.height, tex_size.height + sb->get_margin(MARGIN_TOP) + sb->get_margin(MARGIN_BOTTOM));
+
+ return minsize;
+}
+
void CheckBox::_notification(int p_what) {
- if (p_what == NOTIFICATION_DRAW) {
+ if (p_what == NOTIFICATION_THEME_CHANGED) {
+
+ _set_internal_margin(MARGIN_LEFT, get_icon_size().width);
+ } else if (p_what == NOTIFICATION_DRAW) {
RID ci = get_canvas_item();
Ref<Texture> on = Control::get_icon(is_radio() ? "radio_checked" : "checked");
Ref<Texture> off = Control::get_icon(is_radio() ? "radio_unchecked" : "unchecked");
+ Ref<StyleBox> sb = get_stylebox("normal");
Vector2 ofs;
- ofs.x = 0;
- ofs.y = int((get_size().height - on->get_height()) / 2);
+ ofs.x = sb->get_margin(MARGIN_LEFT);
+ ofs.y = int((get_size().height - get_icon_size().height) / 2);
if (is_pressed())
on->draw(ci, ofs);
@@ -60,6 +96,7 @@ CheckBox::CheckBox(const String &p_text) :
Button(p_text) {
set_toggle_mode(true);
set_text_align(ALIGN_LEFT);
+ _set_internal_margin(MARGIN_LEFT, get_icon_size().width);
}
CheckBox::~CheckBox() {
diff --git a/scene/gui/check_box.h b/scene/gui/check_box.h
index 4da06be8d1..3d3f170e8c 100644
--- a/scene/gui/check_box.h
+++ b/scene/gui/check_box.h
@@ -39,6 +39,8 @@ class CheckBox : public Button {
GDCLASS(CheckBox, Button);
protected:
+ Size2 get_icon_size() const;
+ Size2 get_minimum_size() const;
void _notification(int p_what);
bool is_radio();
diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp
index 77fdedd5e5..641d2d4f01 100644
--- a/scene/gui/check_button.cpp
+++ b/scene/gui/check_button.cpp
@@ -32,10 +32,7 @@
#include "print_string.h"
#include "servers/visual_server.h"
-Size2 CheckButton::get_minimum_size() const {
-
- Size2 minsize = Button::get_minimum_size();
-
+Size2 CheckButton::get_icon_size() const {
Ref<Texture> on = Control::get_icon("on");
Ref<Texture> off = Control::get_icon("off");
Size2 tex_size = Size2(0, 0);
@@ -43,15 +40,29 @@ Size2 CheckButton::get_minimum_size() const {
tex_size = Size2(on->get_width(), on->get_height());
if (!off.is_null())
tex_size = Size2(MAX(tex_size.width, off->get_width()), MAX(tex_size.height, off->get_height()));
- minsize += Size2(tex_size.width + get_constant("hseparation"), 0);
- minsize.height = MAX(minsize.height, tex_size.height);
+ return tex_size;
+}
+
+Size2 CheckButton::get_minimum_size() const {
- return get_stylebox("normal")->get_minimum_size() + minsize;
+ Size2 minsize = Button::get_minimum_size();
+ Size2 tex_size = get_icon_size();
+ minsize.width += tex_size.width;
+ if (get_text().length() > 0) {
+ minsize.width += get_constant("hseparation");
+ }
+ Ref<StyleBox> sb = get_stylebox("normal");
+ minsize.height = MAX(minsize.height, tex_size.height + sb->get_margin(MARGIN_TOP) + sb->get_margin(MARGIN_BOTTOM));
+
+ return minsize;
}
void CheckButton::_notification(int p_what) {
- if (p_what == NOTIFICATION_DRAW) {
+ if (p_what == NOTIFICATION_THEME_CHANGED) {
+
+ _set_internal_margin(MARGIN_RIGHT, get_icon_size().width);
+ } else if (p_what == NOTIFICATION_DRAW) {
RID ci = get_canvas_item();
@@ -59,10 +70,11 @@ void CheckButton::_notification(int p_what) {
Ref<Texture> off = Control::get_icon("off");
Ref<StyleBox> sb = get_stylebox("normal");
- Size2 sb_ofs = Size2(sb->get_margin(MARGIN_RIGHT), sb->get_margin(MARGIN_TOP));
Vector2 ofs;
- ofs.x = get_minimum_size().width - (on->get_width() + sb_ofs.width);
- ofs.y = sb_ofs.height;
+ Size2 tex_size = get_icon_size();
+
+ ofs.x = get_size().width - (tex_size.width + sb->get_margin(MARGIN_RIGHT));
+ ofs.y = (get_size().height - tex_size.height) / 2;
if (is_pressed())
on->draw(ci, ofs);
@@ -75,6 +87,8 @@ CheckButton::CheckButton() {
set_toggle_mode(true);
set_text_align(ALIGN_LEFT);
+
+ _set_internal_margin(MARGIN_RIGHT, get_icon_size().width);
}
CheckButton::~CheckButton() {
diff --git a/scene/gui/check_button.h b/scene/gui/check_button.h
index eb68943fe7..3103a40d3c 100644
--- a/scene/gui/check_button.h
+++ b/scene/gui/check_button.h
@@ -39,6 +39,7 @@ class CheckButton : public Button {
GDCLASS(CheckButton, Button);
protected:
+ Size2 get_icon_size() const;
virtual Size2 get_minimum_size() const;
void _notification(int p_what);
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index adca78d1d4..81d2b6731f 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -2470,6 +2470,16 @@ Control::MouseFilter Control::get_mouse_filter() const {
return data.mouse_filter;
}
+void Control::set_pass_on_modal_close_click(bool p_pass_on) {
+
+ data.pass_on_modal_close_click = p_pass_on;
+}
+
+bool Control::pass_on_modal_close_click() const {
+
+ return data.pass_on_modal_close_click;
+}
+
Control *Control::get_focus_owner() const {
ERR_FAIL_COND_V(!is_inside_tree(), NULL);
@@ -2934,6 +2944,7 @@ Control::Control() {
data.parent = NULL;
data.mouse_filter = MOUSE_FILTER_STOP;
+ data.pass_on_modal_close_click = true;
data.SI = NULL;
data.MI = NULL;
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 92d1c969fc..9ac0eb0be3 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -165,6 +165,8 @@ private:
bool pending_min_size_update;
Point2 custom_minimum_size;
+ bool pass_on_modal_close_click;
+
MouseFilter mouse_filter;
bool clip_contents;
@@ -401,6 +403,9 @@ public:
void set_mouse_filter(MouseFilter p_filter);
MouseFilter get_mouse_filter() const;
+ void set_pass_on_modal_close_click(bool p_pass_on);
+ bool pass_on_modal_close_click() const;
+
/* SKINNING */
void add_icon_override(const StringName &p_name, const Ref<Texture> &p_icon);
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 8af499fd96..6af869c503 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -603,6 +603,14 @@ void FileDialog::set_current_path(const String &p_path) {
}
}
+void FileDialog::set_mode_overrides_title(bool p_override) {
+ mode_overrides_title = p_override;
+}
+
+bool FileDialog::is_mode_overriding_title() const {
+ return mode_overrides_title;
+}
+
void FileDialog::set_mode(Mode p_mode) {
mode = p_mode;
@@ -610,27 +618,32 @@ void FileDialog::set_mode(Mode p_mode) {
case MODE_OPEN_FILE:
get_ok()->set_text(RTR("Open"));
- set_title(RTR("Open a File"));
+ if (mode_overrides_title)
+ set_title(RTR("Open a File"));
makedir->hide();
break;
case MODE_OPEN_FILES:
get_ok()->set_text(RTR("Open"));
- set_title(RTR("Open File(s)"));
+ if (mode_overrides_title)
+ set_title(RTR("Open File(s)"));
makedir->hide();
break;
case MODE_OPEN_DIR:
get_ok()->set_text(RTR("Select Current Folder"));
- set_title(RTR("Open a Directory"));
+ if (mode_overrides_title)
+ set_title(RTR("Open a Directory"));
makedir->show();
break;
case MODE_OPEN_ANY:
get_ok()->set_text(RTR("Open"));
- set_title(RTR("Open a File or Directory"));
+ if (mode_overrides_title)
+ set_title(RTR("Open a File or Directory"));
makedir->show();
break;
case MODE_SAVE_FILE:
get_ok()->set_text(RTR("Save"));
- set_title(RTR("Save a File"));
+ if (mode_overrides_title)
+ set_title(RTR("Save a File"));
makedir->show();
break;
}
@@ -760,6 +773,8 @@ void FileDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_current_dir", "dir"), &FileDialog::set_current_dir);
ClassDB::bind_method(D_METHOD("set_current_file", "file"), &FileDialog::set_current_file);
ClassDB::bind_method(D_METHOD("set_current_path", "path"), &FileDialog::set_current_path);
+ ClassDB::bind_method(D_METHOD("set_mode_overrides_title", "override"), &FileDialog::set_mode_overrides_title);
+ ClassDB::bind_method(D_METHOD("is_mode_overriding_title"), &FileDialog::is_mode_overriding_title);
ClassDB::bind_method(D_METHOD("set_mode", "mode"), &FileDialog::set_mode);
ClassDB::bind_method(D_METHOD("get_mode"), &FileDialog::get_mode);
ClassDB::bind_method(D_METHOD("get_vbox"), &FileDialog::get_vbox);
@@ -791,6 +806,7 @@ void FileDialog::_bind_methods() {
BIND_ENUM_CONSTANT(ACCESS_USERDATA);
BIND_ENUM_CONSTANT(ACCESS_FILESYSTEM);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "mode_overrides_title"), "set_mode_overrides_title", "is_mode_overriding_title");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Open one,Open many,Open folder,Open any,Save"), "set_mode", "get_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access");
ADD_PROPERTY(PropertyInfo(Variant::POOL_STRING_ARRAY, "filters"), "set_filters", "get_filters");
@@ -814,6 +830,8 @@ FileDialog::FileDialog() {
show_hidden_files = default_show_hidden_files;
+ mode_overrides_title = true;
+
VBoxContainer *vbc = memnew(VBoxContainer);
add_child(vbc);
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index ca3d9f54b2..c8c1f23105 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -92,6 +92,8 @@ private:
Vector<String> filters;
+ bool mode_overrides_title;
+
static bool default_show_hidden_files;
bool show_hidden_files;
@@ -143,6 +145,9 @@ public:
void set_current_file(const String &p_file);
void set_current_path(const String &p_path);
+ void set_mode_overrides_title(bool p_override);
+ bool is_mode_overriding_title() const;
+
void set_mode(Mode p_mode);
Mode get_mode() const;
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index ac450616d6..d850553957 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -111,6 +111,7 @@ MenuButton::MenuButton() {
popup->hide();
add_child(popup);
popup->set_as_toplevel(true);
+ popup->set_pass_on_modal_close_click(false);
connect("button_up", popup, "call_deferred", make_binds("grab_click_focus"));
set_process_unhandled_key_input(true);
set_action_mode(ACTION_MODE_BUTTON_PRESS);
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index b4d0799945..70f3d9ca83 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -323,6 +323,7 @@ OptionButton::OptionButton() {
popup = memnew(PopupMenu);
popup->hide();
popup->set_as_toplevel(true);
+ popup->set_pass_on_modal_close_click(false);
add_child(popup);
popup->connect("id_pressed", this, "_selected");
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 4ee6f93c9a..e37cdd5cc9 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -624,6 +624,20 @@ void PopupMenu::add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_ID, bo
update();
}
+void PopupMenu::add_statable_item(const String &p_label, int p_max_states, int p_default_state, int p_ID, uint32_t p_accel) {
+
+ Item item;
+ item.text = p_label;
+ item.xl_text = tr(p_label);
+ item.accel = p_accel;
+ item.ID = p_ID;
+ item.checkable = false;
+ item.max_states = p_max_states;
+ item.state = p_default_state;
+ items.push_back(item);
+ update();
+}
+
void PopupMenu::set_item_text(int p_idx, const String &p_text) {
ERR_FAIL_INDEX(p_idx, items.size());
@@ -772,6 +786,11 @@ Ref<ShortCut> PopupMenu::get_item_shortcut(int p_idx) const {
return items[p_idx].shortcut;
}
+int PopupMenu::get_item_state(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, items.size(), -1);
+ return items[p_idx].state;
+}
+
void PopupMenu::set_item_as_separator(int p_idx, bool p_separator) {
ERR_FAIL_INDEX(p_idx, items.size());
@@ -820,6 +839,27 @@ void PopupMenu::set_item_h_offset(int p_idx, int p_offset) {
update();
}
+void PopupMenu::set_item_statable(int p_idx, int p_state) {
+
+ ERR_FAIL_INDEX(p_idx, items.size());
+ items[p_idx].state = p_state;
+ update();
+}
+
+void PopupMenu::toggle_item_statable(int p_idx) {
+
+ ERR_FAIL_INDEX(p_idx, items.size());
+ if (0 >= items[p_idx].max_states) {
+ return;
+ }
+
+ ++items[p_idx].state;
+ if (items[p_idx].max_states <= items[p_idx].state)
+ items[p_idx].state = 0;
+
+ update();
+}
+
bool PopupMenu::is_item_checkable(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, items.size(), false);
return items[p_idx].checkable;
@@ -895,21 +935,34 @@ void PopupMenu::activate_item(int p_item) {
while (pop) {
// We close all parents that are chained together,
// with hide_on_item_selection enabled
- if ((items[p_item].checkable && hide_on_checkable_item_selection && pop->is_hide_on_checkable_item_selection()) || (!items[p_item].checkable && hide_on_item_selection && pop->is_hide_on_item_selection())) {
- pop->hide();
- next = next->get_parent();
- pop = Object::cast_to<PopupMenu>(next);
- } else {
- // Break out of loop when the next parent has
- // hide_on_item_selection disabled
+
+ if (items[p_item].checkable) {
+ if (!hide_on_checkable_item_selection || !pop->is_hide_on_checkable_item_selection())
+ break;
+ } else if (0 < items[p_item].max_states) {
+ if (!hide_on_statable_item_selection || !pop->is_hide_on_statable_item_selection())
+ break;
+ } else if (!hide_on_item_selection || !pop->is_hide_on_item_selection())
break;
- }
+
+ pop->hide();
+ next = next->get_parent();
+ pop = Object::cast_to<PopupMenu>(next);
}
+
// Hides popup by default; unless otherwise specified
// by using set_hide_on_item_selection and set_hide_on_checkable_item_selection
- if ((items[p_item].checkable && hide_on_checkable_item_selection) || (!items[p_item].checkable && hide_on_item_selection)) {
- hide();
- }
+
+ if (items[p_item].checkable) {
+ if (!hide_on_checkable_item_selection)
+ return;
+ } else if (0 < items[p_item].max_states) {
+ if (!hide_on_statable_item_selection)
+ return;
+ } else if (!hide_on_item_selection)
+ return;
+
+ hide();
}
void PopupMenu::remove_item(int p_idx) {
@@ -1025,7 +1078,7 @@ void PopupMenu::set_hide_on_item_selection(bool p_enabled) {
hide_on_item_selection = p_enabled;
}
-bool PopupMenu::is_hide_on_item_selection() {
+bool PopupMenu::is_hide_on_item_selection() const {
return hide_on_item_selection;
}
@@ -1035,11 +1088,21 @@ void PopupMenu::set_hide_on_checkable_item_selection(bool p_enabled) {
hide_on_checkable_item_selection = p_enabled;
}
-bool PopupMenu::is_hide_on_checkable_item_selection() {
+bool PopupMenu::is_hide_on_checkable_item_selection() const {
return hide_on_checkable_item_selection;
}
+void PopupMenu::set_hide_on_statable_item_selection(bool p_enabled) {
+
+ hide_on_statable_item_selection = p_enabled;
+}
+
+bool PopupMenu::is_hide_on_statable_item_selection() const {
+
+ return hide_on_statable_item_selection;
+}
+
String PopupMenu::get_tooltip(const Point2 &p_pos) const {
int over = _get_mouse_over(p_pos);
@@ -1098,8 +1161,10 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_item_as_checkable", "idx", "enable"), &PopupMenu::set_item_as_checkable);
ClassDB::bind_method(D_METHOD("set_item_tooltip", "idx", "tooltip"), &PopupMenu::set_item_tooltip);
ClassDB::bind_method(D_METHOD("set_item_shortcut", "idx", "shortcut", "global"), &PopupMenu::set_item_shortcut, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("set_item_statable", "idx", "state"), &PopupMenu::set_item_statable);
ClassDB::bind_method(D_METHOD("toggle_item_checked", "idx"), &PopupMenu::toggle_item_checked);
+ ClassDB::bind_method(D_METHOD("toggle_item_statable", "idx"), &PopupMenu::toggle_item_statable);
ClassDB::bind_method(D_METHOD("get_item_text", "idx"), &PopupMenu::get_item_text);
ClassDB::bind_method(D_METHOD("get_item_icon", "idx"), &PopupMenu::get_item_icon);
@@ -1131,6 +1196,9 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_hide_on_checkable_item_selection", "enable"), &PopupMenu::set_hide_on_checkable_item_selection);
ClassDB::bind_method(D_METHOD("is_hide_on_checkable_item_selection"), &PopupMenu::is_hide_on_checkable_item_selection);
+ ClassDB::bind_method(D_METHOD("set_hide_on_state_item_selection", "enable"), &PopupMenu::set_hide_on_statable_item_selection);
+ ClassDB::bind_method(D_METHOD("is_hide_on_state_item_selection"), &PopupMenu::is_hide_on_statable_item_selection);
+
ClassDB::bind_method(D_METHOD("_submenu_timeout"), &PopupMenu::_submenu_timeout);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_items", "_get_items");
@@ -1154,6 +1222,7 @@ PopupMenu::PopupMenu() {
set_as_toplevel(true);
set_hide_on_item_selection(true);
set_hide_on_checkable_item_selection(true);
+ set_hide_on_statable_item_selection(false);
submenu_timer = memnew(Timer);
submenu_timer->set_wait_time(0.3);
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index c9e9c8e311..5a10bf0765 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -46,6 +46,8 @@ class PopupMenu : public Popup {
String xl_text;
bool checked;
bool checkable;
+ int max_states;
+ int state;
bool separator;
bool disabled;
int ID;
@@ -62,6 +64,8 @@ class PopupMenu : public Popup {
checked = false;
checkable = false;
separator = false;
+ max_states = 0;
+ state = 0;
accel = 0;
disabled = false;
_ofs_cache = 0;
@@ -86,6 +90,7 @@ class PopupMenu : public Popup {
bool invalidated_click;
bool hide_on_item_selection;
bool hide_on_checkable_item_selection;
+ bool hide_on_statable_item_selection;
Vector2 moved;
Array _get_items() const;
@@ -115,6 +120,8 @@ public:
void add_icon_check_shortcut(const Ref<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_ID = -1, bool p_global = false);
void add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_ID = -1, bool p_global = false);
+ void add_statable_item(const String &p_label, int p_max_states, int p_default_state, int p_ID = -1, uint32_t p_accel = 0);
+
void set_item_text(int p_idx, const String &p_text);
void set_item_icon(int p_idx, const Ref<Texture> &p_icon);
void set_item_checked(int p_idx, bool p_checked);
@@ -128,6 +135,8 @@ public:
void set_item_tooltip(int p_idx, const String &p_tooltip);
void set_item_shortcut(int p_idx, const Ref<ShortCut> &p_shortcut, bool p_global = false);
void set_item_h_offset(int p_idx, int p_offset);
+ void set_item_statable(int p_idx, int p_state);
+ void toggle_item_statable(int p_idx);
void toggle_item_checked(int p_idx);
@@ -145,6 +154,7 @@ public:
bool is_item_checkable(int p_idx) const;
String get_item_tooltip(int p_idx) const;
Ref<ShortCut> get_item_shortcut(int p_idx) const;
+ int get_item_state(int p_idx) const;
int get_item_count() const;
@@ -168,10 +178,13 @@ public:
void set_invalidate_click_until_motion();
void set_hide_on_item_selection(bool p_enabled);
- bool is_hide_on_item_selection();
+ bool is_hide_on_item_selection() const;
void set_hide_on_checkable_item_selection(bool p_enabled);
- bool is_hide_on_checkable_item_selection();
+ bool is_hide_on_checkable_item_selection() const;
+
+ void set_hide_on_statable_item_selection(bool p_enabled);
+ bool is_hide_on_statable_item_selection() const;
PopupMenu();
~PopupMenu();
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 9cf4c105b4..45188c3a52 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -1822,7 +1822,7 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection) {
void RichTextLabel::selection_copy() {
- if (!selection.enabled)
+ if (!selection.active || !selection.enabled)
return;
String text;
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 1096e3f650..b9a719dd10 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -256,8 +256,8 @@ private:
Item *to;
int to_char;
- bool active;
- bool enabled;
+ bool active; // anything selected? i.e. from, to, etc. valid?
+ bool enabled; // allow selections?
};
Selection selection;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 7ff85716a5..e5169089f2 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -4646,6 +4646,16 @@ void TextEdit::unfold_line(int p_line) {
update();
}
+void TextEdit::toggle_fold_line(int p_line) {
+
+ ERR_FAIL_INDEX(p_line, text.size());
+
+ if (!is_folded(p_line))
+ fold_line(p_line);
+ else
+ unfold_line(p_line);
+}
+
int TextEdit::get_line_count() const {
return text.size();
@@ -5461,6 +5471,7 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("unhide_all_lines"), &TextEdit::unhide_all_lines);
ClassDB::bind_method(D_METHOD("fold_line", "line"), &TextEdit::fold_line);
ClassDB::bind_method(D_METHOD("unfold_line", "line"), &TextEdit::unfold_line);
+ ClassDB::bind_method(D_METHOD("toggle_fold_line", "line"), &TextEdit::toggle_fold_line);
ClassDB::bind_method(D_METHOD("can_fold", "line"), &TextEdit::can_fold);
ClassDB::bind_method(D_METHOD("is_folded", "line"), &TextEdit::is_folded);
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index e5dc2da7c7..dd305d5822 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -436,6 +436,7 @@ public:
bool is_folded(int p_line) const;
void fold_line(int p_line);
void unfold_line(int p_line);
+ void toggle_fold_line(int p_line);
String get_text();
String get_line(int line) const;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index a785abbc65..4635de81e8 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -1269,12 +1269,9 @@ Transform2D Viewport::_get_input_pre_xform() const {
Vector2 Viewport::_get_window_offset() const {
- /*
- if (parent_control) {
- return (parent_control->get_viewport()->get_final_transform() * parent_control->get_global_transform_with_canvas()).get_origin();
+ if (get_parent() && get_parent()->has_method("get_global_position")) {
+ return get_parent()->call("get_global_position");
}
- */
-
return Vector2();
}
@@ -1649,6 +1646,8 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
} else {
+ bool is_handled = false;
+
_gui_sort_modal_stack();
while (!gui.modal_stack.empty()) {
@@ -1666,11 +1665,20 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
top->notification(Control::NOTIFICATION_MODAL_CLOSE);
top->_modal_stack_remove();
top->hide();
+
+ if (!top->pass_on_modal_close_click()) {
+ is_handled = true;
+ }
} else {
break;
}
}
+ if (is_handled) {
+ get_tree()->set_input_as_handled();
+ return;
+ }
+
//Matrix32 parent_xform;
/*
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index ebbd2d35c3..4544549f94 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -77,6 +77,8 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
track_set_interpolation_loop_wrap(track, p_value);
else if (what == "imported")
track_set_imported(track, p_value);
+ else if (what == "enabled")
+ track_set_enabled(track, p_value);
else if (what == "keys" || what == "key_values") {
if (track_get_type(track) == TYPE_TRANSFORM) {
@@ -247,6 +249,8 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = track_get_interpolation_loop_wrap(track);
else if (what == "imported")
r_ret = track_is_imported(track);
+ else if (what == "enabled")
+ r_ret = track_is_enabled(track);
else if (what == "keys") {
if (track_get_type(track) == TYPE_TRANSFORM) {
@@ -391,6 +395,7 @@ void Animation::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::INT, "tracks/" + itos(i) + "/interp", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
p_list->push_back(PropertyInfo(Variant::BOOL, "tracks/" + itos(i) + "/loop_wrap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
p_list->push_back(PropertyInfo(Variant::BOOL, "tracks/" + itos(i) + "/imported", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+ p_list->push_back(PropertyInfo(Variant::BOOL, "tracks/" + itos(i) + "/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
p_list->push_back(PropertyInfo(Variant::ARRAY, "tracks/" + itos(i) + "/keys", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
}
}
@@ -1575,6 +1580,19 @@ bool Animation::track_is_imported(int p_track) const {
return tracks[p_track]->imported;
}
+void Animation::track_set_enabled(int p_track, bool p_enabled) {
+
+ ERR_FAIL_INDEX(p_track, tracks.size());
+ tracks[p_track]->enabled = p_enabled;
+ emit_changed();
+}
+
+bool Animation::track_is_enabled(int p_track) const {
+
+ ERR_FAIL_INDEX_V(p_track, tracks.size(), false);
+ return tracks[p_track]->enabled;
+}
+
void Animation::track_move_down(int p_track) {
if (p_track > 0 && p_track < tracks.size()) {
@@ -1603,6 +1621,7 @@ void Animation::copy_track(int src_track, Ref<Animation> p_to_animation) {
p_to_animation->track_set_path(dst_track, track_get_path(src_track));
p_to_animation->track_set_imported(dst_track, track_is_imported(src_track));
+ p_to_animation->track_set_enabled(dst_track, track_is_enabled(src_track));
p_to_animation->track_set_interpolation_type(dst_track, track_get_interpolation_type(src_track));
p_to_animation->track_set_interpolation_loop_wrap(dst_track, track_get_interpolation_loop_wrap(src_track));
for (int i = 0; i < track_get_key_count(src_track); i++) {
@@ -1626,6 +1645,9 @@ void Animation::_bind_methods() {
ClassDB::bind_method(D_METHOD("track_set_imported", "idx", "imported"), &Animation::track_set_imported);
ClassDB::bind_method(D_METHOD("track_is_imported", "idx"), &Animation::track_is_imported);
+ ClassDB::bind_method(D_METHOD("track_set_enabled", "idx", "enabled"), &Animation::track_set_enabled);
+ ClassDB::bind_method(D_METHOD("track_is_enabled", "idx"), &Animation::track_is_enabled);
+
ClassDB::bind_method(D_METHOD("transform_track_insert_key", "idx", "time", "location", "rotation", "scale"), &Animation::transform_track_insert_key);
ClassDB::bind_method(D_METHOD("track_insert_key", "idx", "time", "key", "transition"), &Animation::track_insert_key, DEFVAL(1));
ClassDB::bind_method(D_METHOD("track_remove_key", "idx", "key_idx"), &Animation::track_remove_key);
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index c96beeb01f..1f468b29b5 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -67,10 +67,12 @@ private:
bool loop_wrap;
NodePath path; // path to something
bool imported;
+ bool enabled;
Track() {
interpolation = INTERPOLATION_LINEAR;
imported = false;
loop_wrap = true;
+ enabled = true;
}
virtual ~Track() {}
};
@@ -239,6 +241,9 @@ public:
void track_set_imported(int p_track, bool p_imported);
bool track_is_imported(int p_track) const;
+ void track_set_enabled(int p_track, bool p_enabled);
+ bool track_is_enabled(int p_track) const;
+
int transform_track_insert_key(int p_track, float p_time, const Vector3 p_loc, const Quat &p_rot = Quat(), const Vector3 &p_scale = Vector3());
void track_insert_key(int p_track, float p_time, const Variant &p_key, float p_transition = 1);
void track_set_key_transition(int p_track, int p_key_idx, float p_transition);
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index bb2c8750e3..f4e6c5e247 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -350,15 +350,15 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
// CheckBox
Ref<StyleBox> cbx_empty = memnew(StyleBoxEmpty);
- cbx_empty->set_default_margin(MARGIN_LEFT, 22 * scale);
+ cbx_empty->set_default_margin(MARGIN_LEFT, 4 * scale);
cbx_empty->set_default_margin(MARGIN_RIGHT, 4 * scale);
cbx_empty->set_default_margin(MARGIN_TOP, 4 * scale);
- cbx_empty->set_default_margin(MARGIN_BOTTOM, 5 * scale);
+ cbx_empty->set_default_margin(MARGIN_BOTTOM, 4 * scale);
Ref<StyleBox> cbx_focus = focus;
cbx_focus->set_default_margin(MARGIN_LEFT, 4 * scale);
- cbx_focus->set_default_margin(MARGIN_RIGHT, 22 * scale);
+ cbx_focus->set_default_margin(MARGIN_RIGHT, 4 * scale);
cbx_focus->set_default_margin(MARGIN_TOP, 4 * scale);
- cbx_focus->set_default_margin(MARGIN_BOTTOM, 5 * scale);
+ cbx_focus->set_default_margin(MARGIN_BOTTOM, 4 * scale);
theme->set_stylebox("normal", "CheckBox", cbx_empty);
theme->set_stylebox("pressed", "CheckBox", cbx_empty);
@@ -385,7 +385,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
Ref<StyleBox> cb_empty = memnew(StyleBoxEmpty);
cb_empty->set_default_margin(MARGIN_LEFT, 6 * scale);
- cb_empty->set_default_margin(MARGIN_RIGHT, 70 * scale);
+ cb_empty->set_default_margin(MARGIN_RIGHT, 6 * scale);
cb_empty->set_default_margin(MARGIN_TOP, 4 * scale);
cb_empty->set_default_margin(MARGIN_BOTTOM, 4 * scale);
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 0a886c25b1..0b352efca2 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -28,10 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "mesh.h"
+
+#include "pair.h"
#include "scene/resources/concave_polygon_shape.h"
#include "scene/resources/convex_polygon_shape.h"
#include "surface_tool.h"
+#include <stdlib.h>
+
void Mesh::_clear_triangle_mesh() const {
triangle_mesh.unref();
@@ -413,8 +417,21 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const {
return newmesh;
}
+void Mesh::set_lightmap_size_hint(const Vector2 &p_size) {
+ lightmap_size_hint = p_size;
+}
+
+Size2 Mesh::get_lightmap_size_hint() const {
+ return lightmap_size_hint;
+}
+
void Mesh::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_lightmap_size_hint", "size"), &Mesh::set_lightmap_size_hint);
+ ClassDB::bind_method(D_METHOD("get_lightmap_size_hint"), &Mesh::get_lightmap_size_hint);
+
+ ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "lightmap_size_hint"), "set_lightmap_size_hint", "get_lightmap_size_hint");
+
BIND_ENUM_CONSTANT(PRIMITIVE_POINTS);
BIND_ENUM_CONSTANT(PRIMITIVE_LINES);
BIND_ENUM_CONSTANT(PRIMITIVE_LINE_STRIP);
@@ -1035,6 +1052,200 @@ void ArrayMesh::regen_normalmaps() {
}
}
+//dirty hack
+bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y) = NULL;
+
+struct ArrayMeshLightmapSurface {
+
+ Ref<Material> material;
+ Vector<SurfaceTool::Vertex> vertices;
+ Mesh::PrimitiveType primitive;
+ uint32_t format;
+};
+
+Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texel_size) {
+
+ ERR_FAIL_COND_V(!array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED);
+ ERR_EXPLAIN("Can't unwrap mesh with blend shapes");
+ ERR_FAIL_COND_V(blend_shapes.size() != 0, ERR_UNAVAILABLE);
+
+ Vector<float> vertices;
+ Vector<float> normals;
+ Vector<int> indices;
+ Vector<int> face_materials;
+ Vector<float> uv;
+ Vector<Pair<int, int> > uv_index;
+
+ Vector<ArrayMeshLightmapSurface> surfaces;
+ for (int i = 0; i < get_surface_count(); i++) {
+ ArrayMeshLightmapSurface s;
+ s.primitive = surface_get_primitive_type(i);
+
+ if (s.primitive != Mesh::PRIMITIVE_TRIANGLES) {
+ ERR_EXPLAIN("Only triangles are supported for lightmap unwrap");
+ ERR_FAIL_V(ERR_UNAVAILABLE);
+ }
+ s.format = surface_get_format(i);
+ if (!(s.format & ARRAY_FORMAT_NORMAL)) {
+ ERR_EXPLAIN("Normals are required for lightmap unwrap");
+ ERR_FAIL_V(ERR_UNAVAILABLE);
+ }
+
+ Array arrays = surface_get_arrays(i);
+ s.material = surface_get_material(i);
+ s.vertices = SurfaceTool::create_vertex_array_from_triangle_arrays(arrays);
+
+ PoolVector<Vector3> rvertices = arrays[Mesh::ARRAY_VERTEX];
+ int vc = rvertices.size();
+ PoolVector<Vector3>::Read r = rvertices.read();
+
+ PoolVector<Vector3> rnormals = arrays[Mesh::ARRAY_NORMAL];
+ PoolVector<Vector3>::Read rn = rnormals.read();
+
+ int vertex_ofs = vertices.size() / 3;
+
+ vertices.resize((vertex_ofs + vc) * 3);
+ normals.resize((vertex_ofs + vc) * 3);
+ uv_index.resize(vertex_ofs + vc);
+
+ for (int j = 0; j < vc; j++) {
+
+ Vector3 v = p_base_transform.xform(r[j]);
+
+ vertices[(j + vertex_ofs) * 3 + 0] = v.x;
+ vertices[(j + vertex_ofs) * 3 + 1] = v.y;
+ vertices[(j + vertex_ofs) * 3 + 2] = v.z;
+ normals[(j + vertex_ofs) * 3 + 0] = rn[j].x;
+ normals[(j + vertex_ofs) * 3 + 1] = rn[j].y;
+ normals[(j + vertex_ofs) * 3 + 2] = rn[j].z;
+ uv_index[j + vertex_ofs] = Pair<int, int>(i, j);
+ }
+
+ PoolVector<int> rindices = arrays[Mesh::ARRAY_INDEX];
+ int ic = rindices.size();
+ int index_ofs = indices.size();
+
+ if (ic == 0) {
+ indices.resize(index_ofs + vc);
+ face_materials.resize((index_ofs + vc) / 3);
+ for (int j = 0; j < vc; j++) {
+ indices[index_ofs + j] = vertex_ofs + j;
+ }
+ for (int j = 0; j < vc / 3; j++) {
+ face_materials[(index_ofs / 3) + j] = i;
+ }
+
+ } else {
+ PoolVector<int>::Read ri = rindices.read();
+ indices.resize(index_ofs + ic);
+ face_materials.resize((index_ofs + ic) / 3);
+ for (int j = 0; j < ic; j++) {
+ indices[index_ofs + j] = vertex_ofs + ri[j];
+ }
+ for (int j = 0; j < ic / 3; j++) {
+ face_materials[(index_ofs / 3) + j] = i;
+ }
+ }
+
+ surfaces.push_back(s);
+ }
+
+ //unwrap
+
+ float *gen_uvs;
+ int *gen_vertices;
+ int *gen_indices;
+ int gen_vertex_count;
+ int gen_index_count;
+ int size_x;
+ int size_y;
+
+ bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), face_materials.ptr(), indices.size(), &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y);
+
+ if (!ok) {
+ return ERR_CANT_CREATE;
+ }
+
+ //remove surfaces
+ while (get_surface_count()) {
+ surface_remove(0);
+ }
+
+ //create surfacetools for each surface..
+ Vector<Ref<SurfaceTool> > surfaces_tools;
+
+ for (int i = 0; i < surfaces.size(); i++) {
+ Ref<SurfaceTool> st;
+ st.instance();
+ st->begin(Mesh::PRIMITIVE_TRIANGLES);
+ st->set_material(surfaces[i].material);
+ surfaces_tools.push_back(st); //stay there
+ }
+
+ print_line("gen indices: " + itos(gen_index_count));
+ //go through all indices
+ for (int i = 0; i < gen_index_count; i += 3) {
+
+ ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], uv_index.size(), ERR_BUG);
+ ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], uv_index.size(), ERR_BUG);
+ ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], uv_index.size(), ERR_BUG);
+
+ ERR_FAIL_COND_V(uv_index[gen_vertices[gen_indices[i + 0]]].first != uv_index[gen_vertices[gen_indices[i + 1]]].first || uv_index[gen_vertices[gen_indices[i + 0]]].first != uv_index[gen_vertices[gen_indices[i + 2]]].first, ERR_BUG);
+
+ int surface = uv_index[gen_vertices[gen_indices[i + 0]]].first;
+
+ for (int j = 0; j < 3; j++) {
+
+ int vertex_idx = gen_vertices[gen_indices[i + j]];
+
+ SurfaceTool::Vertex v = surfaces[surface].vertices[uv_index[gen_vertices[gen_indices[i + j]]].second];
+
+ if (surfaces[surface].format & ARRAY_FORMAT_COLOR) {
+ surfaces_tools[surface]->add_color(v.color);
+ }
+ if (surfaces[surface].format & ARRAY_FORMAT_TEX_UV) {
+ surfaces_tools[surface]->add_uv(v.uv);
+ }
+ if (surfaces[surface].format & ARRAY_FORMAT_NORMAL) {
+ surfaces_tools[surface]->add_normal(v.normal);
+ }
+ if (surfaces[surface].format & ARRAY_FORMAT_TANGENT) {
+ Plane t;
+ t.normal = v.tangent;
+ t.d = v.binormal.dot(v.normal.cross(v.tangent)) < 0 ? -1 : 1;
+ surfaces_tools[surface]->add_tangent(t);
+ }
+ if (surfaces[surface].format & ARRAY_FORMAT_BONES) {
+ surfaces_tools[surface]->add_bones(v.bones);
+ }
+ if (surfaces[surface].format & ARRAY_FORMAT_WEIGHTS) {
+ surfaces_tools[surface]->add_weights(v.weights);
+ }
+
+ Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]);
+ surfaces_tools[surface]->add_uv2(uv2);
+
+ surfaces_tools[surface]->add_vertex(v.vertex);
+ }
+ }
+
+ //free stuff
+ ::free(gen_vertices);
+ ::free(gen_indices);
+ ::free(gen_uvs);
+
+ //generate surfaces
+
+ for (int i = 0; i < surfaces_tools.size(); i++) {
+ surfaces_tools[i]->index();
+ surfaces_tools[i]->commit(Ref<ArrayMesh>((ArrayMesh *)this), surfaces[i].format);
+ }
+
+ set_lightmap_size_hint(Size2(size_x, size_y));
+
+ return OK;
+}
+
void ArrayMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &ArrayMesh::add_blend_shape);
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index b85a6a84af..ea38ebf2ff 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -43,6 +43,8 @@ class Mesh : public Resource {
GDCLASS(Mesh, Resource);
mutable Ref<TriangleMesh> triangle_mesh; //cached
+ Size2 lightmap_size_hint;
+
protected:
void _clear_triangle_mesh() const;
@@ -138,6 +140,9 @@ public:
virtual AABB get_aabb() const = 0;
+ void set_lightmap_size_hint(const Vector2 &p_size);
+ Size2 get_lightmap_size_hint() const;
+
Mesh();
};
@@ -216,6 +221,8 @@ public:
void center_geometry();
void regen_normalmaps();
+ Error lightmap_unwrap(const Transform &p_base_transform = Transform(), float p_texel_size = 0.05);
+
virtual void reload_from_file();
ArrayMesh();
diff --git a/scene/resources/sky_box.cpp b/scene/resources/sky_box.cpp
index 2ef20f67f5..a2c3f1f111 100644
--- a/scene/resources/sky_box.cpp
+++ b/scene/resources/sky_box.cpp
@@ -180,7 +180,7 @@ Ref<Image> ProceduralSky::_generate_sky() {
normal.normalize();
- float v_angle = Math::acos(normal.y);
+ float v_angle = Math::acos(CLAMP(normal.y, -1.0, 1.0));
Color color;
@@ -193,7 +193,7 @@ Ref<Image> ProceduralSky::_generate_sky() {
float c = v_angle / (Math_PI * 0.5);
color = sky_horizon_linear.linear_interpolate(sky_top_linear, Math::ease(1.0 - c, sky_curve));
- float sun_angle = Math::rad2deg(Math::acos(sun.dot(normal)));
+ float sun_angle = Math::rad2deg(Math::acos(CLAMP(sun.dot(normal), -1.0, 1.0)));
if (sun_angle < sun_angle_min) {
color = color.blend(sun_color);
diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp
index bf89e704bc..d8600e041d 100644
--- a/scene/resources/surface_tool.cpp
+++ b/scene/resources/surface_tool.cpp
@@ -101,6 +101,7 @@ void SurfaceTool::add_vertex(const Vector3 &p_vertex) {
vtx.color = last_color;
vtx.normal = last_normal;
vtx.uv = last_uv;
+ vtx.uv2 = last_uv2;
vtx.weights = last_weights;
vtx.bones = last_bones;
vtx.tangent = last_tangent.normal;
@@ -401,7 +402,7 @@ Array SurfaceTool::commit_to_arrays() {
return a;
}
-Ref<ArrayMesh> SurfaceTool::commit(const Ref<ArrayMesh> &p_existing) {
+Ref<ArrayMesh> SurfaceTool::commit(const Ref<ArrayMesh> &p_existing, uint32_t p_flags) {
Ref<ArrayMesh> mesh;
if (p_existing.is_valid())
@@ -418,7 +419,7 @@ Ref<ArrayMesh> SurfaceTool::commit(const Ref<ArrayMesh> &p_existing) {
Array a = commit_to_arrays();
- mesh->add_surface_from_arrays(primitive, a);
+ mesh->add_surface_from_arrays(primitive, a, Array(), p_flags);
if (material.is_valid())
mesh->surface_set_material(surface, material);
@@ -482,6 +483,113 @@ void SurfaceTool::_create_list(const Ref<Mesh> &p_existing, int p_surface, List<
_create_list_from_arrays(arr, r_vertex, r_index, lformat);
}
+Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_arrays(const Array &p_arrays) {
+
+ Vector<SurfaceTool::Vertex> ret;
+
+ PoolVector<Vector3> varr = p_arrays[VS::ARRAY_VERTEX];
+ PoolVector<Vector3> narr = p_arrays[VS::ARRAY_NORMAL];
+ PoolVector<float> tarr = p_arrays[VS::ARRAY_TANGENT];
+ PoolVector<Color> carr = p_arrays[VS::ARRAY_COLOR];
+ PoolVector<Vector2> uvarr = p_arrays[VS::ARRAY_TEX_UV];
+ PoolVector<Vector2> uv2arr = p_arrays[VS::ARRAY_TEX_UV2];
+ PoolVector<int> barr = p_arrays[VS::ARRAY_BONES];
+ PoolVector<float> warr = p_arrays[VS::ARRAY_WEIGHTS];
+
+ int vc = varr.size();
+
+ if (vc == 0)
+ return ret;
+ int lformat = 0;
+
+ PoolVector<Vector3>::Read rv;
+ if (varr.size()) {
+ lformat |= VS::ARRAY_FORMAT_VERTEX;
+ rv = varr.read();
+ }
+ PoolVector<Vector3>::Read rn;
+ if (narr.size()) {
+ lformat |= VS::ARRAY_FORMAT_NORMAL;
+ rn = narr.read();
+ }
+ PoolVector<float>::Read rt;
+ if (tarr.size()) {
+ lformat |= VS::ARRAY_FORMAT_TANGENT;
+ rt = tarr.read();
+ }
+ PoolVector<Color>::Read rc;
+ if (carr.size()) {
+ lformat |= VS::ARRAY_FORMAT_COLOR;
+ rc = carr.read();
+ }
+
+ PoolVector<Vector2>::Read ruv;
+ if (uvarr.size()) {
+ lformat |= VS::ARRAY_FORMAT_TEX_UV;
+ ruv = uvarr.read();
+ }
+
+ PoolVector<Vector2>::Read ruv2;
+ if (uv2arr.size()) {
+ lformat |= VS::ARRAY_FORMAT_TEX_UV2;
+ ruv2 = uv2arr.read();
+ }
+
+ PoolVector<int>::Read rb;
+ if (barr.size()) {
+ lformat |= VS::ARRAY_FORMAT_BONES;
+ rb = barr.read();
+ }
+
+ PoolVector<float>::Read rw;
+ if (warr.size()) {
+ lformat |= VS::ARRAY_FORMAT_WEIGHTS;
+ rw = warr.read();
+ }
+
+ for (int i = 0; i < vc; i++) {
+
+ Vertex v;
+ if (lformat & VS::ARRAY_FORMAT_VERTEX)
+ v.vertex = varr[i];
+ if (lformat & VS::ARRAY_FORMAT_NORMAL)
+ v.normal = narr[i];
+ if (lformat & VS::ARRAY_FORMAT_TANGENT) {
+ Plane p(tarr[i * 4 + 0], tarr[i * 4 + 1], tarr[i * 4 + 2], tarr[i * 4 + 3]);
+ v.tangent = p.normal;
+ v.binormal = p.normal.cross(v.tangent).normalized() * p.d;
+ }
+ if (lformat & VS::ARRAY_FORMAT_COLOR)
+ v.color = carr[i];
+ if (lformat & VS::ARRAY_FORMAT_TEX_UV)
+ v.uv = uvarr[i];
+ if (lformat & VS::ARRAY_FORMAT_TEX_UV2)
+ v.uv2 = uv2arr[i];
+ if (lformat & VS::ARRAY_FORMAT_BONES) {
+ Vector<int> b;
+ b.resize(4);
+ b[0] = barr[i * 4 + 0];
+ b[1] = barr[i * 4 + 1];
+ b[2] = barr[i * 4 + 2];
+ b[3] = barr[i * 4 + 3];
+ v.bones = b;
+ }
+ if (lformat & VS::ARRAY_FORMAT_WEIGHTS) {
+ Vector<float> w;
+ w.resize(4);
+ w[0] = warr[i * 4 + 0];
+ w[1] = warr[i * 4 + 1];
+ w[2] = warr[i * 4 + 2];
+ w[3] = warr[i * 4 + 3];
+ v.weights = w;
+ }
+
+ ret.push_back(v);
+ }
+
+ return ret;
+}
+
void SurfaceTool::_create_list_from_arrays(Array arr, List<Vertex> *r_vertex, List<int> *r_index, int &lformat) {
PoolVector<Vector3> varr = arr[VS::ARRAY_VERTEX];
@@ -882,7 +990,7 @@ void SurfaceTool::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_from", "existing", "surface"), &SurfaceTool::create_from);
ClassDB::bind_method(D_METHOD("append_from", "existing", "surface", "transform"), &SurfaceTool::append_from);
- ClassDB::bind_method(D_METHOD("commit", "existing"), &SurfaceTool::commit, DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("commit", "existing", "flags"), &SurfaceTool::commit, DEFVAL(Variant()), DEFVAL(Mesh::ARRAY_COMPRESS_DEFAULT));
}
SurfaceTool::SurfaceTool() {
diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h
index cdaac643de..b180ffe260 100644
--- a/scene/resources/surface_tool.h
+++ b/scene/resources/surface_tool.h
@@ -127,10 +127,11 @@ public:
List<Vertex> &get_vertex_array() { return vertex_array; }
void create_from_triangle_arrays(const Array &p_arrays);
+ static Vector<Vertex> create_vertex_array_from_triangle_arrays(const Array &p_arrays);
Array commit_to_arrays();
void create_from(const Ref<Mesh> &p_existing, int p_surface);
void append_from(const Ref<Mesh> &p_existing, int p_surface, const Transform &p_xform);
- Ref<ArrayMesh> commit(const Ref<ArrayMesh> &p_existing = Ref<ArrayMesh>());
+ Ref<ArrayMesh> commit(const Ref<ArrayMesh> &p_existing = Ref<ArrayMesh>(), uint32_t p_flags = Mesh::ARRAY_COMPRESS_DEFAULT);
SurfaceTool();
};
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 6fab597d2b..bd6b917d4e 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -83,7 +83,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
}
}
} else if (what == "occluder_map") {
- tile_map[id].autotile_data.ocludder_map.clear();
+ tile_map[id].autotile_data.occluder_map.clear();
Array p = p_value;
Vector2 last_coord;
while (p.size() > 0) {
@@ -194,7 +194,7 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = p;
} else if (what == "occluder_map") {
Array p;
- for (Map<Vector2, Ref<OccluderPolygon2D> >::Element *E = tile_map[id].autotile_data.ocludder_map.front(); E; E = E->next()) {
+ for (Map<Vector2, Ref<OccluderPolygon2D> >::Element *E = tile_map[id].autotile_data.occluder_map.front(); E; E = E->next()) {
p.push_back(E->key());
p.push_back(E->value());
}
@@ -643,20 +643,20 @@ Ref<OccluderPolygon2D> TileSet::tile_get_light_occluder(int p_id) const {
void TileSet::autotile_set_light_occluder(int p_id, const Ref<OccluderPolygon2D> &p_light_occluder, const Vector2 &p_coord) {
ERR_FAIL_COND(!tile_map.has(p_id));
if (p_light_occluder.is_null()) {
- if (tile_map[p_id].autotile_data.ocludder_map.has(p_coord)) {
- tile_map[p_id].autotile_data.ocludder_map.erase(p_coord);
+ if (tile_map[p_id].autotile_data.occluder_map.has(p_coord)) {
+ tile_map[p_id].autotile_data.occluder_map.erase(p_coord);
}
} else {
- tile_map[p_id].autotile_data.ocludder_map[p_coord] = p_light_occluder;
+ tile_map[p_id].autotile_data.occluder_map[p_coord] = p_light_occluder;
}
}
Ref<OccluderPolygon2D> TileSet::autotile_get_light_occluder(int p_id, const Vector2 &p_coord) const {
ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<OccluderPolygon2D>());
- if (!tile_map[p_id].autotile_data.ocludder_map.has(p_coord)) {
+ if (!tile_map[p_id].autotile_data.occluder_map.has(p_coord)) {
return Ref<OccluderPolygon2D>();
} else {
- return tile_map[p_id].autotile_data.ocludder_map[p_coord];
+ return tile_map[p_id].autotile_data.occluder_map[p_coord];
}
}
@@ -688,7 +688,7 @@ const Map<Vector2, Ref<OccluderPolygon2D> > &TileSet::autotile_get_light_oclusio
static Map<Vector2, Ref<OccluderPolygon2D> > dummy;
ERR_FAIL_COND_V(!tile_map.has(p_id), dummy);
- return tile_map[p_id].autotile_data.ocludder_map;
+ return tile_map[p_id].autotile_data.occluder_map;
}
void TileSet::autotile_set_navigation_polygon(int p_id, const Ref<NavigationPolygon> &p_navigation_polygon, const Vector2 &p_coord) {
@@ -932,8 +932,8 @@ void TileSet::_bind_methods() {
ClassDB::bind_method(D_METHOD("find_tile_by_name", "name"), &TileSet::find_tile_by_name);
ClassDB::bind_method(D_METHOD("get_tiles_ids"), &TileSet::_get_tiles_ids);
- BIND_VMETHOD(MethodInfo("_is_tile_bound", PropertyInfo(Variant::INT, "drawn_id"), PropertyInfo(Variant::INT, "neighbor_id")));
- BIND_VMETHOD(MethodInfo("_forward_subtile_selection", PropertyInfo(Variant::INT, "autotile_id"), PropertyInfo(Variant::INT, "bitmask"), PropertyInfo(Variant::OBJECT, "tilemap", PROPERTY_HINT_NONE, "TileMap"), PropertyInfo(Variant::VECTOR2, "tile_location")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_tile_bound", PropertyInfo(Variant::INT, "drawn_id"), PropertyInfo(Variant::INT, "neighbor_id")));
+ BIND_VMETHOD(MethodInfo(Variant::VECTOR2, "_forward_subtile_selection", PropertyInfo(Variant::INT, "autotile_id"), PropertyInfo(Variant::INT, "bitmask"), PropertyInfo(Variant::OBJECT, "tilemap", PROPERTY_HINT_NONE, "TileMap"), PropertyInfo(Variant::VECTOR2, "tile_location")));
BIND_ENUM_CONSTANT(BITMASK_2X2);
BIND_ENUM_CONSTANT(BITMASK_3X3);
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 4d2b02f54b..deac583f62 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -76,7 +76,7 @@ public:
Size2 size;
Vector2 icon_coord;
Map<Vector2, uint16_t> flags;
- Map<Vector2, Ref<OccluderPolygon2D> > ocludder_map;
+ Map<Vector2, Ref<OccluderPolygon2D> > occluder_map;
Map<Vector2, Ref<NavigationPolygon> > navpoly_map;
Map<Vector2, int> priority_map;
diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp
index 5057c6ab9d..7fa7f0a45d 100644
--- a/servers/physics/body_sw.cpp
+++ b/servers/physics/body_sw.cpp
@@ -422,6 +422,18 @@ void BodySW::_compute_area_gravity_and_dampenings(const AreaSW *p_area) {
area_angular_damp += p_area->get_angular_damp();
}
+void BodySW::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock) {
+ if (lock) {
+ locked_axis |= p_axis;
+ } else {
+ locked_axis &= ~p_axis;
+ }
+}
+
+bool BodySW::is_axis_locked(PhysicsServer::BodyAxis p_axis) const {
+ return locked_axis & p_axis;
+}
+
void BodySW::integrate_forces(real_t p_step) {
if (mode == PhysicsServer::BODY_MODE_STATIC)
@@ -559,6 +571,22 @@ void BodySW::integrate_velocities(real_t p_step) {
if (fi_callback)
get_space()->body_add_to_state_query_list(&direct_state_query_list);
+ //apply axis lock linear
+ for (int i = 0; i < 3; i++) {
+ if (is_axis_locked((PhysicsServer::BodyAxis)(1 << i))) {
+ linear_velocity[i] = 0;
+ biased_linear_velocity[i] = 0;
+ new_transform.origin[i] = get_transform().origin[i];
+ }
+ }
+ //apply axis lock angular
+ for (int i = 0; i < 3; i++) {
+ if (is_axis_locked((PhysicsServer::BodyAxis)(1 << (i + 3)))) {
+ angular_velocity[i] = 0;
+ biased_angular_velocity[i] = 0;
+ }
+ }
+
if (mode == PhysicsServer::BODY_MODE_KINEMATIC) {
_set_transform(new_transform, false);
@@ -569,22 +597,6 @@ void BodySW::integrate_velocities(real_t p_step) {
return;
}
- //apply axis lock
- if (axis_lock != PhysicsServer::BODY_AXIS_LOCK_DISABLED) {
-
- int axis = axis_lock - 1;
- for (int i = 0; i < 3; i++) {
- if (i == axis) {
- linear_velocity[i] = 0;
- biased_linear_velocity[i] = 0;
- } else {
-
- angular_velocity[i] = 0;
- biased_angular_velocity[i] = 0;
- }
- }
- }
-
Vector3 total_angular_velocity = angular_velocity + biased_angular_velocity;
real_t ang_vel = total_angular_velocity.length();
@@ -744,7 +756,8 @@ BodySW::BodySW() :
CollisionObjectSW(TYPE_BODY),
active_list(this),
inertia_update_list(this),
- direct_state_query_list(this) {
+ direct_state_query_list(this),
+ locked_axis(0) {
mode = PhysicsServer::BODY_MODE_RIGID;
active = true;
@@ -775,7 +788,6 @@ BodySW::BodySW() :
continuous_cd = false;
can_sleep = false;
fi_callback = NULL;
- axis_lock = PhysicsServer::BODY_AXIS_LOCK_DISABLED;
}
BodySW::~BodySW() {
diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h
index 738d99c764..b6aa76c70a 100644
--- a/servers/physics/body_sw.h
+++ b/servers/physics/body_sw.h
@@ -53,7 +53,7 @@ class BodySW : public CollisionObjectSW {
real_t angular_damp;
real_t gravity_scale;
- PhysicsServer::BodyAxisLock axis_lock;
+ uint16_t locked_axis;
real_t kinematic_safe_margin;
real_t _inv_mass;
@@ -288,8 +288,8 @@ public:
_FORCE_INLINE_ Vector3 get_gravity() const { return gravity; }
_FORCE_INLINE_ real_t get_bounce() const { return bounce; }
- _FORCE_INLINE_ void set_axis_lock(PhysicsServer::BodyAxisLock p_lock) { axis_lock = p_lock; }
- _FORCE_INLINE_ PhysicsServer::BodyAxisLock get_axis_lock() const { return axis_lock; }
+ void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock);
+ bool is_axis_locked(PhysicsServer::BodyAxis p_axis) const;
void integrate_forces(real_t p_step);
void integrate_velocities(real_t p_step);
diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp
index ce63d84617..0a1d524839 100644
--- a/servers/physics/physics_server_sw.cpp
+++ b/servers/physics/physics_server_sw.cpp
@@ -794,20 +794,20 @@ void PhysicsServerSW::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_v
body->wakeup();
};
-void PhysicsServerSW::body_set_axis_lock(RID p_body, BodyAxisLock p_lock) {
+void PhysicsServerSW::body_set_axis_lock(RID p_body, BodyAxis p_axis, bool lock) {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
- body->set_axis_lock(p_lock);
+ body->set_axis_lock(p_axis, lock);
body->wakeup();
}
-PhysicsServerSW::BodyAxisLock PhysicsServerSW::body_get_axis_lock(RID p_body) const {
+bool PhysicsServerSW::body_is_axis_locked(RID p_body, BodyAxis p_axis) const {
const BodySW *body = body_owner.get(p_body);
- ERR_FAIL_COND_V(!body, BODY_AXIS_LOCK_DISABLED);
- return body->get_axis_lock();
+ ERR_FAIL_COND_V(!body, 0);
+ return body->is_axis_locked(p_axis);
}
void PhysicsServerSW::body_add_collision_exception(RID p_body, RID p_body_b) {
diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h
index fa754a1c8f..71547f24c8 100644
--- a/servers/physics/physics_server_sw.h
+++ b/servers/physics/physics_server_sw.h
@@ -203,8 +203,8 @@ public:
virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse);
virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity);
- virtual void body_set_axis_lock(RID p_body, BodyAxisLock p_lock);
- virtual BodyAxisLock body_get_axis_lock(RID p_body) const;
+ virtual void body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock);
+ virtual bool body_is_axis_locked(RID p_body, BodyAxis p_axis) const;
virtual void body_add_collision_exception(RID p_body, RID p_body_b);
virtual void body_remove_collision_exception(RID p_body, RID p_body_b);
diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp
index f693622ede..2aef12f04c 100644
--- a/servers/physics_server.cpp
+++ b/servers/physics_server.cpp
@@ -472,8 +472,8 @@ void PhysicsServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_apply_torque_impulse", "body", "impulse"), &PhysicsServer::body_apply_torque_impulse);
ClassDB::bind_method(D_METHOD("body_set_axis_velocity", "body", "axis_velocity"), &PhysicsServer::body_set_axis_velocity);
- ClassDB::bind_method(D_METHOD("body_set_axis_lock", "body", "axis"), &PhysicsServer::body_set_axis_lock);
- ClassDB::bind_method(D_METHOD("body_get_axis_lock", "body"), &PhysicsServer::body_get_axis_lock);
+ ClassDB::bind_method(D_METHOD("body_set_axis_lock", "body", "axis", "lock"), &PhysicsServer::body_set_axis_lock);
+ ClassDB::bind_method(D_METHOD("body_is_axis_locked", "body", "axis"), &PhysicsServer::body_is_axis_locked);
ClassDB::bind_method(D_METHOD("body_add_collision_exception", "body", "excepted_body"), &PhysicsServer::body_add_collision_exception);
ClassDB::bind_method(D_METHOD("body_remove_collision_exception", "body", "excepted_body"), &PhysicsServer::body_remove_collision_exception);
@@ -702,11 +702,12 @@ void PhysicsServer::_bind_methods() {
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP);
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO);
BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS);
-
- BIND_ENUM_CONSTANT(BODY_AXIS_LOCK_DISABLED);
- BIND_ENUM_CONSTANT(BODY_AXIS_LOCK_X);
- BIND_ENUM_CONSTANT(BODY_AXIS_LOCK_Y);
- BIND_ENUM_CONSTANT(BODY_AXIS_LOCK_Z);
+ BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_X);
+ BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_Y);
+ BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_Z);
+ BIND_ENUM_CONSTANT(BODY_AXIS_ANGULAR_X);
+ BIND_ENUM_CONSTANT(BODY_AXIS_ANGULAR_Y);
+ BIND_ENUM_CONSTANT(BODY_AXIS_ANGULAR_Z);
}
PhysicsServer::PhysicsServer() {
diff --git a/servers/physics_server.h b/servers/physics_server.h
index 4886317224..341d02eb87 100644
--- a/servers/physics_server.h
+++ b/servers/physics_server.h
@@ -421,15 +421,17 @@ public:
virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) = 0;
virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) = 0;
- enum BodyAxisLock {
- BODY_AXIS_LOCK_DISABLED,
- BODY_AXIS_LOCK_X,
- BODY_AXIS_LOCK_Y,
- BODY_AXIS_LOCK_Z,
+ enum BodyAxis {
+ BODY_AXIS_LINEAR_X = 1 << 0,
+ BODY_AXIS_LINEAR_Y = 1 << 1,
+ BODY_AXIS_LINEAR_Z = 1 << 2,
+ BODY_AXIS_ANGULAR_X = 1 << 3,
+ BODY_AXIS_ANGULAR_Y = 1 << 4,
+ BODY_AXIS_ANGULAR_Z = 1 << 5
};
- virtual void body_set_axis_lock(RID p_body, BodyAxisLock p_lock) = 0;
- virtual BodyAxisLock body_get_axis_lock(RID p_body) const = 0;
+ virtual void body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) = 0;
+ virtual bool body_is_axis_locked(RID p_body, BodyAxis p_axis) const = 0;
//fix
virtual void body_add_collision_exception(RID p_body, RID p_body_b) = 0;
@@ -692,7 +694,7 @@ VARIANT_ENUM_CAST(PhysicsServer::AreaSpaceOverrideMode);
VARIANT_ENUM_CAST(PhysicsServer::BodyMode);
VARIANT_ENUM_CAST(PhysicsServer::BodyParameter);
VARIANT_ENUM_CAST(PhysicsServer::BodyState);
-VARIANT_ENUM_CAST(PhysicsServer::BodyAxisLock);
+VARIANT_ENUM_CAST(PhysicsServer::BodyAxis);
VARIANT_ENUM_CAST(PhysicsServer::PinJointParam);
VARIANT_ENUM_CAST(PhysicsServer::JointType);
VARIANT_ENUM_CAST(PhysicsServer::HingeJointParam);
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 0ee70878dc..df41c3b5ce 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -636,6 +636,7 @@ public:
struct CommandPolyLine : public Command {
bool antialiased;
+ bool multiline;
Vector<Point2> triangles;
Vector<Color> triangle_colors;
Vector<Point2> lines;
@@ -643,6 +644,7 @@ public:
CommandPolyLine() {
type = TYPE_POLYLINE;
antialiased = false;
+ multiline = false;
}
};
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 4de902af58..e10a57c571 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -254,6 +254,9 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_TYPE_ISAMPLER2D, "isampler2D" },
{ TK_TYPE_USAMPLER2D, "usampler2D" },
{ TK_TYPE_SAMPLERCUBE, "samplerCube" },
+ { TK_INTERPOLATION_FLAT, "flat" },
+ { TK_INTERPOLATION_NO_PERSPECTIVE, "noperspective" },
+ { TK_INTERPOLATION_SMOOTH, "smooth" },
{ TK_PRECISION_LOW, "lowp" },
{ TK_PRECISION_MID, "mediump" },
{ TK_PRECISION_HIGH, "highp" },
@@ -658,6 +661,24 @@ ShaderLanguage::DataType ShaderLanguage::get_token_datatype(TokenType p_type) {
return DataType(p_type - TK_TYPE_VOID);
}
+bool ShaderLanguage::is_token_interpolation(TokenType p_type) {
+
+ return (
+ p_type == TK_INTERPOLATION_FLAT ||
+ p_type == TK_INTERPOLATION_NO_PERSPECTIVE ||
+ p_type == TK_INTERPOLATION_SMOOTH);
+}
+
+ShaderLanguage::DataInterpolation ShaderLanguage::get_token_interpolation(TokenType p_type) {
+
+ if (p_type == TK_INTERPOLATION_FLAT)
+ return INTERPOLATION_FLAT;
+ else if (p_type == TK_INTERPOLATION_NO_PERSPECTIVE)
+ return INTERPOLATION_NO_PERSPECTIVE;
+ else
+ return INTERPOLATION_SMOOTH;
+}
+
bool ShaderLanguage::is_token_precision(TokenType p_type) {
return (
@@ -3576,10 +3597,16 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
bool uniform = tk.type == TK_UNIFORM;
DataPrecision precision = PRECISION_DEFAULT;
+ DataInterpolation interpolation = INTERPOLATION_SMOOTH;
DataType type;
StringName name;
tk = _get_token();
+ if (is_token_interpolation(tk.type)) {
+ interpolation = get_token_interpolation(tk.type);
+ tk = _get_token();
+ }
+
if (is_token_precision(tk.type)) {
precision = get_token_precision(tk.type);
tk = _get_token();
@@ -3777,6 +3804,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
ShaderNode::Varying varying;
varying.type = type;
varying.precission = precision;
+ varying.interpolation = interpolation;
shader->varyings[name] = varying;
tk = _get_token();
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index 7a7f6dd71c..e092bf931f 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -72,6 +72,9 @@ public:
TK_TYPE_ISAMPLER2D,
TK_TYPE_USAMPLER2D,
TK_TYPE_SAMPLERCUBE,
+ TK_INTERPOLATION_FLAT,
+ TK_INTERPOLATION_NO_PERSPECTIVE,
+ TK_INTERPOLATION_SMOOTH,
TK_PRECISION_LOW,
TK_PRECISION_MID,
TK_PRECISION_HIGH,
@@ -192,6 +195,12 @@ public:
PRECISION_DEFAULT,
};
+ enum DataInterpolation {
+ INTERPOLATION_FLAT,
+ INTERPOLATION_NO_PERSPECTIVE,
+ INTERPOLATION_SMOOTH,
+ };
+
enum Operator {
OP_EQUAL,
OP_NOT_EQUAL,
@@ -431,6 +440,7 @@ public:
struct Varying {
DataType type;
+ DataInterpolation interpolation;
DataPrecision precission;
};
@@ -511,6 +521,8 @@ public:
static bool is_token_datatype(TokenType p_type);
static DataType get_token_datatype(TokenType p_type);
+ static bool is_token_interpolation(TokenType p_type);
+ static DataInterpolation get_token_interpolation(TokenType p_type);
static bool is_token_precision(TokenType p_type);
static DataPrecision get_token_precision(TokenType p_type);
static String get_datatype_name(DataType p_type);
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
index 31c09dc23d..0fed9cc961 100644
--- a/servers/visual/visual_server_canvas.cpp
+++ b/servers/visual/visual_server_canvas.cpp
@@ -416,6 +416,7 @@ void VisualServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Point
ERR_FAIL_COND(!pline);
pline->antialiased = p_antialiased;
+ pline->multiline = false;
if (p_width <= 1) {
pline->lines = p_points;
@@ -486,6 +487,90 @@ void VisualServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Point
canvas_item->commands.push_back(pline);
}
+void VisualServerCanvas::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) {
+
+ ERR_FAIL_COND(p_points.size() < 2);
+ Item *canvas_item = canvas_item_owner.getornull(p_item);
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandPolyLine *pline = memnew(Item::CommandPolyLine);
+ ERR_FAIL_COND(!pline);
+
+ pline->antialiased = false; //todo
+ pline->multiline = true;
+
+ // if (p_width <= 1) {
+ pline->lines = p_points;
+ pline->line_colors = p_colors;
+ if (pline->line_colors.size() == 0) {
+ pline->line_colors.push_back(Color(1, 1, 1, 1));
+ } else if (pline->line_colors.size() > 1 && pline->line_colors.size() != pline->lines.size()) {
+ pline->line_colors.resize(1);
+ }
+#if 0
+//width not yet
+ } else {
+ //make a trianglestrip for drawing the line...
+ Vector2 prev_t;
+ pline->triangles.resize(p_points.size() * 2);
+ if (p_antialiased) {
+ pline->lines.resize(p_points.size() * 2);
+ }
+
+ if (p_colors.size() == 0) {
+ pline->triangle_colors.push_back(Color(1, 1, 1, 1));
+ if (p_antialiased) {
+ pline->line_colors.push_back(Color(1, 1, 1, 1));
+ }
+ }
+ if (p_colors.size() == 1) {
+ pline->triangle_colors = p_colors;
+ pline->line_colors = p_colors;
+ } else {
+ pline->triangle_colors.resize(pline->triangles.size());
+ pline->line_colors.resize(pline->lines.size());
+ }
+
+ for (int i = 0; i < p_points.size(); i++) {
+
+ Vector2 t;
+ if (i == p_points.size() - 1) {
+ t = prev_t;
+ } else {
+ t = (p_points[i + 1] - p_points[i]).normalized().tangent();
+ if (i == 0) {
+ prev_t = t;
+ }
+ }
+
+ Vector2 tangent = ((t + prev_t).normalized()) * p_width * 0.5;
+
+ if (p_antialiased) {
+ pline->lines[i] = p_points[i] + tangent;
+ pline->lines[p_points.size() * 2 - i - 1] = p_points[i] - tangent;
+ if (pline->line_colors.size() > 1) {
+ pline->line_colors[i] = p_colors[i];
+ pline->line_colors[p_points.size() * 2 - i - 1] = p_colors[i];
+ }
+ }
+
+ pline->triangles[i * 2 + 0] = p_points[i] + tangent;
+ pline->triangles[i * 2 + 1] = p_points[i] - tangent;
+
+ if (pline->triangle_colors.size() > 1) {
+
+ pline->triangle_colors[i * 2 + 0] = p_colors[i];
+ pline->triangle_colors[i * 2 + 1] = p_colors[i];
+ }
+
+ prev_t = t;
+ }
+ }
+#endif
+ canvas_item->rect_dirty = true;
+ canvas_item->commands.push_back(pline);
+}
+
void VisualServerCanvas::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h
index a92370f1f0..3143ac847f 100644
--- a/servers/visual/visual_server_canvas.h
+++ b/servers/visual/visual_server_canvas.h
@@ -172,6 +172,7 @@ public:
void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false);
void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false);
+ void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false);
void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color);
void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color);
void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID());
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 9223d81e32..d843c443a2 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -551,6 +551,7 @@ public:
BIND6(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float, bool)
BIND5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
+ BIND5(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
BIND3(canvas_item_add_rect, RID, const Rect2 &, const Color &)
BIND4(canvas_item_add_circle, RID, const Point2 &, float, const Color &)
BIND7(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool, RID)
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index eef4720d22..dde69eedd3 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -2283,7 +2283,7 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co
if (angle > light_cache.spot_angle)
continue;
- float d = CLAMP(angle / light_cache.spot_angle, 1, 0);
+ float d = CLAMP(angle / light_cache.spot_angle, 0, 1);
att *= powf(1.0 - d, light_cache.spot_attenuation);
}
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index b58b1d917e..94f450c024 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -467,6 +467,7 @@ public:
FUNC6(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float, bool)
FUNC5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
+ FUNC5(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &)
FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &)
FUNC7(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool, RID)
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 350097c1b5..de5ef7da0a 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -815,6 +815,7 @@ public:
virtual void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false) = 0;
virtual void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false) = 0;
+ virtual void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false) = 0;
virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0;
virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0;
virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID()) = 0;
diff --git a/thirdparty/thekla_atlas/nvmesh/param/Atlas.cpp b/thirdparty/thekla_atlas/nvmesh/param/Atlas.cpp
index 4e41e76695..98f92cef96 100644
--- a/thirdparty/thekla_atlas/nvmesh/param/Atlas.cpp
+++ b/thirdparty/thekla_atlas/nvmesh/param/Atlas.cpp
@@ -38,6 +38,7 @@ using namespace nv;
/// Ctor.
Atlas::Atlas()
{
+ failed=false;
}
// Dtor.
@@ -100,6 +101,7 @@ void Atlas::extractCharts(const HalfEdge::Mesh * mesh)
void Atlas::computeCharts(const HalfEdge::Mesh * mesh, const SegmentationSettings & settings, const Array<uint> & unchartedMaterialArray)
{
+ failed=false;
MeshCharts * meshCharts = new MeshCharts(mesh);
meshCharts->computeCharts(settings, unchartedMaterialArray);
addMeshCharts(meshCharts);
@@ -235,6 +237,8 @@ float Atlas::packCharts(int quality, float texelsPerUnit, bool blockAlign, bool
{
AtlasPacker packer(this);
packer.packCharts(quality, texelsPerUnit, blockAlign, conservative);
+ if (hasFailed())
+ return 0;
return packer.computeAtlasUtilization();
}
diff --git a/thirdparty/thekla_atlas/nvmesh/param/Atlas.h b/thirdparty/thekla_atlas/nvmesh/param/Atlas.h
index 8b478207e3..41cfaea9cb 100644
--- a/thirdparty/thekla_atlas/nvmesh/param/Atlas.h
+++ b/thirdparty/thekla_atlas/nvmesh/param/Atlas.h
@@ -64,9 +64,12 @@ namespace nv
// Pack charts in the smallest possible rectangle.
float packCharts(int quality, float texelArea, bool blockAlign, bool conservative);
+ void setFailed() { failed = true; }
+ bool hasFailed() const { return failed; }
private:
+ bool failed;
Array<MeshCharts *> m_meshChartsArray;
};
diff --git a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp
index f2156899ae..5ce452cb9e 100644
--- a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp
+++ b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp
@@ -152,7 +152,7 @@ AtlasPacker::~AtlasPacker()
}
// This should compute convex hull and use rotating calipers to find the best box. Currently it uses a brute force method.
-static void computeBoundingBox(Chart * chart, Vector2 * majorAxis, Vector2 * minorAxis, Vector2 * minCorner, Vector2 * maxCorner)
+static bool computeBoundingBox(Chart * chart, Vector2 * majorAxis, Vector2 * minorAxis, Vector2 * minCorner, Vector2 * maxCorner)
{
// Compute list of boundary points.
Array<Vector2> points(16);
@@ -184,6 +184,9 @@ static void computeBoundingBox(Chart * chart, Vector2 * majorAxis, Vector2 * min
#if 1
Array<Vector2> hull;
+ if (points.size()==0) {
+ return false;
+ }
convexHull(points, hull, 0.00001f);
@@ -373,6 +376,8 @@ static void computeBoundingBox(Chart * chart, Vector2 * majorAxis, Vector2 * min
}
}*/
#endif
+
+ return true;
}
@@ -431,7 +436,10 @@ void AtlasPacker::packCharts(int quality, float texelsPerUnit, bool blockAligned
// Compute bounding box of chart.
Vector2 majorAxis, minorAxis, origin, end;
- computeBoundingBox(chart, &majorAxis, &minorAxis, &origin, &end);
+ if (!computeBoundingBox(chart, &majorAxis, &minorAxis, &origin, &end)) {
+ m_atlas->setFailed();
+ return;
+ }
nvCheck(isFinite(majorAxis) && isFinite(minorAxis) && isFinite(origin));
diff --git a/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp b/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp
new file mode 100644
index 0000000000..d6f0accf54
--- /dev/null
+++ b/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp
@@ -0,0 +1,271 @@
+
+#include "thekla_atlas.h"
+
+#include <cfloat>
+
+#include "nvmesh/halfedge/Edge.h"
+#include "nvmesh/halfedge/Mesh.h"
+#include "nvmesh/halfedge/Face.h"
+#include "nvmesh/halfedge/Vertex.h"
+#include "nvmesh/param/Atlas.h"
+
+#include "nvmath/Vector.inl"
+#include "nvmath/ftoi.h"
+
+#include "nvcore/Array.inl"
+
+
+using namespace Thekla;
+using namespace nv;
+
+
+inline Atlas_Output_Mesh * set_error(Atlas_Error * error, Atlas_Error code) {
+ if (error) *error = code;
+ return NULL;
+}
+
+
+
+static void input_to_mesh(const Atlas_Input_Mesh * input, HalfEdge::Mesh * mesh, Atlas_Error * error) {
+
+ Array<uint> canonicalMap;
+ canonicalMap.reserve(input->vertex_count);
+
+ for (int i = 0; i < input->vertex_count; i++) {
+ const Atlas_Input_Vertex & input_vertex = input->vertex_array[i];
+ const float * pos = input_vertex.position;
+ const float * nor = input_vertex.normal;
+ const float * tex = input_vertex.uv;
+
+ HalfEdge::Vertex * vertex = mesh->addVertex(Vector3(pos[0], pos[1], pos[2]));
+ vertex->nor.set(nor[0], nor[1], nor[2]);
+ vertex->tex.set(tex[0], tex[1]);
+
+ canonicalMap.append(input_vertex.first_colocal);
+ }
+
+ mesh->linkColocalsWithCanonicalMap(canonicalMap);
+
+
+ const int face_count = input->face_count;
+
+ int non_manifold_faces = 0;
+ for (int i = 0; i < face_count; i++) {
+ const Atlas_Input_Face & input_face = input->face_array[i];
+
+ int v0 = input_face.vertex_index[0];
+ int v1 = input_face.vertex_index[1];
+ int v2 = input_face.vertex_index[2];
+
+ HalfEdge::Face * face = mesh->addFace(v0, v1, v2);
+ if (face != NULL) {
+ face->material = input_face.material_index;
+ }
+ else {
+ non_manifold_faces++;
+ }
+ }
+
+ mesh->linkBoundary();
+
+ if (non_manifold_faces != 0 && error != NULL) {
+ *error = Atlas_Error_Invalid_Mesh_Non_Manifold;
+ }
+}
+
+static Atlas_Output_Mesh * mesh_atlas_to_output(const HalfEdge::Mesh * mesh, const Atlas & atlas, Atlas_Error * error) {
+
+ Atlas_Output_Mesh * output = new Atlas_Output_Mesh;
+
+ const MeshCharts * charts = atlas.meshAt(0);
+
+ // Allocate vertices.
+ const int vertex_count = charts->vertexCount();
+ output->vertex_count = vertex_count;
+ output->vertex_array = new Atlas_Output_Vertex[vertex_count];
+
+ int w = 0;
+ int h = 0;
+
+ // Output vertices.
+ const int chart_count = charts->chartCount();
+ for (int i = 0; i < chart_count; i++) {
+ const Chart * chart = charts->chartAt(i);
+ uint vertexOffset = charts->vertexCountBeforeChartAt(i);
+
+ const uint chart_vertex_count = chart->vertexCount();
+ for (uint v = 0; v < chart_vertex_count; v++) {
+ Atlas_Output_Vertex & output_vertex = output->vertex_array[vertexOffset + v];
+
+ uint original_vertex = chart->mapChartVertexToOriginalVertex(v);
+ output_vertex.xref = original_vertex;
+
+ Vector2 uv = chart->chartMesh()->vertexAt(v)->tex;
+ output_vertex.uv[0] = uv.x;
+ output_vertex.uv[1] = uv.y;
+ w = max(w, ftoi_ceil(uv.x));
+ h = max(h, ftoi_ceil(uv.y));
+ }
+ }
+
+ const int face_count = mesh->faceCount();
+ output->index_count = face_count * 3;
+ output->index_array = new int[face_count * 3];
+
+ // Set face indices.
+ for (int f = 0; f < face_count; f++) {
+ uint c = charts->faceChartAt(f);
+ uint i = charts->faceIndexWithinChartAt(f);
+ uint vertexOffset = charts->vertexCountBeforeChartAt(c);
+
+ const Chart * chart = charts->chartAt(c);
+ nvDebugCheck(chart->faceAt(i) == f);
+
+ const HalfEdge::Face * face = chart->chartMesh()->faceAt(i);
+ const HalfEdge::Edge * edge = face->edge;
+
+ output->index_array[3*f+0] = vertexOffset + edge->vertex->id;
+ output->index_array[3*f+1] = vertexOffset + edge->next->vertex->id;
+ output->index_array[3*f+2] = vertexOffset + edge->next->next->vertex->id;
+ }
+
+ *error = Atlas_Error_Success;
+ output->atlas_width = w;
+ output->atlas_height = h;
+
+ return output;
+}
+
+
+void Thekla::atlas_set_default_options(Atlas_Options * options) {
+ if (options != NULL) {
+ // These are the default values we use on The Witness.
+
+ options->charter = Atlas_Charter_Default;
+ options->charter_options.witness.proxy_fit_metric_weight = 2.0f;
+ options->charter_options.witness.roundness_metric_weight = 0.01f;
+ options->charter_options.witness.straightness_metric_weight = 6.0f;
+ options->charter_options.witness.normal_seam_metric_weight = 4.0f;
+ options->charter_options.witness.texture_seam_metric_weight = 0.5f;
+ options->charter_options.witness.max_chart_area = FLT_MAX;
+ options->charter_options.witness.max_boundary_length = FLT_MAX;
+
+ options->mapper = Atlas_Mapper_Default;
+
+ options->packer = Atlas_Packer_Default;
+ options->packer_options.witness.packing_quality = 0;
+ options->packer_options.witness.texel_area = 8;
+ options->packer_options.witness.block_align = true;
+ options->packer_options.witness.conservative = false;
+ }
+}
+
+
+Atlas_Output_Mesh * Thekla::atlas_generate(const Atlas_Input_Mesh * input, const Atlas_Options * options, Atlas_Error * error) {
+ // Validate args.
+ if (input == NULL || options == NULL || error == NULL) return set_error(error, Atlas_Error_Invalid_Args);
+
+ // Validate options.
+ if (options->charter != Atlas_Charter_Witness) {
+ return set_error(error, Atlas_Error_Invalid_Options);
+ }
+ if (options->charter == Atlas_Charter_Witness) {
+ // @@ Validate input options!
+ }
+
+ if (options->mapper != Atlas_Mapper_LSCM) {
+ return set_error(error, Atlas_Error_Invalid_Options);
+ }
+ if (options->mapper == Atlas_Mapper_LSCM) {
+ // No options.
+ }
+
+ if (options->packer != Atlas_Packer_Witness) {
+ return set_error(error, Atlas_Error_Invalid_Options);
+ }
+ if (options->packer == Atlas_Packer_Witness) {
+ // @@ Validate input options!
+ }
+
+ // Validate input mesh.
+ for (int i = 0; i < input->face_count; i++) {
+ int v0 = input->face_array[i].vertex_index[0];
+ int v1 = input->face_array[i].vertex_index[1];
+ int v2 = input->face_array[i].vertex_index[2];
+
+ if (v0 < 0 || v0 >= input->vertex_count ||
+ v1 < 0 || v1 >= input->vertex_count ||
+ v2 < 0 || v2 >= input->vertex_count)
+ {
+ return set_error(error, Atlas_Error_Invalid_Mesh);
+ }
+ }
+
+
+ // Build half edge mesh.
+ AutoPtr<HalfEdge::Mesh> mesh(new HalfEdge::Mesh);
+
+ input_to_mesh(input, mesh.ptr(), error);
+
+ if (*error == Atlas_Error_Invalid_Mesh) {
+ return NULL;
+ }
+
+ Atlas atlas;
+
+ // Charter.
+ if (options->charter == Atlas_Charter_Extract) {
+ return set_error(error, Atlas_Error_Not_Implemented);
+ }
+ else if (options->charter == Atlas_Charter_Witness) {
+ SegmentationSettings segmentation_settings;
+ segmentation_settings.proxyFitMetricWeight = options->charter_options.witness.proxy_fit_metric_weight;
+ segmentation_settings.roundnessMetricWeight = options->charter_options.witness.roundness_metric_weight;
+ segmentation_settings.straightnessMetricWeight = options->charter_options.witness.straightness_metric_weight;
+ segmentation_settings.normalSeamMetricWeight = options->charter_options.witness.normal_seam_metric_weight;
+ segmentation_settings.textureSeamMetricWeight = options->charter_options.witness.texture_seam_metric_weight;
+ segmentation_settings.maxChartArea = options->charter_options.witness.max_chart_area;
+ segmentation_settings.maxBoundaryLength = options->charter_options.witness.max_boundary_length;
+
+ Array<uint> uncharted_materials;
+ atlas.computeCharts(mesh.ptr(), segmentation_settings, uncharted_materials);
+ }
+
+ if (atlas.hasFailed())
+ return NULL;
+
+ // Mapper.
+ if (options->mapper == Atlas_Mapper_LSCM) {
+ atlas.parameterizeCharts();
+ }
+
+ if (atlas.hasFailed())
+ return NULL;
+
+ // Packer.
+ if (options->packer == Atlas_Packer_Witness) {
+ int packing_quality = options->packer_options.witness.packing_quality;
+ float texel_area = options->packer_options.witness.texel_area;
+ int block_align = options->packer_options.witness.block_align;
+ int conservative = options->packer_options.witness.conservative;
+
+ /*float utilization =*/ atlas.packCharts(packing_quality, texel_area, block_align, conservative);
+ }
+
+ if (atlas.hasFailed())
+ return NULL;
+
+
+ // Build output mesh.
+ return mesh_atlas_to_output(mesh.ptr(), atlas, error);
+}
+
+
+void Thekla::atlas_free(Atlas_Output_Mesh * output) {
+ if (output != NULL) {
+ delete [] output->vertex_array;
+ delete [] output->index_array;
+ delete output;
+ }
+}
+
diff --git a/thirdparty/thekla_atlas/thekla/thekla_atlas.h b/thirdparty/thekla_atlas/thekla/thekla_atlas.h
new file mode 100644
index 0000000000..1d0716e781
--- /dev/null
+++ b/thirdparty/thekla_atlas/thekla/thekla_atlas.h
@@ -0,0 +1,116 @@
+
+// Thekla Atlas Generator
+
+namespace Thekla {
+
+enum Atlas_Charter {
+ Atlas_Charter_Witness, // Options: threshold
+ Atlas_Charter_Extract, // Options: ---
+ Atlas_Charter_Default = Atlas_Charter_Witness
+};
+
+enum Atlas_Mapper {
+ Atlas_Mapper_LSCM, // Options: ---
+ Atlas_Mapper_Default = Atlas_Mapper_LSCM
+};
+
+enum Atlas_Packer {
+ Atlas_Packer_Witness, // Options: texel_area
+ Atlas_Packer_Default = Atlas_Packer_Witness
+};
+
+struct Atlas_Options {
+ Atlas_Charter charter;
+ union {
+ struct {
+ float proxy_fit_metric_weight;
+ float roundness_metric_weight;
+ float straightness_metric_weight;
+ float normal_seam_metric_weight;
+ float texture_seam_metric_weight;
+ float max_chart_area;
+ float max_boundary_length;
+ } witness;
+ struct {
+ } extract;
+ } charter_options;
+
+ Atlas_Mapper mapper;
+ union {
+ } mapper_options;
+
+ Atlas_Packer packer;
+ union {
+ struct {
+ int packing_quality;
+ float texel_area; // This is not really texel area, but 1 / texel width?
+ bool block_align; // Align charts to 4x4 blocks.
+ bool conservative; // Pack charts with extra padding.
+ } witness;
+ } packer_options;
+};
+
+struct Atlas_Input_Vertex {
+ float position[3];
+ float normal[3];
+ float uv[2];
+ int first_colocal;
+};
+
+struct Atlas_Input_Face {
+ int vertex_index[3];
+ int material_index;
+};
+
+struct Atlas_Input_Mesh {
+ int vertex_count;
+ int face_count;
+ Atlas_Input_Vertex * vertex_array;
+ Atlas_Input_Face * face_array;
+};
+
+struct Atlas_Output_Vertex {
+ float uv[2];
+ int xref; // Index of input vertex from which this output vertex originated.
+};
+
+struct Atlas_Output_Mesh {
+ int atlas_width;
+ int atlas_height;
+ int vertex_count;
+ int index_count;
+ Atlas_Output_Vertex * vertex_array;
+ int * index_array;
+};
+
+enum Atlas_Error {
+ Atlas_Error_Success,
+ Atlas_Error_Invalid_Args,
+ Atlas_Error_Invalid_Options,
+ Atlas_Error_Invalid_Mesh,
+ Atlas_Error_Invalid_Mesh_Non_Manifold,
+ Atlas_Error_Not_Implemented,
+};
+
+void atlas_set_default_options(Atlas_Options * options);
+
+Atlas_Output_Mesh * atlas_generate(const Atlas_Input_Mesh * input, const Atlas_Options * options, Atlas_Error * error);
+
+void atlas_free(Atlas_Output_Mesh * output);
+
+
+/*
+
+Should we represent the input mesh with an opaque structure that simply holds pointers to the user data? That would allow us to avoid having to copy attributes to an intermediate representation.
+
+struct Atlas_Input_Mesh;
+
+void mesh_set_vertex_position(Atlas_Input_Mesh * mesh, float * ptr, int stride);
+void mesh_set_vertex_normal(Atlas_Input_Mesh * mesh, float * ptr, int stride);
+void mesh_set_vertex_uv(Mesh * mesh, float * ptr, int stride);
+
+void mesh_set_index(Mesh * mesh, int * ptr);
+*/
+
+} // Thekla namespace
+