aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/math/a_star.cpp25
-rw-r--r--core/math/a_star.h3
-rw-r--r--doc/base/classes.xml19
-rw-r--r--editor/editor_run.cpp8
-rw-r--r--editor/plugins/sample_library_editor_plugin.cpp25
-rw-r--r--editor/plugins/tile_map_editor_plugin.cpp49
-rw-r--r--editor/property_editor.cpp2
-rw-r--r--editor/scene_tree_editor.cpp1
-rw-r--r--main/input_default.cpp64
-rw-r--r--modules/gdscript/gd_parser.cpp104
-rw-r--r--modules/gdscript/gd_tokenizer.cpp2
-rw-r--r--modules/gdscript/gd_tokenizer.h1
-rw-r--r--platform/android/build.gradle.template1
-rw-r--r--platform/android/detect.py2
-rw-r--r--platform/windows/os_windows.cpp3
-rw-r--r--platform/x11/os_x11.cpp9
-rw-r--r--scene/2d/area_2d.cpp11
-rw-r--r--scene/2d/area_2d.h1
-rw-r--r--scene/2d/sample_player_2d.cpp3
-rw-r--r--scene/2d/screen_button.cpp31
-rw-r--r--scene/2d/screen_button.h4
-rw-r--r--scene/3d/area.cpp34
-rw-r--r--scene/3d/area.h2
-rw-r--r--scene/3d/spatial_sample_player.cpp1
-rw-r--r--scene/animation/tween.cpp1
-rw-r--r--scene/audio/sample_player.cpp18
-rw-r--r--scene/audio/sample_player.h1
-rw-r--r--scene/main/scene_main_loop.cpp5
-rw-r--r--scene/main/scene_main_loop.h1
-rw-r--r--scene/main/timer.cpp6
-rw-r--r--scene/main/viewport.cpp4
-rw-r--r--scene/resources/sample_library.cpp18
-rw-r--r--scene/resources/sample_library.h4
-rw-r--r--scene/scene_string_names.cpp3
-rw-r--r--scene/scene_string_names.h3
-rw-r--r--servers/spatial_sound/spatial_sound_server_sw.cpp30
-rw-r--r--servers/spatial_sound/spatial_sound_server_sw.h3
-rw-r--r--servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp30
-rw-r--r--servers/spatial_sound_2d/spatial_sound_2d_server_sw.h3
-rw-r--r--servers/spatial_sound_2d_server.h2
-rw-r--r--servers/spatial_sound_server.h2
41 files changed, 469 insertions, 70 deletions
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index 401a33da8..0ba82ff88 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -28,6 +28,8 @@
/*************************************************************************/
#include "a_star.h"
#include "geometry.h"
+#include "scene/scene_string_names.h"
+#include "script_language.h"
int AStar::get_available_point_id() const {
@@ -187,7 +189,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
Point *n = begin_point->neighbours[i];
n->prev_point = begin_point;
- n->distance = n->pos.distance_to(begin_point->pos);
+ n->distance = _compute_cost(n->id, begin_point->id);
n->distance *= n->weight_scale;
n->last_pass = pass;
open_list.add(&n->list);
@@ -215,7 +217,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
Point *p = E->self();
float cost = p->distance;
- cost += p->pos.distance_to(end_point->pos);
+ cost += _estimate_cost(p->id, end_point->id);
cost *= p->weight_scale;
if (cost < least_cost) {
@@ -233,7 +235,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
Point *e = p->neighbours[i];
- float distance = p->pos.distance_to(e->pos) + p->distance;
+ float distance = _compute_cost(p->id, e->id) + p->distance;
distance *= e->weight_scale;
if (e->last_pass == pass) {
@@ -274,6 +276,20 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
return found_route;
}
+float AStar::_estimate_cost(int p_from_id, int p_to_id) {
+ if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_estimate_cost))
+ return get_script_instance()->call(SceneStringNames::get_singleton()->_estimate_cost, p_from_id, p_to_id);
+
+ return points[p_from_id]->pos.distance_to(points[p_to_id]->pos);
+}
+
+float AStar::_compute_cost(int p_from_id, int p_to_id) {
+ if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_compute_cost))
+ return get_script_instance()->call(SceneStringNames::get_singleton()->_compute_cost, p_from_id, p_to_id);
+
+ return points[p_from_id]->pos.distance_to(points[p_to_id]->pos);
+}
+
DVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) {
ERR_FAIL_COND_V(!points.has(p_from_id), DVector<Vector3>());
@@ -395,6 +411,9 @@ void AStar::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_point_path", "from_id", "to_id"), &AStar::get_point_path);
ObjectTypeDB::bind_method(_MD("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")));
}
AStar::AStar() {
diff --git a/core/math/a_star.h b/core/math/a_star.h
index c88591cf9..a0e9fc2cc 100644
--- a/core/math/a_star.h
+++ b/core/math/a_star.h
@@ -93,6 +93,9 @@ class AStar : public Reference {
protected:
static void _bind_methods();
+ virtual float _estimate_cost(int p_from_id, int p_to_id);
+ virtual float _compute_cost(int p_from_id, int p_to_id);
+
public:
int get_available_point_id() const;
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index aad217b8e..0f3e1a3f0 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -33677,6 +33677,7 @@
</brief_description>
<description>
Library that contains a collection of [Sample], each identified by a text ID. This is used as a data container for the majority of the SamplePlayer classes and derivatives.
+ Sample players will never yield an active (currently playing) voice for a new playback request when there are no inactive voices available if the priority of the sample requested to be played is lower than that of every currently played samples.
</description>
<methods>
<method name="add_sample">
@@ -33737,6 +33738,15 @@
Return the volume (in dB) for the given sample.
</description>
</method>
+ <method name="sample_get_priority" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <description>
+ Return the priority for the given sample.
+ </description>
+ </method>
<method name="sample_set_pitch_scale">
<argument index="0" name="name" type="String">
</argument>
@@ -33755,6 +33765,15 @@
Set the volume (in dB) for the given sample.
</description>
</method>
+ <method name="sample_set_priority">
+ <argument index="0" name="name" type="String">
+ </argument>
+ <argument index="1" name="priority" type="int">
+ </argument>
+ <description>
+ Set the priority for the given sample.
+ </description>
+ </method>
</methods>
<constants>
</constants>
diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp
index e571c1971..0e9c0b77b 100644
--- a/editor/editor_run.cpp
+++ b/editor/editor_run.cpp
@@ -47,7 +47,13 @@ Error EditorRun::run(const String &p_scene, const String p_custom_args, const Li
if (true) {
args.push_back("-rdebug");
- args.push_back("localhost:" + String::num(GLOBAL_DEF("debug/debug_port", 6007)));
+#ifdef WINDOWS_ENABLED
+ // Avoid failing DNS lookup on disconnected Windows machines.
+ const char *debug_host = "127.0.0.1:";
+#else
+ const char *debug_host = "localhost:";
+#endif
+ args.push_back(debug_host + String::num(GLOBAL_DEF("debug/debug_port", 6007)));
}
args.push_back("-epid");
diff --git a/editor/plugins/sample_library_editor_plugin.cpp b/editor/plugins/sample_library_editor_plugin.cpp
index 08231d6eb..f626b4d33 100644
--- a/editor/plugins/sample_library_editor_plugin.cpp
+++ b/editor/plugins/sample_library_editor_plugin.cpp
@@ -175,6 +175,11 @@ void SampleLibraryEditor::_item_edited() {
StringName n = s->get_text(0);
sample_library->sample_set_pitch_scale(n, s->get_range(4));
+
+ } else if (tree->get_selected_column() == 5) { // Priority
+
+ StringName n = s->get_text(0);
+ sample_library->sample_set_priority(n, s->get_range(5));
}
}
@@ -248,9 +253,16 @@ void SampleLibraryEditor::_update_library() {
ti->set_editable(4, true);
ti->set_range(4, sample_library->sample_get_pitch_scale(E->get()));
+ // Priority
+ ti->set_cell_mode(5, TreeItem::CELL_MODE_RANGE);
+ ti->set_range_config(5, 0, 100, 1);
+ ti->set_selectable(5, true);
+ ti->set_editable(5, true);
+ ti->set_range(5, sample_library->sample_get_priority(E->get()));
+
// Delete
- ti->set_cell_mode(5, TreeItem::CELL_MODE_STRING);
- ti->add_button(5, get_icon("Remove", "EditorIcons"));
+ ti->set_cell_mode(6, TreeItem::CELL_MODE_STRING);
+ ti->add_button(6, get_icon("Remove", "EditorIcons"));
}
//player->add_sample("default",sample);
@@ -411,7 +423,7 @@ SampleLibraryEditor::SampleLibraryEditor() {
file->set_mode(EditorFileDialog::MODE_OPEN_FILES);
tree = memnew(Tree);
- tree->set_columns(6);
+ tree->set_columns(7);
add_child(tree);
tree->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 5);
tree->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 5);
@@ -423,18 +435,21 @@ SampleLibraryEditor::SampleLibraryEditor() {
tree->set_column_title(2, TTR("Format"));
tree->set_column_title(3, "dB");
tree->set_column_title(4, TTR("Pitch"));
- tree->set_column_title(5, "");
+ tree->set_column_title(5, TTR("Priority"));
+ tree->set_column_title(6, "");
tree->set_column_min_width(1, 150);
tree->set_column_min_width(2, 100);
tree->set_column_min_width(3, 50);
tree->set_column_min_width(4, 50);
- tree->set_column_min_width(5, 32);
+ tree->set_column_min_width(5, 60);
+ tree->set_column_min_width(6, 32);
tree->set_column_expand(1, false);
tree->set_column_expand(2, false);
tree->set_column_expand(3, false);
tree->set_column_expand(4, false);
tree->set_column_expand(5, false);
+ tree->set_column_expand(6, false);
tree->set_drag_forwarding(this);
diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp
index 6e52c41d1..6c32650a4 100644
--- a/editor/plugins/tile_map_editor_plugin.cpp
+++ b/editor/plugins/tile_map_editor_plugin.cpp
@@ -192,6 +192,19 @@ void TileMapEditor::_sbox_input(const InputEvent &p_ie) {
}
}
+// Implementation detail of TileMapEditor::_update_palette();
+// in modern C++ this could have been inside its body
+namespace {
+struct _PaletteEntry {
+ int id;
+ String name;
+
+ bool operator<(const _PaletteEntry &p_rhs) const {
+ return name < p_rhs.name;
+ }
+};
+}
+
void TileMapEditor::_update_palette() {
if (!node)
@@ -214,6 +227,8 @@ void TileMapEditor::_update_palette() {
min_size *= EDSCALE;
int hseparation = EDITOR_DEF("tile_map/palette_item_hseparation", 8);
bool show_tile_names = bool(EDITOR_DEF("tile_map/show_tile_names", true));
+ bool show_tile_ids = bool(EDITOR_DEF("tile_map/show_tile_ids", true));
+ bool sort_by_name = bool(EDITOR_DEF("tile_map/sort_tiles_by_name", false));
palette->add_constant_override("hseparation", hseparation * EDSCALE);
palette->add_constant_override("vseparation", 8 * EDSCALE);
@@ -223,12 +238,20 @@ void TileMapEditor::_update_palette() {
String filter = search_box->get_text().strip_edges();
+ Vector<_PaletteEntry> entries;
+
for (List<int>::Element *E = tiles.front(); E; E = E->next()) {
- String name;
+ String name = tileset->tile_get_name(E->get());
- if (tileset->tile_get_name(E->get()) != "") {
- name = itos(E->get()) + " - " + tileset->tile_get_name(E->get());
+ if (name != "") {
+ if (show_tile_ids) {
+ if (sort_by_name) {
+ name = name + " - " + itos(E->get());
+ } else {
+ name = itos(E->get()) + " - " + name;
+ }
+ }
} else {
name = "#" + itos(E->get());
}
@@ -236,16 +259,26 @@ void TileMapEditor::_update_palette() {
if (filter != "" && !filter.is_subsequence_ofi(name))
continue;
+ const _PaletteEntry entry = { E->get(), name };
+ entries.push_back(entry);
+ }
+
+ if (sort_by_name) {
+ entries.sort();
+ }
+
+ for (int i = 0; i < entries.size(); i++) {
+
if (show_tile_names) {
- palette->add_item(name);
+ palette->add_item(entries[i].name);
} else {
palette->add_item(String());
}
- Ref<Texture> tex = tileset->tile_get_texture(E->get());
+ Ref<Texture> tex = tileset->tile_get_texture(entries[i].id);
if (tex.is_valid()) {
- Rect2 region = tileset->tile_get_region(E->get());
+ Rect2 region = tileset->tile_get_region(entries[i].id);
if (!region.has_no_area())
palette->set_item_icon_region(palette->get_item_count() - 1, region);
@@ -253,7 +286,7 @@ void TileMapEditor::_update_palette() {
palette->set_item_icon(palette->get_item_count() - 1, tex);
}
- palette->set_item_metadata(palette->get_item_count() - 1, E->get());
+ palette->set_item_metadata(palette->get_item_count() - 1, entries[i].id);
}
palette->set_same_column_width(true);
@@ -1565,6 +1598,8 @@ TileMapEditorPlugin::TileMapEditorPlugin(EditorNode *p_node) {
EDITOR_DEF("tile_map/preview_size", 64);
EDITOR_DEF("tile_map/palette_item_hseparation", 8);
EDITOR_DEF("tile_map/show_tile_names", true);
+ EDITOR_DEF("tile_map/show_tile_ids", true);
+ EDITOR_DEF("tile_map/sort_tiles_by_name", false);
EDITOR_DEF("tile_map/bucket_fill_preview", true);
tile_map_editor = memnew(TileMapEditor(p_node));
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index 33f50a99c..1d0449e44 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -3385,8 +3385,8 @@ void PropertyEditor::_item_edited() {
} break;
case Variant::BOOL: {
- _edit_set(name, item->is_checked(1));
item->set_tooltip(1, item->is_checked(1) ? "True" : "False");
+ _edit_set(name, item->is_checked(1));
} break;
case Variant::INT:
case Variant::REAL: {
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index 5123ae6a7..d862a02d3 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -1110,6 +1110,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope
tree->set_anchor(MARGIN_BOTTOM, ANCHOR_END);
tree->set_begin(Point2(0, p_label ? 18 : 0));
tree->set_end(Point2(0, 0));
+ tree->add_constant_override("button_margin", 0);
add_child(tree);
diff --git a/main/input_default.cpp b/main/input_default.cpp
index 61169985b..e9d1cf53a 100644
--- a/main/input_default.cpp
+++ b/main/input_default.cpp
@@ -440,12 +440,27 @@ void InputDefault::warp_mouse_pos(const Vector2 &p_to) {
Point2i InputDefault::warp_mouse_motion(const InputEventMouseMotion &p_motion, const Rect2 &p_rect) {
- const Point2i rel_warped(Math::fmod(p_motion.relative_x, p_rect.size.x), Math::fmod(p_motion.relative_y, p_rect.size.y));
+ // The relative distance reported for the next event after a warp is in the boundaries of the
+ // size of the rect on that axis, but it may be greater, in which case there's not problem as fmod()
+ // will warp it, but if the pointer has moved in the opposite direction between the pointer relocation
+ // and the subsequent event, the reported relative distance will be less than the size of the rect
+ // and thus fmod() will be disabled for handling the situation.
+ // And due to this mouse warping mechanism being stateless, we need to apply some heuristics to
+ // detect the warp: if the relative distance is greater than the half of the size of the relevant rect
+ // (checked per each axis), it will be considered as the consequence of a former pointer warp.
+
+ const Point2i rel_sgn(p_motion.relative_x >= 0.0f ? 1 : -1, p_motion.relative_y >= 0.0 ? 1 : -1);
+ const Size2i warp_margin = p_rect.size * 0.5f;
+ const Point2i rel_warped(
+ Math::fmod(p_motion.relative_x + rel_sgn.x * warp_margin.x, p_rect.size.x) - rel_sgn.x * warp_margin.x,
+ Math::fmod(p_motion.relative_y + rel_sgn.y * warp_margin.y, p_rect.size.y) - rel_sgn.y * warp_margin.y);
+
const Point2i pos_local = Point2i(p_motion.global_x, p_motion.global_y) - p_rect.pos;
const Point2i pos_warped(Math::fposmod(pos_local.x, p_rect.size.x), Math::fposmod(pos_local.y, p_rect.size.y));
if (pos_warped != pos_local) {
OS::get_singleton()->warp_mouse_pos(pos_warped + p_rect.pos);
}
+
return rel_warped;
}
@@ -523,6 +538,7 @@ static const char *s_ControllerMappings[] = {
"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,",
"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,",
"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,",
"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,",
@@ -533,25 +549,28 @@ static const char *s_ControllerMappings[] = {
"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,",
- "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",
+ "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,",
+ "4c05a00b000000000000504944564944,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,",
"4c05c405000000000000504944564944,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,",
+ "4c05cc09000000000000504944564944,Sony DualShock 4,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,",
"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",
+ "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,",
"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,",
"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,",
"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,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,",
"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,Trust GXT 28,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,",
+ "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,",
"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,",
@@ -576,21 +595,27 @@ static const char *s_ControllerMappings[] = {
"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,",
"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,",
"4f0400000000000015b3000000000000,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,",
"5e040000000000008e02000000000000,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,",
"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. */
"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. */
"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,",
+ "79000000000000001100000000000000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a3,lefty:a4,",
+ "81170000000000007e05000000000000,Sega Saturn,x:b0,a:b2,b:b4,y:b6,start:b13,dpleft:b15,dpdown:b16,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,lefttrigger:b10,rightshoulder:b9,righttrigger:a4,righttrigger:b11,leftx:a0,lefty:a2,",
"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,",
"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,",
"d814000000000000cecf000000000000,MC Cthulhu,leftx:,lefty:,rightx:,righty:,lefttrigger:b6,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,righttrigger:b7,",
#endif
@@ -598,24 +623,30 @@ static const char *s_ControllerMappings[] = {
"0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,x:b2,y:b3,start:b7,back:b6,guide:b8,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,lefttrigger:a5,righttrigger:a4,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
"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",
"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,",
+ "030000001008000001e5000010010000,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,",
+ "03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,x:b3,y:b0,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,",
"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,",
"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,",
"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,",
+ "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,",
"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,",
"030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,x:b1,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,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,",
"030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,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,",
"030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,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:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,",
- "030000005e0400001907000000010000,X360 Wireless Controller,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:h0.8,lefttrigger:a2,x:b2,dpup:h0.1,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:h0.2,righttrigger:a5,b:b1,",
+ "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,",
+ "030000005e0400008502000000010000,Microsoft X-Box pad (Japan),x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
"030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
"030000005e0400008e02000001000000,Microsoft X-Box 360 pad,leftstick:b9,leftx:a0,lefty:a1,dpdown:h0.1,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:h0.2,lefttrigger:a2,x:b2,dpup:h0.4,back:b6,leftshoulder:b4,y:b3,a:b0,dpright:h0.8,righttrigger:a5,b:b1,",
"030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,",
@@ -623,12 +654,15 @@ static const char *s_ControllerMappings[] = {
"030000005e0400008e02000014010000,X360 Controller,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,",
"030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,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,",
"030000005e0400008e02000062230000,Microsoft X-Box 360 pad,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,",
- "030000005e0400009102000007010000,X360 Wireless Controller,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,",
+ "030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,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,",
+ "030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,",
+ "030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,",
"030000005e040000d102000001010000,Microsoft X-Box One pad,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,",
"030000005e040000dd02000003020000,Microsoft X-Box One pad v2,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,",
"03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13,",
"030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,",
"030000006d04000016c2000010010000,Logitech Logitech Dual Action,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,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,",
+ "030000006d04000016c2000011010000,Logitech F310 Gamepad (DInput),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,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,",
"030000006d04000018c2000010010000,Logitech 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,",
"030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,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:b0,y:b3,",
"030000006d04000019c2000011010000,Logitech F710 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,",
@@ -645,6 +679,7 @@ static const char *s_ControllerMappings[] = {
"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,",
"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,",
@@ -657,24 +692,29 @@ static const char *s_ControllerMappings[] = {
"03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,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:a4,lefttrigger:b6,righttrigger:b7,",
"03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
"03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
+ "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,",
"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,",
"03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,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,",
+ "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,",
"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,leftx:a0,lefty:a1,dpdown:b9,rightstick:b7,rightshoulder:b5,rightx:a3,start:b16,righty:a4,dpleft:b10,lefttrigger:b12,x:b1,dpup:b8,back:b14,leftstick:b6,leftshoulder:b4,y:b2,a:b0,dpright:b11,righttrigger:b13,b:b3,",
- "05000000362800000100000003010000,OUYA Game Controller,leftx:a0,lefty:a1,dpdown:b9,rightstick:b7,rightshoulder:b5,rightx:a3,start:b16,righty:a4,dpleft:b10,lefttrigger:b12,x:b1,dpup:b8,back:b14,leftstick:b6,leftshoulder:b4,y:b2,a:b0,dpright:b11,righttrigger:b13,b:b3,",
- "05000000362800000100000004010000,OUYA Game Controller,leftx:a0,lefty:a1,dpdown:b9,rightstick:b7,rightshoulder:b5,rightx:a3,start:b16,righty:a4,dpleft:b10,lefttrigger:b12,x:b1,dpup:b8,back:b14,leftstick:b6,leftshoulder:b4,y:b2,a:b0,dpright:b11,righttrigger:b13,b:b3,",
- "05000000380700006652000025010000,Mad Catz C.T.R.L.R,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,",
+ "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,",
+ "05000000362800000100000003010000,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,",
+ "05000000380700006652000025010000,Mad Catz C.T.R.L.R ,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,",
"0500000047532047616d657061640000,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,",
"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,",
"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,",
#endif
@@ -989,6 +1029,8 @@ void InputDefault::parse_mapping(String p_mapping) {
_THREAD_SAFE_METHOD_;
JoyDeviceMapping mapping;
+ for (int i = 0; i < HAT_MAX; ++i)
+ mapping.hat[i].index = 1024 + i;
Vector<String> entry = p_mapping.split(",");
CharString uid;
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp
index 74a3d5e9e..009100cb3 100644
--- a/modules/gdscript/gd_parser.cpp
+++ b/modules/gdscript/gd_parser.cpp
@@ -3153,6 +3153,110 @@ void GDParser::_parse_class(ClassNode *p_class) {
}
} break;
+ case GDTokenizer::TK_PR_ENUM: {
+ //mutiple constant declarations..
+
+ int last_assign = -1; // Incremented by 1 right before the assingment.
+ String enum_name;
+ Dictionary enum_dict;
+
+ tokenizer->advance();
+ if (tokenizer->get_token() == GDTokenizer::TK_IDENTIFIER) {
+ enum_name = tokenizer->get_token_identifier();
+ tokenizer->advance();
+ }
+ if (tokenizer->get_token() != GDTokenizer::TK_CURLY_BRACKET_OPEN) {
+ _set_error("Expected '{' in enum declaration");
+ return;
+ }
+ tokenizer->advance();
+
+ while (true) {
+ if (tokenizer->get_token() == GDTokenizer::TK_NEWLINE) {
+
+ tokenizer->advance(); // Ignore newlines
+ } else if (tokenizer->get_token() == GDTokenizer::TK_CURLY_BRACKET_CLOSE) {
+
+ tokenizer->advance();
+ break; // End of enum
+ } else if (tokenizer->get_token() != GDTokenizer::TK_IDENTIFIER) {
+
+ if (tokenizer->get_token() == GDTokenizer::TK_EOF) {
+ _set_error("Unexpected end of file.");
+ } else {
+ _set_error(String("Unexpected ") + GDTokenizer::get_token_name(tokenizer->get_token()) + ", expected identifier");
+ }
+
+ return;
+ } else { // tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER
+ ClassNode::Constant constant;
+
+ constant.identifier = tokenizer->get_token_identifier();
+
+ tokenizer->advance();
+
+ if (tokenizer->get_token() == GDTokenizer::TK_OP_ASSIGN) {
+ tokenizer->advance();
+
+ Node *subexpr = NULL;
+
+ subexpr = _parse_and_reduce_expression(p_class, true, true);
+ if (!subexpr) {
+ if (_recover_from_completion()) {
+ break;
+ }
+ return;
+ }
+
+ if (subexpr->type != Node::TYPE_CONSTANT) {
+ _set_error("Expected constant expression");
+ }
+
+ const ConstantNode *subexpr_const = static_cast<const ConstantNode *>(subexpr);
+
+ if (subexpr_const->value.get_type() != Variant::INT) {
+ _set_error("Expected an int value for enum");
+ }
+
+ last_assign = subexpr_const->value;
+
+ constant.expression = subexpr;
+
+ } else {
+ last_assign = last_assign + 1;
+ ConstantNode *cn = alloc_node<ConstantNode>();
+ cn->value = last_assign;
+ constant.expression = cn;
+ }
+
+ if (tokenizer->get_token() == GDTokenizer::TK_COMMA) {
+ tokenizer->advance();
+ }
+
+ if (enum_name != "") {
+ const ConstantNode *cn = static_cast<const ConstantNode *>(constant.expression);
+ enum_dict[constant.identifier] = cn->value;
+ }
+
+ p_class->constant_expressions.push_back(constant);
+ }
+ }
+
+ if (enum_name != "") {
+ ClassNode::Constant enum_constant;
+ enum_constant.identifier = enum_name;
+ ConstantNode *cn = alloc_node<ConstantNode>();
+ cn->value = enum_dict;
+ enum_constant.expression = cn;
+ p_class->constant_expressions.push_back(enum_constant);
+ }
+
+ if (!_end_statement()) {
+ _set_error("Expected end of statement (enum)");
+ return;
+ }
+
+ } break;
default: {
diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp
index 3d9d49303..65156f0a9 100644
--- a/modules/gdscript/gd_tokenizer.cpp
+++ b/modules/gdscript/gd_tokenizer.cpp
@@ -95,6 +95,7 @@ const char *GDTokenizer::token_names[TK_MAX] = {
"setget",
"const",
"var",
+ "enum",
"preload",
"assert",
"yield",
@@ -861,6 +862,7 @@ void GDTokenizerText::_advance() {
{ TK_PR_SIGNAL, "signal" },
{ TK_PR_BREAKPOINT, "breakpoint" },
{ TK_PR_CONST, "const" },
+ { TK_PR_ENUM, "enum" },
//controlflow
{ TK_CF_IF, "if" },
{ TK_CF_ELIF, "elif" },
diff --git a/modules/gdscript/gd_tokenizer.h b/modules/gdscript/gd_tokenizer.h
index 1fe0910c3..84d15a56e 100644
--- a/modules/gdscript/gd_tokenizer.h
+++ b/modules/gdscript/gd_tokenizer.h
@@ -101,6 +101,7 @@ public:
TK_PR_SETGET,
TK_PR_CONST,
TK_PR_VAR,
+ TK_PR_ENUM,
TK_PR_PRELOAD,
TK_PR_ASSERT,
TK_PR_YIELD,
diff --git a/platform/android/build.gradle.template b/platform/android/build.gradle.template
index 24aab8e01..ec5bbb663 100644
--- a/platform/android/build.gradle.template
+++ b/platform/android/build.gradle.template
@@ -12,6 +12,7 @@ apply plugin: 'com.android.application'
allprojects {
repositories {
+ jcenter()
mavenCentral()
$$GRADLE_REPOSITORY_URLS$$
}
diff --git a/platform/android/detect.py b/platform/android/detect.py
index 2522a55aa..31551a5bc 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -175,6 +175,8 @@ def configure(env):
if env['android_arch'] == 'x86':
can_vectorize = True
target_opts = ['-target', 'i686-none-linux-android']
+ # The NDK adds this if targeting API < 21, so we can drop it when Godot targets it at least
+ env.Append(CPPFLAGS=['-mstackrealign'])
elif env["android_arch"] == "armv6":
can_vectorize = False
target_opts = ['-target', 'armv6-none-linux-androideabi']
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 2b9574458..436c6ebf4 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -2176,6 +2176,9 @@ void OS_Windows::run() {
if (!main_loop)
return;
+ // Process all events before the main initialization so the cursor will get initialized properly
+ process_events(); // get rid of pending events
+
main_loop->init();
uint64_t last_ticks = get_ticks_usec();
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 5a829d62d..3975a6184 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -1282,8 +1282,12 @@ void OS_X11::process_xevents() {
if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED)
main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
- if (input)
+ if (input) {
+ // Update mouse position. It is triggered before mouse motion.
+ Point2i pos(event.xmotion.x, event.xmotion.y);
+ input->set_mouse_pos(pos);
input->set_mouse_in_window(true);
+ }
} break;
case FocusIn:
minimized = false;
@@ -1893,6 +1897,9 @@ void OS_X11::run() {
if (!main_loop)
return;
+ // Process all events before the main initialization so the cursor will get initialized properly
+ process_xevents(); // get rid of pending events
+
main_loop->init();
// uint64_t last_ticks=get_ticks_usec();
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index fff399f8f..1a53f684e 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -380,6 +380,10 @@ void Area2D::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_READY: {
+
+ is_ready = true;
+ } break;
case NOTIFICATION_EXIT_TREE: {
monitoring_stored = monitoring;
@@ -387,8 +391,8 @@ void Area2D::_notification(int p_what) {
_clear_monitoring();
} break;
case NOTIFICATION_ENTER_TREE: {
-
- set_enable_monitoring(monitoring_stored);
+ if (is_ready)
+ set_enable_monitoring(monitoring_stored);
} break;
}
}
@@ -646,7 +650,8 @@ Area2D::Area2D()
monitorable = false;
collision_mask = 1;
layer_mask = 1;
- monitoring_stored = true;
+ monitoring_stored = false;
+ is_ready = false;
set_enable_monitoring(true);
set_monitorable(true);
}
diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h
index 8e854d474..1860127cb 100644
--- a/scene/2d/area_2d.h
+++ b/scene/2d/area_2d.h
@@ -60,6 +60,7 @@ private:
bool monitoring_stored;
bool monitorable;
bool locked;
+ bool is_ready;
void _body_inout(int p_status, const RID &p_body, int p_instance, int p_body_shape, int p_area_shape);
diff --git a/scene/2d/sample_player_2d.cpp b/scene/2d/sample_player_2d.cpp
index 07f0e3fb3..5e958058a 100644
--- a/scene/2d/sample_player_2d.cpp
+++ b/scene/2d/sample_player_2d.cpp
@@ -130,8 +130,9 @@ SamplePlayer2D::VoiceID SamplePlayer2D::play(const String &p_sample, int p_voice
Ref<Sample> sample = library->get_sample(p_sample);
float vol_change = library->sample_get_volume_db(p_sample);
float pitch_change = library->sample_get_pitch_scale(p_sample);
+ int priority = library->sample_get_priority(p_sample);
- VoiceID vid = SpatialSound2DServer::get_singleton()->source_play_sample(get_source_rid(), sample->get_rid(), sample->get_mix_rate() * pitch_change, p_voice);
+ VoiceID vid = SpatialSound2DServer::get_singleton()->source_play_sample(get_source_rid(), sample->get_rid(), sample->get_mix_rate() * pitch_change, p_voice, priority);
if (vol_change)
SpatialSound2DServer::get_singleton()->source_voice_set_volume_scale_db(get_source_rid(), vid, vol_change);
diff --git a/scene/2d/screen_button.cpp b/scene/2d/screen_button.cpp
index 569303138..8335106d9 100644
--- a/scene/2d/screen_button.cpp
+++ b/scene/2d/screen_button.cpp
@@ -65,12 +65,14 @@ Ref<BitMap> TouchScreenButton::get_bitmask() const {
void TouchScreenButton::set_shape(const Ref<Shape2D> &p_shape) {
+ if (shape.is_valid())
+ shape->disconnect("changed", this, "update");
+
shape = p_shape;
- if (!is_inside_tree())
- return;
- if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint())
- return;
+ if (shape.is_valid())
+ shape->connect("changed", this, "update");
+
update();
}
@@ -82,11 +84,17 @@ Ref<Shape2D> TouchScreenButton::get_shape() const {
void TouchScreenButton::set_shape_centered(bool p_shape_centered) {
shape_centered = p_shape_centered;
+ update();
+}
- if (!is_inside_tree())
- return;
- if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint())
- return;
+bool TouchScreenButton::is_shape_visible() const {
+
+ return shape_visible;
+}
+
+void TouchScreenButton::set_shape_visible(bool p_shape_visible) {
+
+ shape_visible = p_shape_visible;
update();
}
@@ -118,6 +126,8 @@ void TouchScreenButton::_notification(int p_what) {
draw_texture(texture, Point2());
}
+ if (!shape_visible)
+ return;
if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint())
return;
if (shape.is_valid()) {
@@ -373,6 +383,9 @@ void TouchScreenButton::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_shape_centered", "bool"), &TouchScreenButton::set_shape_centered);
ObjectTypeDB::bind_method(_MD("is_shape_centered"), &TouchScreenButton::is_shape_centered);
+ ObjectTypeDB::bind_method(_MD("set_shape_visible", "bool"), &TouchScreenButton::set_shape_visible);
+ ObjectTypeDB::bind_method(_MD("is_shape_visible"), &TouchScreenButton::is_shape_visible);
+
ObjectTypeDB::bind_method(_MD("set_action", "action"), &TouchScreenButton::set_action);
ObjectTypeDB::bind_method(_MD("get_action"), &TouchScreenButton::get_action);
@@ -391,6 +404,7 @@ void TouchScreenButton::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "bitmask", PROPERTY_HINT_RESOURCE_TYPE, "BitMap"), _SCS("set_bitmask"), _SCS("get_bitmask"));
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), _SCS("set_shape"), _SCS("get_shape"));
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shape_centered"), _SCS("set_shape_centered"), _SCS("is_shape_centered"));
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shape_visible"), _SCS("set_shape_visible"), _SCS("is_shape_visible"));
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "passby_press"), _SCS("set_passby_press"), _SCS("is_passby_press_enabled"));
ADD_PROPERTY(PropertyInfo(Variant::STRING, "action"), _SCS("set_action"), _SCS("get_action"));
ADD_PROPERTY(PropertyInfo(Variant::INT, "visibility_mode", PROPERTY_HINT_ENUM, "Always,TouchScreen Only"), _SCS("set_visibility_mode"), _SCS("get_visibility_mode"));
@@ -406,6 +420,7 @@ TouchScreenButton::TouchScreenButton() {
passby_press = false;
visibility = VISIBILITY_ALWAYS;
shape_centered = true;
+ shape_visible = true;
unit_rect = Ref<RectangleShape2D>(memnew(RectangleShape2D));
unit_rect->set_extents(Vector2(0.5, 0.5));
}
diff --git a/scene/2d/screen_button.h b/scene/2d/screen_button.h
index bbd69a35b..84be43144 100644
--- a/scene/2d/screen_button.h
+++ b/scene/2d/screen_button.h
@@ -50,6 +50,7 @@ private:
Ref<BitMap> bitmask;
Ref<Shape2D> shape;
bool shape_centered;
+ bool shape_visible;
Ref<RectangleShape2D> unit_rect;
@@ -85,6 +86,9 @@ public:
void set_shape_centered(bool p_shape_centered);
bool is_shape_centered() const;
+ void set_shape_visible(bool p_shape_visible);
+ bool is_shape_visible() const;
+
void set_action(const String &p_action);
String get_action() const;
diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp
index f0dec5d2e..b4c63d629 100644
--- a/scene/3d/area.cpp
+++ b/scene/3d/area.cpp
@@ -227,6 +227,10 @@ void Area::_clear_monitoring() {
Object *obj = ObjectDB::get_instance(E->key());
Node *node = obj ? obj->cast_to<Node>() : NULL;
ERR_CONTINUE(!node);
+
+ node->disconnect(SceneStringNames::get_singleton()->enter_tree, this, SceneStringNames::get_singleton()->_body_enter_tree);
+ node->disconnect(SceneStringNames::get_singleton()->exit_tree, this, SceneStringNames::get_singleton()->_body_exit_tree);
+
if (!E->get().in_tree)
continue;
@@ -236,9 +240,6 @@ void Area::_clear_monitoring() {
}
emit_signal(SceneStringNames::get_singleton()->body_exit, obj);
-
- node->disconnect(SceneStringNames::get_singleton()->enter_tree, this, SceneStringNames::get_singleton()->_body_enter_tree);
- node->disconnect(SceneStringNames::get_singleton()->exit_tree, this, SceneStringNames::get_singleton()->_body_exit_tree);
}
}
@@ -253,6 +254,10 @@ void Area::_clear_monitoring() {
Object *obj = ObjectDB::get_instance(E->key());
Node *node = obj ? obj->cast_to<Node>() : NULL;
ERR_CONTINUE(!node);
+
+ node->disconnect(SceneStringNames::get_singleton()->enter_tree, this, SceneStringNames::get_singleton()->_area_enter_tree);
+ node->disconnect(SceneStringNames::get_singleton()->exit_tree, this, SceneStringNames::get_singleton()->_area_exit_tree);
+
if (!E->get().in_tree)
continue;
@@ -262,16 +267,27 @@ void Area::_clear_monitoring() {
}
emit_signal(SceneStringNames::get_singleton()->area_exit, obj);
-
- node->disconnect(SceneStringNames::get_singleton()->enter_tree, this, SceneStringNames::get_singleton()->_area_enter_tree);
- node->disconnect(SceneStringNames::get_singleton()->exit_tree, this, SceneStringNames::get_singleton()->_area_exit_tree);
}
}
}
void Area::_notification(int p_what) {
- if (p_what == NOTIFICATION_EXIT_TREE) {
- _clear_monitoring();
+ switch (p_what) {
+
+ case NOTIFICATION_READY: {
+
+ is_ready = true;
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+
+ monitoring_stored = monitoring;
+ set_enable_monitoring(false);
+ _clear_monitoring();
+ } break;
+ case NOTIFICATION_ENTER_TREE: {
+ if (is_ready)
+ set_enable_monitoring(monitoring_stored);
+ } break;
}
}
@@ -627,6 +643,8 @@ Area::Area()
monitoring = false;
collision_mask = 1;
layer_mask = 1;
+ monitoring_stored = false;
+ is_ready = false;
set_ray_pickable(false);
set_enable_monitoring(true);
set_monitorable(true);
diff --git a/scene/3d/area.h b/scene/3d/area.h
index 75c66c88b..718243fdb 100644
--- a/scene/3d/area.h
+++ b/scene/3d/area.h
@@ -57,8 +57,10 @@ private:
uint32_t layer_mask;
int priority;
bool monitoring;
+ bool monitoring_stored;
bool monitorable;
bool locked;
+ bool is_ready;
void _body_inout(int p_status, const RID &p_body, int p_instance, int p_body_shape, int p_area_shape);
diff --git a/scene/3d/spatial_sample_player.cpp b/scene/3d/spatial_sample_player.cpp
index c2860b4f7..25873bcfb 100644
--- a/scene/3d/spatial_sample_player.cpp
+++ b/scene/3d/spatial_sample_player.cpp
@@ -130,6 +130,7 @@ SpatialSamplePlayer::VoiceID SpatialSamplePlayer::play(const String &p_sample, i
Ref<Sample> sample = library->get_sample(p_sample);
float vol_change = library->sample_get_volume_db(p_sample);
float pitch_change = library->sample_get_pitch_scale(p_sample);
+ int priority = library->sample_get_priority(p_sample);
VoiceID vid = SpatialSoundServer::get_singleton()->source_play_sample(get_source_rid(), sample->get_rid(), sample->get_mix_rate() * pitch_change, p_voice);
if (vol_change)
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index 394e152b3..fd3abc543 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -609,6 +609,7 @@ void Tween::_tween_process(float p_delta) {
_apply_tween_value(data, result);
if (data.finish) {
+ _apply_tween_value(data, data.final_val);
emit_signal("tween_complete", object, data.key);
// not repeat mode, remove completed action
if (!repeat)
diff --git a/scene/audio/sample_player.cpp b/scene/audio/sample_player.cpp
index dfccc5c7c..416d560b7 100644
--- a/scene/audio/sample_player.cpp
+++ b/scene/audio/sample_player.cpp
@@ -187,6 +187,7 @@ void SamplePlayer::Voice::clear() {
reverb_room = REVERB_HALL;
reverb_send = 0;
active = false;
+ priority = 0;
}
SamplePlayer::Voice::~Voice() {
@@ -214,13 +215,28 @@ SamplePlayer::VoiceID SamplePlayer::play(const String &p_name, bool unique) {
Ref<Sample> sample = library->get_sample(p_name);
float vol_change = library->sample_get_volume_db(p_name);
float pitch_change = library->sample_get_pitch_scale(p_name);
+ int priority = library->sample_get_priority(p_name);
last_check++;
- last_id = (last_id + 1) % voices.size();
+
+ const int num_voices = voices.size();
+ bool found = false;
+ for (int i = 0; i < num_voices; i++) {
+ const int candidate = (last_id + 1 + i) % num_voices;
+ if (voices[candidate].priority <= priority) {
+ found = true;
+ last_id = candidate;
+ break;
+ }
+ }
+
+ if (!found)
+ return INVALID_VOICE_ID;
Voice &v = voices[last_id];
v.clear();
+ v.priority = priority;
v.mix_rate = sample->get_mix_rate() * (_default.pitch_scale * pitch_change);
v.sample_mix_rate = sample->get_mix_rate();
v.check = last_check;
diff --git a/scene/audio/sample_player.h b/scene/audio/sample_player.h
index 0f026a085..392679f05 100644
--- a/scene/audio/sample_player.h
+++ b/scene/audio/sample_player.h
@@ -74,6 +74,7 @@ private:
uint32_t check;
bool active;
+ int priority;
int sample_mix_rate;
int mix_rate;
float volume;
diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp
index 79a6b79f9..e4a863b90 100644
--- a/scene/main/scene_main_loop.cpp
+++ b/scene/main/scene_main_loop.cpp
@@ -327,6 +327,10 @@ void SceneTree::input_text(const String &p_text) {
root_lock--;
}
+bool SceneTree::is_input_handled() {
+ return input_handled;
+}
+
void SceneTree::input_event(const InputEvent &p_event) {
if (is_editor_hint() && (p_event.type == InputEvent::JOYSTICK_MOTION || p_event.type == InputEvent::JOYSTICK_BUTTON))
@@ -1556,6 +1560,7 @@ void SceneTree::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_pause", "enable"), &SceneTree::set_pause);
ObjectTypeDB::bind_method(_MD("is_paused"), &SceneTree::is_paused);
ObjectTypeDB::bind_method(_MD("set_input_as_handled"), &SceneTree::set_input_as_handled);
+ ObjectTypeDB::bind_method(_MD("is_input_handled"), &SceneTree::is_input_handled);
ObjectTypeDB::bind_method(_MD("get_node_count"), &SceneTree::get_node_count);
ObjectTypeDB::bind_method(_MD("get_frame"), &SceneTree::get_frame);
diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h
index 8b20c8dbf..9a658f197 100644
--- a/scene/main/scene_main_loop.h
+++ b/scene/main/scene_main_loop.h
@@ -262,6 +262,7 @@ public:
void quit();
void set_input_as_handled();
+ bool is_input_handled();
_FORCE_INLINE_ float get_fixed_process_time() const { return fixed_process_time; }
_FORCE_INLINE_ float get_idle_process_time() const { return idle_process_time; }
diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp
index 1010e76ba..3fb0d1e25 100644
--- a/scene/main/timer.cpp
+++ b/scene/main/timer.cpp
@@ -50,8 +50,7 @@ void Timer::_notification(int p_what) {
if (time_left < 0) {
if (!one_shot)
- //time_left=wait_time+time_left;
- time_left = wait_time;
+ time_left += wait_time;
else
stop();
@@ -66,8 +65,7 @@ void Timer::_notification(int p_what) {
if (time_left < 0) {
if (!one_shot)
- //time_left = wait_time + time_left;
- time_left = wait_time;
+ time_left += wait_time;
else
stop();
emit_signal("timeout");
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index d37f95641..2dd12a6bb 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -1347,7 +1347,7 @@ void Viewport::_vp_input(const InputEvent &p_ev) {
return;
#ifdef TOOLS_ENABLED
- if (get_tree()->is_editor_hint() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
+ if (get_tree()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
return;
}
#endif
@@ -1371,7 +1371,7 @@ void Viewport::_vp_unhandled_input(const InputEvent &p_ev) {
if (disable_input)
return;
#ifdef TOOLS_ENABLED
- if (get_tree()->is_editor_hint() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
+ if (get_tree()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
return;
}
#endif
diff --git a/scene/resources/sample_library.cpp b/scene/resources/sample_library.cpp
index e6ccdceb3..752b988d8 100644
--- a/scene/resources/sample_library.cpp
+++ b/scene/resources/sample_library.cpp
@@ -49,6 +49,7 @@ bool SampleLibrary::_set(const StringName &p_name, const Variant &p_value) {
sd.sample = d["sample"];
sd.pitch_scale = d["pitch"];
sd.db = d["db"];
+ sd.priority = d.has("priority") ? d["priority"] : Variant(0); // For libraries before priority was introduced
}
sample_map[name] = sd;
@@ -70,6 +71,7 @@ bool SampleLibrary::_get(const StringName &p_name, Variant &r_ret) const {
d["sample"] = sample_map[name].sample;
d["pitch"] = sample_map[name].pitch_scale;
d["db"] = sample_map[name].db;
+ d["priority"] = sample_map[name].priority;
r_ret = d;
} else {
return false;
@@ -170,6 +172,19 @@ float SampleLibrary::sample_get_pitch_scale(const StringName &p_name) const {
return sample_map[p_name].pitch_scale;
}
+void SampleLibrary::sample_set_priority(const StringName &p_name, int p_priority) {
+
+ ERR_FAIL_COND(!sample_map.has(p_name));
+ sample_map[p_name].priority = p_priority;
+}
+
+int SampleLibrary::sample_get_priority(const StringName &p_name) const {
+
+ ERR_FAIL_COND_V(!sample_map.has(p_name), 0);
+
+ return sample_map[p_name].priority;
+}
+
Array SampleLibrary::_get_sample_list() const {
List<StringName> snames;
@@ -199,6 +214,9 @@ void SampleLibrary::_bind_methods() {
ObjectTypeDB::bind_method(_MD("sample_set_pitch_scale", "name", "pitch"), &SampleLibrary::sample_set_pitch_scale);
ObjectTypeDB::bind_method(_MD("sample_get_pitch_scale", "name"), &SampleLibrary::sample_get_pitch_scale);
+
+ ObjectTypeDB::bind_method(_MD("sample_set_priority", "name", "priority"), &SampleLibrary::sample_set_priority);
+ ObjectTypeDB::bind_method(_MD("sample_get_priority", "name"), &SampleLibrary::sample_get_priority);
}
SampleLibrary::SampleLibrary() {
diff --git a/scene/resources/sample_library.h b/scene/resources/sample_library.h
index 1928e55bb..d8008106b 100644
--- a/scene/resources/sample_library.h
+++ b/scene/resources/sample_library.h
@@ -42,10 +42,12 @@ class SampleLibrary : public Resource {
Ref<Sample> sample;
float db;
float pitch_scale;
+ int priority;
SampleData() {
db = 0;
pitch_scale = 1;
+ priority = 0;
}
};
@@ -67,6 +69,8 @@ public:
float sample_get_volume_db(const StringName &p_name) const;
void sample_set_pitch_scale(const StringName &p_name, float p_pitch);
float sample_get_pitch_scale(const StringName &p_name) const;
+ void sample_set_priority(const StringName &p_name, int p_priority);
+ int sample_get_priority(const StringName &p_name) const;
Ref<Sample> get_sample(const StringName &p_name) const;
void get_sample_list(List<StringName> *p_samples) const;
void remove_sample(const StringName &p_name);
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index 458f5c220..18873808e 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -32,6 +32,9 @@ SceneStringNames *SceneStringNames::singleton = NULL;
SceneStringNames::SceneStringNames() {
+ _estimate_cost = StaticCString::create("_estimate_cost");
+ _compute_cost = StaticCString::create("_compute_cost");
+
resized = StaticCString::create("resized");
dot = StaticCString::create(".");
doubledot = StaticCString::create("..");
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index 6d0382ba7..e18128fe4 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -49,6 +49,9 @@ class SceneStringNames {
public:
_FORCE_INLINE_ static SceneStringNames *get_singleton() { return singleton; }
+ StringName _estimate_cost;
+ StringName _compute_cost;
+
StringName resized;
StringName dot;
StringName doubledot;
diff --git a/servers/spatial_sound/spatial_sound_server_sw.cpp b/servers/spatial_sound/spatial_sound_server_sw.cpp
index 6a10b175e..410159d23 100644
--- a/servers/spatial_sound/spatial_sound_server_sw.cpp
+++ b/servers/spatial_sound/spatial_sound_server_sw.cpp
@@ -97,6 +97,7 @@ SpatialSoundServerSW::Source::Voice::Voice() {
active = false;
restart = false;
+ priority = 0;
pitch_scale = 1.0;
volume_scale = 0.0;
voice_rid = AudioServer::get_singleton()->voice_create();
@@ -390,7 +391,7 @@ void SpatialSoundServerSW::source_set_audio_stream(RID p_source, AudioServer::Au
} //null to unset
-SpatialSoundServer::SourceVoiceID SpatialSoundServerSW::source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice) {
+SpatialSoundServer::SourceVoiceID SpatialSoundServerSW::source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice, int p_priority) {
Source *source = source_owner.get(p_source);
ERR_FAIL_COND_V(!source, SOURCE_INVALID_VOICE);
@@ -398,16 +399,35 @@ SpatialSoundServer::SourceVoiceID SpatialSoundServerSW::source_play_sample(RID p
int to_play = 0;
if (p_voice == SOURCE_NEXT_VOICE) {
- to_play = source->last_voice + 1;
- if (to_play >= source->voices.size())
- to_play = 0;
-
+ const int num_voices = source->voices.size();
+ bool free_found = false;
+ int lowest_priority_voice = 0;
+ int lowest_priority = 0x7FFFFFFF;
+ for (int i = 0; i < num_voices; i++) {
+ const int candidate = (source->last_voice + 1 + i) % num_voices;
+ const Source::Voice &v = source->voices[candidate];
+ if (!v.active && !v.restart) {
+ free_found = true;
+ to_play = candidate;
+ break;
+ }
+ if (v.priority < lowest_priority) {
+ lowest_priority = v.priority;
+ lowest_priority_voice = candidate;
+ }
+ }
+ if (!free_found)
+ to_play = (source->last_voice + 1) % num_voices;
} else
to_play = p_voice;
ERR_FAIL_INDEX_V(to_play, source->voices.size(), SOURCE_INVALID_VOICE);
+ if ((source->voices[to_play].active || source->voices[to_play].restart) && source->voices[to_play].priority > p_priority)
+ return SOURCE_INVALID_VOICE;
+
source->voices[to_play].restart = true;
+ source->voices[to_play].priority = p_priority;
source->voices[to_play].sample_rid = p_sample;
source->voices[to_play].sample_mix_rate = p_mix_rate;
source->voices[to_play].pitch_scale = 1;
diff --git a/servers/spatial_sound/spatial_sound_server_sw.h b/servers/spatial_sound/spatial_sound_server_sw.h
index e05b78a94..54f276ede 100644
--- a/servers/spatial_sound/spatial_sound_server_sw.h
+++ b/servers/spatial_sound/spatial_sound_server_sw.h
@@ -101,6 +101,7 @@ class SpatialSoundServerSW : public SpatialSoundServer {
RID sample_rid;
bool active;
bool restart;
+ int priority;
float pitch_scale;
float volume_scale;
int sample_mix_rate;
@@ -226,7 +227,7 @@ public:
virtual float source_get_param(RID p_source, SourceParam p_param) const;
virtual void source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream); //null to unset
- virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice = SOURCE_NEXT_VOICE);
+ virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice = SOURCE_NEXT_VOICE, int p_priority = 0);
/* VOICES */
virtual void source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale);
virtual void source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_volume);
diff --git a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp
index 2c6614da8..6f0ae8910 100644
--- a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp
+++ b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp
@@ -94,6 +94,7 @@ SpatialSound2DServerSW::Source::Voice::Voice() {
active = false;
restart = false;
+ priority = 0;
pitch_scale = 1.0;
volume_scale = 0.0;
voice_rid = AudioServer::get_singleton()->voice_create();
@@ -387,7 +388,7 @@ void SpatialSound2DServerSW::source_set_audio_stream(RID p_source, AudioServer::
} //null to unset
-SpatialSound2DServer::SourceVoiceID SpatialSound2DServerSW::source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice) {
+SpatialSound2DServer::SourceVoiceID SpatialSound2DServerSW::source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice, int p_priority) {
Source *source = source_owner.get(p_source);
ERR_FAIL_COND_V(!source, SOURCE_INVALID_VOICE);
@@ -395,16 +396,35 @@ SpatialSound2DServer::SourceVoiceID SpatialSound2DServerSW::source_play_sample(R
int to_play = 0;
if (p_voice == SOURCE_NEXT_VOICE) {
- to_play = source->last_voice + 1;
- if (to_play >= source->voices.size())
- to_play = 0;
-
+ const int num_voices = source->voices.size();
+ bool free_found = false;
+ int lowest_priority_voice = 0;
+ int lowest_priority = 0x7FFFFFFF;
+ for (int i = 0; i < num_voices; i++) {
+ const int candidate = (source->last_voice + 1 + i) % num_voices;
+ const Source::Voice &v = source->voices[candidate];
+ if (!v.active && !v.restart) {
+ free_found = true;
+ to_play = candidate;
+ break;
+ }
+ if (v.priority < lowest_priority) {
+ lowest_priority = v.priority;
+ lowest_priority_voice = candidate;
+ }
+ }
+ if (!free_found)
+ to_play = (source->last_voice + 1) % num_voices;
} else
to_play = p_voice;
ERR_FAIL_INDEX_V(to_play, source->voices.size(), SOURCE_INVALID_VOICE);
+ if ((source->voices[to_play].active || source->voices[to_play].restart) && source->voices[to_play].priority > p_priority)
+ return SOURCE_INVALID_VOICE;
+
source->voices[to_play].restart = true;
+ source->voices[to_play].priority = p_priority;
source->voices[to_play].sample_rid = p_sample;
source->voices[to_play].sample_mix_rate = p_mix_rate;
source->voices[to_play].pitch_scale = 1;
diff --git a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h
index acc70e69c..de4cfee68 100644
--- a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h
+++ b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h
@@ -100,6 +100,7 @@ class SpatialSound2DServerSW : public SpatialSound2DServer {
RID sample_rid;
bool active;
bool restart;
+ int priority;
float pitch_scale;
float volume_scale;
int sample_mix_rate;
@@ -225,7 +226,7 @@ public:
virtual float source_get_param(RID p_source, SourceParam p_param) const;
virtual void source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream); //null to unset
- virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice = SOURCE_NEXT_VOICE);
+ virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice = SOURCE_NEXT_VOICE, int p_priority = 0);
/* VOICES */
virtual void source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale);
virtual void source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_volume);
diff --git a/servers/spatial_sound_2d_server.h b/servers/spatial_sound_2d_server.h
index 7c577e8be..08833287e 100644
--- a/servers/spatial_sound_2d_server.h
+++ b/servers/spatial_sound_2d_server.h
@@ -117,7 +117,7 @@ public:
virtual float source_get_param(RID p_source, SourceParam p_param) const = 0;
virtual void source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream) = 0; //null to unset
- virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice = SOURCE_NEXT_VOICE) = 0;
+ virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice = SOURCE_NEXT_VOICE, int p_priority = 0) = 0;
//voices
virtual void source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale) = 0;
virtual void source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_volume_db) = 0;
diff --git a/servers/spatial_sound_server.h b/servers/spatial_sound_server.h
index 72d3ae0af..be37f9b50 100644
--- a/servers/spatial_sound_server.h
+++ b/servers/spatial_sound_server.h
@@ -121,7 +121,7 @@ public:
virtual float source_get_param(RID p_source, SourceParam p_param) const = 0;
virtual void source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream) = 0; //null to unset
- virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice = SOURCE_NEXT_VOICE) = 0;
+ virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice = SOURCE_NEXT_VOICE, int p_priority = 0) = 0;
//voices
virtual void source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale) = 0;
virtual void source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_volume_db) = 0;