summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/bind/core_bind.cpp5
-rw-r--r--core/bind/core_bind.h2
-rw-r--r--core/global_constants.cpp10
-rw-r--r--core/io/translation_loader_po.cpp40
-rw-r--r--core/math/aabb.cpp4
-rw-r--r--core/math/bsp_tree.cpp10
-rw-r--r--core/os/input_event.cpp119
-rw-r--r--core/os/input_event.h56
-rw-r--r--core/os/midi_driver.cpp107
-rw-r--r--core/os/midi_driver.h59
-rw-r--r--core/os/os.cpp10
-rw-r--r--core/os/os.h2
-rw-r--r--core/safe_refcount.cpp48
-rw-r--r--core/safe_refcount.h50
-rw-r--r--core/translation.cpp8
-rw-r--r--core/ustring.cpp21
-rw-r--r--core/ustring.h1
17 files changed, 462 insertions, 90 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 7a14e85f20..af1d49ae8c 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -221,6 +221,10 @@ String _OS::get_audio_driver_name(int p_driver) const {
return OS::get_singleton()->get_audio_driver_name(p_driver);
}
+PoolStringArray _OS::get_connected_midi_inputs() {
+ return OS::get_singleton()->get_connected_midi_inputs();
+}
+
void _OS::set_video_mode(const Size2 &p_size, bool p_fullscreen, bool p_resizeable, int p_screen) {
OS::VideoMode vm;
@@ -1058,6 +1062,7 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_video_driver_name", "driver"), &_OS::get_video_driver_name);
ClassDB::bind_method(D_METHOD("get_audio_driver_count"), &_OS::get_audio_driver_count);
ClassDB::bind_method(D_METHOD("get_audio_driver_name", "driver"), &_OS::get_audio_driver_name);
+ ClassDB::bind_method(D_METHOD("get_connected_midi_inputs"), &_OS::get_connected_midi_inputs);
ClassDB::bind_method(D_METHOD("get_screen_count"), &_OS::get_screen_count);
ClassDB::bind_method(D_METHOD("get_current_screen"), &_OS::get_current_screen);
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 48b7b74005..1729c23779 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -152,6 +152,8 @@ public:
virtual int get_audio_driver_count() const;
virtual String get_audio_driver_name(int p_driver) const;
+ virtual PoolStringArray get_connected_midi_inputs();
+
virtual int get_screen_count() const;
virtual int get_current_screen() const;
virtual void set_current_screen(int p_screen);
diff --git a/core/global_constants.cpp b/core/global_constants.cpp
index 5b4dd05dbf..187813f9d0 100644
--- a/core/global_constants.cpp
+++ b/core/global_constants.cpp
@@ -89,6 +89,7 @@ VARIANT_ENUM_CAST(KeyList);
VARIANT_ENUM_CAST(KeyModifierMask);
VARIANT_ENUM_CAST(ButtonList);
VARIANT_ENUM_CAST(JoystickList);
+VARIANT_ENUM_CAST(MidiMessageList);
void register_global_constants() {
@@ -458,6 +459,15 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_L2);
BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_R2);
+ // midi
+ BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_OFF);
+ BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_ON);
+ BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_AFTERTOUCH);
+ BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_CONTROL_CHANGE);
+ BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_PROGRAM_CHANGE);
+ BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_CHANNEL_PRESSURE);
+ BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_PITCH_BEND);
+
// error list
BIND_GLOBAL_ENUM_CONSTANT(OK);
diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp
index 16d5e3c282..85c1fc5ddf 100644
--- a/core/io/translation_loader_po.cpp
+++ b/core/io/translation_loader_po.cpp
@@ -54,32 +54,25 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S
int line = 1;
bool skip_this = false;
bool skip_next = false;
+ bool is_eof = false;
- while (true) {
+ while (!is_eof) {
- String l = f->get_line();
+ String l = f->get_line().strip_edges();
+ is_eof = f->eof_reached();
- if (f->eof_reached()) {
+ // If we reached last line and it's not a content line, break, otherwise let processing that last loop
+ if (is_eof && l.empty()) {
- if (status == STATUS_READING_STRING) {
-
- if (msg_id != "") {
- if (!skip_this)
- translation->add_message(msg_id, msg_str);
- } else if (config == "")
- config = msg_str;
- break;
-
- } else if (status == STATUS_NONE)
+ if (status == STATUS_READING_ID) {
+ memdelete(f);
+ ERR_EXPLAIN(p_path + ":" + itos(line) + " Unexpected EOF while reading 'msgid' at file: ");
+ ERR_FAIL_V(RES());
+ } else {
break;
-
- memdelete(f);
- ERR_EXPLAIN(p_path + ":" + itos(line) + " Unexpected EOF while reading 'msgid' at file: ");
- ERR_FAIL_V(RES());
+ }
}
- l = l.strip_edges();
-
if (l.begins_with("msgid")) {
if (status == STATUS_READING_ID) {
@@ -160,6 +153,15 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S
f->close();
memdelete(f);
+ if (status == STATUS_READING_STRING) {
+
+ if (msg_id != "") {
+ if (!skip_this)
+ translation->add_message(msg_id, msg_str);
+ } else if (config == "")
+ config = msg_str;
+ }
+
if (config == "") {
ERR_EXPLAIN("No config found in file: " + p_path);
ERR_FAIL_V(RES());
diff --git a/core/math/aabb.cpp b/core/math/aabb.cpp
index cff19f990c..e2e71dda92 100644
--- a/core/math/aabb.cpp
+++ b/core/math/aabb.cpp
@@ -245,7 +245,6 @@ Vector3 AABB::get_longest_axis() const {
if (size.z > max_size) {
axis = Vector3(0, 0, 1);
- max_size = size.z;
}
return axis;
@@ -262,7 +261,6 @@ int AABB::get_longest_axis_index() const {
if (size.z > max_size) {
axis = 2;
- max_size = size.z;
}
return axis;
@@ -280,7 +278,6 @@ Vector3 AABB::get_shortest_axis() const {
if (size.z < max_size) {
axis = Vector3(0, 0, 1);
- max_size = size.z;
}
return axis;
@@ -297,7 +294,6 @@ int AABB::get_shortest_axis_index() const {
if (size.z < max_size) {
axis = 2;
- max_size = size.z;
}
return axis;
diff --git a/core/math/bsp_tree.cpp b/core/math/bsp_tree.cpp
index b1424e1d78..2e184f7a88 100644
--- a/core/math/bsp_tree.cpp
+++ b/core/math/bsp_tree.cpp
@@ -244,10 +244,8 @@ bool BSP_Tree::point_is_inside(const Vector3 &p_point) const {
const Node *nodesptr = &nodes[0];
const Plane *planesptr = &planes[0];
- int plane_count = planes.size();
int idx = node_count - 1;
- int steps = 0;
while (true) {
@@ -259,21 +257,19 @@ bool BSP_Tree::point_is_inside(const Vector3 &p_point) const {
return true;
}
- uint16_t plane = nodesptr[idx].plane;
#ifdef DEBUG_ENABLED
-
+ int plane_count = planes.size();
+ uint16_t plane = nodesptr[idx].plane;
ERR_FAIL_INDEX_V(plane, plane_count, false);
#endif
+
bool over = planesptr[nodesptr[idx].plane].is_point_over(p_point);
idx = over ? nodes[idx].over : nodes[idx].under;
#ifdef DEBUG_ENABLED
-
ERR_FAIL_COND_V(idx < MAX_NODES && idx >= node_count, false);
#endif
-
- steps++;
}
return false;
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp
index ca6446d015..e94ccb4f48 100644
--- a/core/os/input_event.cpp
+++ b/core/os/input_event.cpp
@@ -1080,3 +1080,122 @@ InputEventPanGesture::InputEventPanGesture() {
delta = Vector2(0, 0);
}
+/////////////////////////////
+
+void InputEventMIDI::set_channel(const int p_channel) {
+
+ channel = p_channel;
+}
+
+int InputEventMIDI::get_channel() const {
+ return channel;
+}
+
+void InputEventMIDI::set_message(const int p_message) {
+
+ message = p_message;
+}
+
+int InputEventMIDI::get_message() const {
+ return message;
+}
+
+void InputEventMIDI::set_pitch(const int p_pitch) {
+
+ pitch = p_pitch;
+}
+
+int InputEventMIDI::get_pitch() const {
+ return pitch;
+}
+
+void InputEventMIDI::set_velocity(const int p_velocity) {
+
+ velocity = p_velocity;
+}
+
+int InputEventMIDI::get_velocity() const {
+ return velocity;
+}
+
+void InputEventMIDI::set_instrument(const int p_instrument) {
+
+ instrument = p_instrument;
+}
+
+int InputEventMIDI::get_instrument() const {
+ return instrument;
+}
+
+void InputEventMIDI::set_pressure(const int p_pressure) {
+
+ pressure = p_pressure;
+}
+
+int InputEventMIDI::get_pressure() const {
+ return pressure;
+}
+
+void InputEventMIDI::set_controller_number(const int p_controller_number) {
+
+ controller_number = p_controller_number;
+}
+
+int InputEventMIDI::get_controller_number() const {
+ return controller_number;
+}
+
+void InputEventMIDI::set_controller_value(const int p_controller_value) {
+
+ controller_value = p_controller_value;
+}
+
+int InputEventMIDI::get_controller_value() const {
+ return controller_value;
+}
+
+String InputEventMIDI::as_text() const {
+
+ return "InputEventMIDI : channel=(" + itos(get_channel()) + "), message=(" + itos(get_message()) + ")";
+}
+
+void InputEventMIDI::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_channel", "channel"), &InputEventMIDI::set_channel);
+ ClassDB::bind_method(D_METHOD("get_channel"), &InputEventMIDI::get_channel);
+ ClassDB::bind_method(D_METHOD("set_message", "message"), &InputEventMIDI::set_message);
+ ClassDB::bind_method(D_METHOD("get_message"), &InputEventMIDI::get_message);
+ ClassDB::bind_method(D_METHOD("set_pitch", "pitch"), &InputEventMIDI::set_pitch);
+ ClassDB::bind_method(D_METHOD("get_pitch"), &InputEventMIDI::get_pitch);
+ ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &InputEventMIDI::set_velocity);
+ ClassDB::bind_method(D_METHOD("get_velocity"), &InputEventMIDI::get_velocity);
+ ClassDB::bind_method(D_METHOD("set_instrument", "instrument"), &InputEventMIDI::set_instrument);
+ ClassDB::bind_method(D_METHOD("get_instrument"), &InputEventMIDI::get_instrument);
+ ClassDB::bind_method(D_METHOD("set_pressure", "pressure"), &InputEventMIDI::set_pressure);
+ ClassDB::bind_method(D_METHOD("get_pressure"), &InputEventMIDI::get_pressure);
+ ClassDB::bind_method(D_METHOD("set_controller_number", "controller_number"), &InputEventMIDI::set_controller_number);
+ ClassDB::bind_method(D_METHOD("get_controller_number"), &InputEventMIDI::get_controller_number);
+ ClassDB::bind_method(D_METHOD("set_controller_value", "controller_value"), &InputEventMIDI::set_controller_value);
+ ClassDB::bind_method(D_METHOD("get_controller_value"), &InputEventMIDI::get_controller_value);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "channel"), "set_channel", "get_channel");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "message"), "set_message", "get_message");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "pitch"), "set_pitch", "get_pitch");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "velocity"), "set_velocity", "get_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "instrument"), "set_instrument", "get_instrument");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "pressure"), "set_pressure", "get_pressure");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_number"), "set_controller_number", "get_controller_number");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_value"), "set_controller_value", "get_controller_value");
+}
+
+InputEventMIDI::InputEventMIDI() {
+
+ channel = 0;
+ message = 0;
+ pitch = 0;
+ velocity = 0;
+ instrument = 0;
+ pressure = 0;
+ controller_number = 0;
+ controller_value = 0;
+}
diff --git a/core/os/input_event.h b/core/os/input_event.h
index bd1a85ce29..04126fee77 100644
--- a/core/os/input_event.h
+++ b/core/os/input_event.h
@@ -140,6 +140,16 @@ enum JoystickList {
JOY_ANALOG_R2 = JOY_AXIS_7,
};
+enum MidiMessageList {
+ MIDI_MESSAGE_NOTE_OFF = 0x8,
+ MIDI_MESSAGE_NOTE_ON = 0x9,
+ MIDI_MESSAGE_AFTERTOUCH = 0xA,
+ MIDI_MESSAGE_CONTROL_CHANGE = 0xB,
+ MIDI_MESSAGE_PROGRAM_CHANGE = 0xC,
+ MIDI_MESSAGE_CHANNEL_PRESSURE = 0xD,
+ MIDI_MESSAGE_PITCH_BEND = 0xE,
+};
+
/**
* Input Modifier Status
* for keyboard/mouse events.
@@ -525,4 +535,50 @@ public:
InputEventPanGesture();
};
+
+class InputEventMIDI : public InputEvent {
+ GDCLASS(InputEventMIDI, InputEvent)
+
+ int channel;
+ int message;
+ int pitch;
+ int velocity;
+ int instrument;
+ int pressure;
+ int controller_number;
+ int controller_value;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_channel(const int p_channel);
+ int get_channel() const;
+
+ void set_message(const int p_message);
+ int get_message() const;
+
+ void set_pitch(const int p_pitch);
+ int get_pitch() const;
+
+ void set_velocity(const int p_velocity);
+ int get_velocity() const;
+
+ void set_instrument(const int p_instrument);
+ int get_instrument() const;
+
+ void set_pressure(const int p_pressure);
+ int get_pressure() const;
+
+ void set_controller_number(const int p_controller_number);
+ int get_controller_number() const;
+
+ void set_controller_value(const int p_controller_value);
+ int get_controller_value() const;
+
+ virtual String as_text() const;
+
+ InputEventMIDI();
+};
+
#endif
diff --git a/core/os/midi_driver.cpp b/core/os/midi_driver.cpp
new file mode 100644
index 0000000000..7b4f84473c
--- /dev/null
+++ b/core/os/midi_driver.cpp
@@ -0,0 +1,107 @@
+/*************************************************************************/
+/* midi_driver.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "midi_driver.h"
+
+#include "main/input_default.h"
+#include "os/os.h"
+
+MIDIDriver *MIDIDriver::singleton = NULL;
+MIDIDriver *MIDIDriver::get_singleton() {
+
+ return singleton;
+}
+
+void MIDIDriver::set_singleton() {
+
+ singleton = this;
+}
+
+void MIDIDriver::receive_input_packet(uint64_t timestamp, uint8_t *data, uint32_t length) {
+
+ Ref<InputEventMIDI> event;
+ event.instance();
+
+ if (length >= 1) {
+ event->set_channel(data[0] & 0xF);
+ event->set_message(data[0] >> 4);
+ }
+
+ switch (event->get_message()) {
+ case MIDI_MESSAGE_AFTERTOUCH:
+ if (length >= 3) {
+ event->set_pitch(data[1]);
+ event->set_pressure(data[2]);
+ }
+ break;
+
+ case MIDI_MESSAGE_CONTROL_CHANGE:
+ if (length >= 3) {
+ event->set_controller_number(data[1]);
+ event->set_controller_value(data[2]);
+ }
+ break;
+
+ case MIDI_MESSAGE_NOTE_ON:
+ case MIDI_MESSAGE_NOTE_OFF:
+ case MIDI_MESSAGE_PITCH_BEND:
+ if (length >= 3) {
+ event->set_pitch(data[1]);
+ event->set_velocity(data[2]);
+ }
+ break;
+
+ case MIDI_MESSAGE_PROGRAM_CHANGE:
+ if (length >= 2) {
+ event->set_instrument(data[1]);
+ }
+ break;
+
+ case MIDI_MESSAGE_CHANNEL_PRESSURE:
+ if (length >= 2) {
+ event->set_pressure(data[1]);
+ }
+ break;
+ }
+
+ InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton());
+ id->parse_input_event(event);
+}
+
+PoolStringArray MIDIDriver::get_connected_inputs() {
+
+ PoolStringArray list;
+ return list;
+}
+
+MIDIDriver::MIDIDriver() {
+
+ set_singleton();
+}
diff --git a/core/os/midi_driver.h b/core/os/midi_driver.h
new file mode 100644
index 0000000000..1a3a67a411
--- /dev/null
+++ b/core/os/midi_driver.h
@@ -0,0 +1,59 @@
+/*************************************************************************/
+/* midi_driver.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MIDI_DRIVER_H
+#define MIDI_DRIVER_H
+
+#include "core/variant.h"
+#include "typedefs.h"
+/**
+ * Multi-Platform abstraction for accessing to MIDI.
+ */
+
+class MIDIDriver {
+
+ static MIDIDriver *singleton;
+
+public:
+ static MIDIDriver *get_singleton();
+ void set_singleton();
+
+ virtual Error open() = 0;
+ virtual void close() = 0;
+
+ virtual PoolStringArray get_connected_inputs();
+
+ static void receive_input_packet(uint64_t timestamp, uint8_t *data, uint32_t length);
+
+ MIDIDriver();
+ virtual ~MIDIDriver() {}
+};
+
+#endif
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 89866e4044..8dcf0990fc 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -33,6 +33,7 @@
#include "dir_access.h"
#include "input.h"
#include "os/file_access.h"
+#include "os/midi_driver.h"
#include "project_settings.h"
#include "servers/audio_server.h"
#include "version_generated.gen.h"
@@ -672,6 +673,15 @@ List<String> OS::get_restart_on_exit_arguments() const {
return restart_commandline;
}
+PoolStringArray OS::get_connected_midi_inputs() {
+
+ if (MIDIDriver::get_singleton())
+ return MIDIDriver::get_singleton()->get_connected_inputs();
+
+ PoolStringArray list;
+ return list;
+}
+
OS::OS() {
void *volatile stack_bottom;
diff --git a/core/os/os.h b/core/os/os.h
index 4e0cb003fb..dd783408e8 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -189,6 +189,8 @@ public:
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
+ virtual PoolStringArray get_connected_midi_inputs();
+
virtual int get_screen_count() const { return 1; }
virtual int get_current_screen() const { return 0; }
virtual void set_current_screen(int p_screen) {}
diff --git a/core/safe_refcount.cpp b/core/safe_refcount.cpp
index 3b203f6977..692ff722f3 100644
--- a/core/safe_refcount.cpp
+++ b/core/safe_refcount.cpp
@@ -57,113 +57,113 @@
return m_val; \
}
-_ALWAYS_INLINE_ uint32_t _atomic_conditional_increment_impl(register uint32_t *pw){
+_ALWAYS_INLINE_ uint32_t _atomic_conditional_increment_impl(volatile uint32_t *pw){
ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONG, InterlockedCompareExchange, uint32_t)
}
-_ALWAYS_INLINE_ uint32_t _atomic_decrement_impl(register uint32_t *pw) {
+_ALWAYS_INLINE_ uint32_t _atomic_decrement_impl(volatile uint32_t *pw) {
return InterlockedDecrement((LONG volatile *)pw);
}
-_ALWAYS_INLINE_ uint32_t _atomic_increment_impl(register uint32_t *pw) {
+_ALWAYS_INLINE_ uint32_t _atomic_increment_impl(volatile uint32_t *pw) {
return InterlockedIncrement((LONG volatile *)pw);
}
-_ALWAYS_INLINE_ uint32_t _atomic_sub_impl(register uint32_t *pw, register uint32_t val) {
+_ALWAYS_INLINE_ uint32_t _atomic_sub_impl(volatile uint32_t *pw, volatile uint32_t val) {
return InterlockedExchangeAdd((LONG volatile *)pw, -(int32_t)val) - val;
}
-_ALWAYS_INLINE_ uint32_t _atomic_add_impl(register uint32_t *pw, register uint32_t val) {
+_ALWAYS_INLINE_ uint32_t _atomic_add_impl(volatile uint32_t *pw, volatile uint32_t val) {
return InterlockedAdd((LONG volatile *)pw, val);
}
-_ALWAYS_INLINE_ uint32_t _atomic_exchange_if_greater_impl(register uint32_t *pw, register uint32_t val){
+_ALWAYS_INLINE_ uint32_t _atomic_exchange_if_greater_impl(volatile uint32_t *pw, volatile uint32_t val){
ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONG, InterlockedCompareExchange, uint32_t)
}
-_ALWAYS_INLINE_ uint64_t _atomic_conditional_increment_impl(register uint64_t *pw){
+_ALWAYS_INLINE_ uint64_t _atomic_conditional_increment_impl(volatile uint64_t *pw){
ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONGLONG, InterlockedCompareExchange64, uint64_t)
}
-_ALWAYS_INLINE_ uint64_t _atomic_decrement_impl(register uint64_t *pw) {
+_ALWAYS_INLINE_ uint64_t _atomic_decrement_impl(volatile uint64_t *pw) {
return InterlockedDecrement64((LONGLONG volatile *)pw);
}
-_ALWAYS_INLINE_ uint64_t _atomic_increment_impl(register uint64_t *pw) {
+_ALWAYS_INLINE_ uint64_t _atomic_increment_impl(volatile uint64_t *pw) {
return InterlockedIncrement64((LONGLONG volatile *)pw);
}
-_ALWAYS_INLINE_ uint64_t _atomic_sub_impl(register uint64_t *pw, register uint64_t val) {
+_ALWAYS_INLINE_ uint64_t _atomic_sub_impl(volatile uint64_t *pw, volatile uint64_t val) {
return InterlockedExchangeAdd64((LONGLONG volatile *)pw, -(int64_t)val) - val;
}
-_ALWAYS_INLINE_ uint64_t _atomic_add_impl(register uint64_t *pw, register uint64_t val) {
+_ALWAYS_INLINE_ uint64_t _atomic_add_impl(volatile uint64_t *pw, volatile uint64_t val) {
return InterlockedAdd64((LONGLONG volatile *)pw, val);
}
-_ALWAYS_INLINE_ uint64_t _atomic_exchange_if_greater_impl(register uint64_t *pw, register uint64_t val){
+_ALWAYS_INLINE_ uint64_t _atomic_exchange_if_greater_impl(volatile uint64_t *pw, volatile uint64_t val){
ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONGLONG, InterlockedCompareExchange64, uint64_t)
}
// The actual advertised functions; they'll call the right implementation
-uint32_t atomic_conditional_increment(register uint32_t *pw) {
+uint32_t atomic_conditional_increment(volatile uint32_t *pw) {
return _atomic_conditional_increment_impl(pw);
}
-uint32_t atomic_decrement(register uint32_t *pw) {
+uint32_t atomic_decrement(volatile uint32_t *pw) {
return _atomic_decrement_impl(pw);
}
-uint32_t atomic_increment(register uint32_t *pw) {
+uint32_t atomic_increment(volatile uint32_t *pw) {
return _atomic_increment_impl(pw);
}
-uint32_t atomic_sub(register uint32_t *pw, register uint32_t val) {
+uint32_t atomic_sub(volatile uint32_t *pw, volatile uint32_t val) {
return _atomic_sub_impl(pw, val);
}
-uint32_t atomic_add(register uint32_t *pw, register uint32_t val) {
+uint32_t atomic_add(volatile uint32_t *pw, volatile uint32_t val) {
return _atomic_add_impl(pw, val);
}
-uint32_t atomic_exchange_if_greater(register uint32_t *pw, register uint32_t val) {
+uint32_t atomic_exchange_if_greater(volatile uint32_t *pw, volatile uint32_t val) {
return _atomic_exchange_if_greater_impl(pw, val);
}
-uint64_t atomic_conditional_increment(register uint64_t *pw) {
+uint64_t atomic_conditional_increment(volatile uint64_t *pw) {
return _atomic_conditional_increment_impl(pw);
}
-uint64_t atomic_decrement(register uint64_t *pw) {
+uint64_t atomic_decrement(volatile uint64_t *pw) {
return _atomic_decrement_impl(pw);
}
-uint64_t atomic_increment(register uint64_t *pw) {
+uint64_t atomic_increment(volatile uint64_t *pw) {
return _atomic_increment_impl(pw);
}
-uint64_t atomic_sub(register uint64_t *pw, register uint64_t val) {
+uint64_t atomic_sub(volatile uint64_t *pw, volatile uint64_t val) {
return _atomic_sub_impl(pw, val);
}
-uint64_t atomic_add(register uint64_t *pw, register uint64_t val) {
+uint64_t atomic_add(volatile uint64_t *pw, volatile uint64_t val) {
return _atomic_add_impl(pw, val);
}
-uint64_t atomic_exchange_if_greater(register uint64_t *pw, register uint64_t val) {
+uint64_t atomic_exchange_if_greater(volatile uint64_t *pw, volatile uint64_t val) {
return _atomic_exchange_if_greater_impl(pw, val);
}
#endif
diff --git a/core/safe_refcount.h b/core/safe_refcount.h
index eff209c2db..36bcf5e576 100644
--- a/core/safe_refcount.h
+++ b/core/safe_refcount.h
@@ -44,7 +44,7 @@
/* Bogus implementation unaware of multiprocessing */
template <class T>
-static _ALWAYS_INLINE_ T atomic_conditional_increment(register T *pw) {
+static _ALWAYS_INLINE_ T atomic_conditional_increment(volatile T *pw) {
if (*pw == 0)
return 0;
@@ -55,7 +55,7 @@ static _ALWAYS_INLINE_ T atomic_conditional_increment(register T *pw) {
}
template <class T>
-static _ALWAYS_INLINE_ T atomic_decrement(register T *pw) {
+static _ALWAYS_INLINE_ T atomic_decrement(volatile T *pw) {
(*pw)--;
@@ -63,7 +63,7 @@ static _ALWAYS_INLINE_ T atomic_decrement(register T *pw) {
}
template <class T>
-static _ALWAYS_INLINE_ T atomic_increment(register T *pw) {
+static _ALWAYS_INLINE_ T atomic_increment(volatile T *pw) {
(*pw)++;
@@ -71,7 +71,7 @@ static _ALWAYS_INLINE_ T atomic_increment(register T *pw) {
}
template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_sub(register T *pw, register V val) {
+static _ALWAYS_INLINE_ T atomic_sub(volatile T *pw, volatile V val) {
(*pw) -= val;
@@ -79,7 +79,7 @@ static _ALWAYS_INLINE_ T atomic_sub(register T *pw, register V val) {
}
template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_add(register T *pw, register V val) {
+static _ALWAYS_INLINE_ T atomic_add(volatile T *pw, volatile V val) {
(*pw) += val;
@@ -87,7 +87,7 @@ static _ALWAYS_INLINE_ T atomic_add(register T *pw, register V val) {
}
template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_exchange_if_greater(register T *pw, register V val) {
+static _ALWAYS_INLINE_ T atomic_exchange_if_greater(volatile T *pw, volatile V val) {
if (val > *pw)
*pw = val;
@@ -103,7 +103,7 @@ static _ALWAYS_INLINE_ T atomic_exchange_if_greater(register T *pw, register V v
// Clang states it supports GCC atomic builtins.
template <class T>
-static _ALWAYS_INLINE_ T atomic_conditional_increment(register T *pw) {
+static _ALWAYS_INLINE_ T atomic_conditional_increment(volatile T *pw) {
while (true) {
T tmp = static_cast<T const volatile &>(*pw);
@@ -115,31 +115,31 @@ static _ALWAYS_INLINE_ T atomic_conditional_increment(register T *pw) {
}
template <class T>
-static _ALWAYS_INLINE_ T atomic_decrement(register T *pw) {
+static _ALWAYS_INLINE_ T atomic_decrement(volatile T *pw) {
return __sync_sub_and_fetch(pw, 1);
}
template <class T>
-static _ALWAYS_INLINE_ T atomic_increment(register T *pw) {
+static _ALWAYS_INLINE_ T atomic_increment(volatile T *pw) {
return __sync_add_and_fetch(pw, 1);
}
template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_sub(register T *pw, register V val) {
+static _ALWAYS_INLINE_ T atomic_sub(volatile T *pw, volatile V val) {
return __sync_sub_and_fetch(pw, val);
}
template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_add(register T *pw, register V val) {
+static _ALWAYS_INLINE_ T atomic_add(volatile T *pw, volatile V val) {
return __sync_add_and_fetch(pw, val);
}
template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_exchange_if_greater(register T *pw, register V val) {
+static _ALWAYS_INLINE_ T atomic_exchange_if_greater(volatile T *pw, volatile V val) {
while (true) {
T tmp = static_cast<T const volatile &>(*pw);
@@ -153,19 +153,19 @@ static _ALWAYS_INLINE_ T atomic_exchange_if_greater(register T *pw, register V v
#elif defined(_MSC_VER)
// For MSVC use a separate compilation unit to prevent windows.h from polluting
// the global namespace.
-uint32_t atomic_conditional_increment(register uint32_t *pw);
-uint32_t atomic_decrement(register uint32_t *pw);
-uint32_t atomic_increment(register uint32_t *pw);
-uint32_t atomic_sub(register uint32_t *pw, register uint32_t val);
-uint32_t atomic_add(register uint32_t *pw, register uint32_t val);
-uint32_t atomic_exchange_if_greater(register uint32_t *pw, register uint32_t val);
-
-uint64_t atomic_conditional_increment(register uint64_t *pw);
-uint64_t atomic_decrement(register uint64_t *pw);
-uint64_t atomic_increment(register uint64_t *pw);
-uint64_t atomic_sub(register uint64_t *pw, register uint64_t val);
-uint64_t atomic_add(register uint64_t *pw, register uint64_t val);
-uint64_t atomic_exchange_if_greater(register uint64_t *pw, register uint64_t val);
+uint32_t atomic_conditional_increment(volatile uint32_t *pw);
+uint32_t atomic_decrement(volatile uint32_t *pw);
+uint32_t atomic_increment(volatile uint32_t *pw);
+uint32_t atomic_sub(volatile uint32_t *pw, volatile uint32_t val);
+uint32_t atomic_add(volatile uint32_t *pw, volatile uint32_t val);
+uint32_t atomic_exchange_if_greater(volatile uint32_t *pw, volatile uint32_t val);
+
+uint64_t atomic_conditional_increment(volatile uint64_t *pw);
+uint64_t atomic_decrement(volatile uint64_t *pw);
+uint64_t atomic_increment(volatile uint64_t *pw);
+uint64_t atomic_sub(volatile uint64_t *pw, volatile uint64_t val);
+uint64_t atomic_add(volatile uint64_t *pw, volatile uint64_t val);
+uint64_t atomic_exchange_if_greater(volatile uint64_t *pw, volatile uint64_t val);
#else
//no threads supported?
diff --git a/core/translation.cpp b/core/translation.cpp
index aaa4de5912..78115c3749 100644
--- a/core/translation.cpp
+++ b/core/translation.cpp
@@ -1171,13 +1171,11 @@ void TranslationServer::_bind_methods() {
void TranslationServer::load_translations() {
String locale = get_locale();
- bool found = _load_translations("locale/translations"); //all
+ _load_translations("locale/translations"); //all
+ _load_translations("locale/translations_" + locale.substr(0, 2));
- if (_load_translations("locale/translations_" + locale.substr(0, 2)))
- found = true;
if (locale.substr(0, 2) != locale) {
- if (_load_translations("locale/translations_" + locale))
- found = true;
+ _load_translations("locale/translations_" + locale);
}
}
diff --git a/core/ustring.cpp b/core/ustring.cpp
index bb08dd13c4..f552cb13ac 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -161,14 +161,21 @@ void String::copy_from(const CharType *p_cstr, int p_clip_to) {
return;
}
- resize(len + 1);
- set(len, 0);
+ copy_from_unchecked(p_cstr, len);
+}
- CharType *dst = &operator[](0);
+// assumes the following have already been validated:
+// p_char != NULL
+// p_length > 0
+// p_length <= p_char strlen
+void String::copy_from_unchecked(const CharType *p_char, int p_length) {
+ resize(p_length + 1);
+ set(p_length, 0);
- for (int i = 0; i < len; i++) {
+ CharType *dst = &operator[](0);
- dst[i] = p_cstr[i];
+ for (int i = 0; i < p_length; i++) {
+ dst[i] = p_char[i];
}
}
@@ -2246,7 +2253,9 @@ String String::substr(int p_from, int p_chars) const {
return String(*this);
}
- return String(&c_str()[p_from], p_chars);
+ String s = String();
+ s.copy_from_unchecked(&c_str()[p_from], p_chars);
+ return s;
}
int String::find_last(const String &p_str) const {
diff --git a/core/ustring.h b/core/ustring.h
index b57e9629d9..001d111d64 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -65,6 +65,7 @@ class String : public Vector<CharType> {
void copy_from(const char *p_cstr);
void copy_from(const CharType *p_cstr, int p_clip_to = -1);
void copy_from(const CharType &p_char);
+ void copy_from_unchecked(const CharType *p_char, int p_length);
bool _base_is_subsequence_of(const String &p_string, bool case_insensitive) const;
public: