summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/io/file_access_buffered.cpp150
-rw-r--r--core/io/file_access_buffered_fa.h139
-rw-r--r--core/math/random_number_generator.cpp7
-rw-r--r--core/math/random_number_generator.h8
-rw-r--r--core/math/random_pcg.h7
-rw-r--r--doc/classes/RandomNumberGenerator.xml22
-rw-r--r--drivers/unix/os_unix.cpp1
-rw-r--r--platform/android/SCsub1
-rw-r--r--platform/android/display_server_android.cpp52
-rw-r--r--platform/android/display_server_android.h7
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.java5
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java5
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java5
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java7
-rw-r--r--platform/android/java_godot_lib_jni.cpp5
-rw-r--r--platform/android/java_godot_view_wrapper.cpp66
-rw-r--r--platform/android/java_godot_view_wrapper.h (renamed from core/io/file_access_buffered.h)67
-rw-r--r--platform/android/java_godot_wrapper.cpp10
-rw-r--r--platform/android/java_godot_wrapper.h4
-rw-r--r--platform/android/os_android.cpp5
-rw-r--r--platform/javascript/os_javascript.cpp2
-rw-r--r--platform/windows/os_windows.cpp1
-rw-r--r--scene/resources/sky_material.cpp2
-rw-r--r--tests/test_main.cpp1
-rw-r--r--tests/test_random_number_generator.h111
25 files changed, 316 insertions, 374 deletions
diff --git a/core/io/file_access_buffered.cpp b/core/io/file_access_buffered.cpp
deleted file mode 100644
index 714f3b6099..0000000000
--- a/core/io/file_access_buffered.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/*************************************************************************/
-/* file_access_buffered.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 "file_access_buffered.h"
-
-#include "core/error/error_macros.h"
-
-Error FileAccessBuffered::set_error(Error p_error) const {
- return (last_error = p_error);
-}
-
-void FileAccessBuffered::set_cache_size(int p_size) {
- cache_size = p_size;
-}
-
-int FileAccessBuffered::get_cache_size() {
- return cache_size;
-}
-
-int FileAccessBuffered::cache_data_left() const {
- if (file.offset >= file.size) {
- return 0;
- }
-
- if (cache.offset == -1 || file.offset < cache.offset || file.offset >= cache.offset + cache.buffer.size()) {
- return read_data_block(file.offset, cache_size);
- }
-
- return cache.buffer.size() - (file.offset - cache.offset);
-}
-
-void FileAccessBuffered::seek(size_t p_position) {
- file.offset = p_position;
-}
-
-void FileAccessBuffered::seek_end(int64_t p_position) {
- file.offset = file.size + p_position;
-}
-
-size_t FileAccessBuffered::get_position() const {
- return file.offset;
-}
-
-size_t FileAccessBuffered::get_len() const {
- return file.size;
-}
-
-bool FileAccessBuffered::eof_reached() const {
- return file.offset > file.size;
-}
-
-uint8_t FileAccessBuffered::get_8() const {
- ERR_FAIL_COND_V_MSG(!file.open, 0, "Can't get data, when file is not opened.");
-
- uint8_t byte = 0;
- if (cache_data_left() >= 1) {
- byte = cache.buffer[file.offset - cache.offset];
- }
-
- ++file.offset;
-
- return byte;
-}
-
-int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const {
- ERR_FAIL_COND_V_MSG(!file.open, -1, "Can't get buffer, when file is not opened.");
-
- if (p_length > cache_size) {
- int total_read = 0;
-
- if (!(cache.offset == -1 || file.offset < cache.offset || file.offset >= cache.offset + cache.buffer.size())) {
- int size = (cache.buffer.size() - (file.offset - cache.offset));
- size = size - (size % 4);
- //const uint8_t* read = cache.buffer.ptr();
- //memcpy(p_dest, read.ptr() + (file.offset - cache.offset), size);
- memcpy(p_dest, cache.buffer.ptr() + (file.offset - cache.offset), size);
- p_dest += size;
- p_length -= size;
- file.offset += size;
- total_read += size;
- }
-
- int err = read_data_block(file.offset, p_length, p_dest);
- if (err >= 0) {
- total_read += err;
- file.offset += err;
- }
-
- return total_read;
- }
-
- int to_read = p_length;
- int total_read = 0;
- while (to_read > 0) {
- int left = cache_data_left();
- if (left == 0) {
- file.offset += to_read;
- return total_read;
- }
- if (left < 0) {
- return left;
- }
-
- int r = MIN(left, to_read);
- //const uint8_t* read = cache.buffer.ptr();
- //memcpy(p_dest+total_read, &read.ptr()[file.offset - cache.offset], r);
- memcpy(p_dest + total_read, cache.buffer.ptr() + (file.offset - cache.offset), r);
-
- file.offset += r;
- total_read += r;
- to_read -= r;
- }
-
- return p_length;
-}
-
-bool FileAccessBuffered::is_open() const {
- return file.open;
-}
-
-Error FileAccessBuffered::get_error() const {
- return last_error;
-}
diff --git a/core/io/file_access_buffered_fa.h b/core/io/file_access_buffered_fa.h
deleted file mode 100644
index f22e54e154..0000000000
--- a/core/io/file_access_buffered_fa.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*************************************************************************/
-/* file_access_buffered_fa.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 FILE_ACCESS_BUFFERED_FA_H
-#define FILE_ACCESS_BUFFERED_FA_H
-
-#include "core/io/file_access_buffered.h"
-
-template <class T>
-class FileAccessBufferedFA : public FileAccessBuffered {
- T f;
-
- int read_data_block(int p_offset, int p_size, uint8_t *p_dest = 0) const {
- ERR_FAIL_COND_V_MSG(!f.is_open(), -1, "Can't read data block when file is not opened.");
-
- ((T *)&f)->seek(p_offset);
-
- if (p_dest) {
- f.get_buffer(p_dest, p_size);
- return p_size;
-
- } else {
- cache.offset = p_offset;
- cache.buffer.resize(p_size);
-
- // on Vector
- //uint8_t* write = cache.buffer.ptrw();
- //f.get_buffer(write.ptrw(), p_size);
-
- // on vector
- f.get_buffer(cache.buffer.ptrw(), p_size);
-
- return p_size;
- }
- }
-
- static FileAccess *create() {
- return memnew(FileAccessBufferedFA<T>());
- }
-
-protected:
- virtual void _set_access_type(AccessType p_access) {
- f._set_access_type(p_access);
- FileAccessBuffered::_set_access_type(p_access);
- }
-
-public:
- void flush() {
- f.flush();
- }
-
- void store_8(uint8_t p_dest) {
- f.store_8(p_dest);
- }
-
- void store_buffer(const uint8_t *p_src, int p_length) {
- f.store_buffer(p_src, p_length);
- }
-
- bool file_exists(const String &p_name) {
- return f.file_exists(p_name);
- }
-
- Error _open(const String &p_path, int p_mode_flags) {
- close();
-
- Error ret = f._open(p_path, p_mode_flags);
- if (ret != OK)
- return ret;
- //ERR_FAIL_COND_V( ret != OK, ret );
-
- file.size = f.get_len();
- file.offset = 0;
- file.open = true;
- file.name = p_path;
- file.access_flags = p_mode_flags;
-
- cache.buffer.resize(0);
- cache.offset = 0;
-
- return set_error(OK);
- }
-
- void close() {
- f.close();
-
- file.offset = 0;
- file.size = 0;
- file.open = false;
- file.name = "";
-
- cache.buffer.resize(0);
- cache.offset = 0;
- set_error(OK);
- }
-
- virtual uint64_t _get_modified_time(const String &p_file) {
- return f._get_modified_time(p_file);
- }
-
- virtual uint32_t _get_unix_permissions(const String &p_file) {
- return f._get_unix_permissions(p_file);
- }
-
- virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) {
- return f._set_unix_permissions(p_file, p_permissions);
- }
-
- FileAccessBufferedFA() {}
-};
-
-#endif // FILE_ACCESS_BUFFERED_FA_H
diff --git a/core/math/random_number_generator.cpp b/core/math/random_number_generator.cpp
index a124f63030..f045213fb9 100644
--- a/core/math/random_number_generator.cpp
+++ b/core/math/random_number_generator.cpp
@@ -34,6 +34,9 @@ void RandomNumberGenerator::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_seed", "seed"), &RandomNumberGenerator::set_seed);
ClassDB::bind_method(D_METHOD("get_seed"), &RandomNumberGenerator::get_seed);
+ ClassDB::bind_method(D_METHOD("set_state", "state"), &RandomNumberGenerator::set_state);
+ ClassDB::bind_method(D_METHOD("get_state"), &RandomNumberGenerator::get_state);
+
ClassDB::bind_method(D_METHOD("randi"), &RandomNumberGenerator::randi);
ClassDB::bind_method(D_METHOD("randf"), &RandomNumberGenerator::randf);
ClassDB::bind_method(D_METHOD("randfn", "mean", "deviation"), &RandomNumberGenerator::randfn, DEFVAL(0.0), DEFVAL(1.0));
@@ -42,6 +45,8 @@ void RandomNumberGenerator::_bind_methods() {
ClassDB::bind_method(D_METHOD("randomize"), &RandomNumberGenerator::randomize);
ADD_PROPERTY(PropertyInfo(Variant::INT, "seed"), "set_seed", "get_seed");
- // Default value is non-deterministic, override it for doc generation purposes.
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "state"), "set_state", "get_state");
+ // Default values are non-deterministic, override for doc generation purposes.
ADD_PROPERTY_DEFAULT("seed", 0);
+ ADD_PROPERTY_DEFAULT("state", 0);
}
diff --git a/core/math/random_number_generator.h b/core/math/random_number_generator.h
index 0d0ea17205..7728fd09c0 100644
--- a/core/math/random_number_generator.h
+++ b/core/math/random_number_generator.h
@@ -44,19 +44,17 @@ protected:
public:
_FORCE_INLINE_ void set_seed(uint64_t p_seed) { randbase.seed(p_seed); }
-
_FORCE_INLINE_ uint64_t get_seed() { return randbase.get_seed(); }
+ _FORCE_INLINE_ void set_state(uint64_t p_state) { randbase.set_state(p_state); }
+ _FORCE_INLINE_ uint64_t get_state() const { return randbase.get_state(); }
+
_FORCE_INLINE_ void randomize() { randbase.randomize(); }
_FORCE_INLINE_ uint32_t randi() { return randbase.rand(); }
-
_FORCE_INLINE_ real_t randf() { return randbase.randf(); }
-
_FORCE_INLINE_ real_t randf_range(real_t p_from, real_t p_to) { return randbase.random(p_from, p_to); }
-
_FORCE_INLINE_ real_t randfn(real_t p_mean = 0.0, real_t p_deviation = 1.0) { return randbase.randfn(p_mean, p_deviation); }
-
_FORCE_INLINE_ int randi_range(int p_from, int p_to) { return randbase.random(p_from, p_to); }
RandomNumberGenerator() {}
diff --git a/core/math/random_pcg.h b/core/math/random_pcg.h
index fe6b1b5639..2e257cb5b7 100644
--- a/core/math/random_pcg.h
+++ b/core/math/random_pcg.h
@@ -61,7 +61,7 @@ static int __bsr_clz32(uint32_t x) {
class RandomPCG {
pcg32_random_t pcg;
- uint64_t current_seed; // seed with this to get the same state
+ uint64_t current_seed; // The seed the current generator state started from.
uint64_t current_inc;
public:
@@ -76,13 +76,14 @@ public:
}
_FORCE_INLINE_ uint64_t get_seed() { return current_seed; }
+ _FORCE_INLINE_ void set_state(uint64_t p_state) { pcg.state = p_state; }
+ _FORCE_INLINE_ uint64_t get_state() const { return pcg.state; }
+
void randomize();
_FORCE_INLINE_ uint32_t rand() {
- current_seed = pcg.state;
return pcg32_random_r(&pcg);
}
_FORCE_INLINE_ uint32_t rand(uint32_t bounds) {
- current_seed = pcg.state;
return pcg32_boundedrand_r(&pcg, bounds);
}
diff --git a/doc/classes/RandomNumberGenerator.xml b/doc/classes/RandomNumberGenerator.xml
index dcb75dc275..6312cd18aa 100644
--- a/doc/classes/RandomNumberGenerator.xml
+++ b/doc/classes/RandomNumberGenerator.xml
@@ -13,6 +13,7 @@
rng.randomize()
var my_random_number = rng.randf_range(-10.0, 10.0)
[/codeblock]
+ [b]Note:[/b] The default values of [member seed] and [member state] properties are pseudo-random, and changes when calling [method randomize]. The [code]0[/code] value documented here is a placeholder, and not the actual default seed.
</description>
<tutorials>
<link title="Random number generation">https://docs.godotengine.org/en/latest/tutorials/math/random_number_generation.html</link>
@@ -75,9 +76,26 @@
</methods>
<members>
<member name="seed" type="int" setter="set_seed" getter="get_seed" default="0">
- The seed used by the random number generator. A given seed will give a reproducible sequence of pseudo-random numbers.
+ Initializes the random number generator state based on the given seed value. A given seed will give a reproducible sequence of pseudo-random numbers.
[b]Note:[/b] The RNG does not have an avalanche effect, and can output similar random streams given similar seeds. Consider using a hash function to improve your seed quality if they're sourced externally.
- [b]Note:[/b] The default value of this property is pseudo-random, and changes when calling [method randomize]. The [code]0[/code] value documented here is a placeholder, and not the actual default seed.
+ [b]Note:[/b] Setting this property produces a side effect of changing the internal [member state], so make sure to initialize the seed [i]before[/i] modifying the [member state]:
+ [codeblock]
+ var rng = RandomNumberGenerator.new()
+ rng.seed = hash("Godot")
+ rng.state = 100 # Restore to some previously saved state.
+ [/codeblock]
+ </member>
+ <member name="state" type="int" setter="set_state" getter="get_state" default="0">
+ The current state of the random number generator. Save and restore this property to restore the generator to a previous state:
+ [codeblock]
+ var rng = RandomNumberGenerator.new()
+ print(rng.randf())
+ var saved_state = rng.state # Store current state.
+ print(rng.randf()) # Advance internal state.
+ rng.state = saved_state # Restore the state.
+ print(rng.randf()) # Prints the same value as in previous.
+ [/codeblock]
+ [b]Note:[/b] Do not set state to arbitrary values, since the random number generator requires the state to have certain qualities to behave properly. It should only be set to values that came from the state property itself. To initialize the random number generator with arbitrary input, use [member seed] instead.
</member>
</members>
<constants>
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 318638e5d0..ca08d689b9 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -127,7 +127,6 @@ void OS_Unix::initialize_core() {
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES);
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM);
- //FileAccessBufferedFA<FileAccessUnix>::make_default();
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_RESOURCES);
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA);
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM);
diff --git a/platform/android/SCsub b/platform/android/SCsub
index ec42bc42b5..2f37624cfb 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -14,6 +14,7 @@ android_files = [
"java_godot_lib_jni.cpp",
"java_class_wrapper.cpp",
"java_godot_wrapper.cpp",
+ "java_godot_view_wrapper.cpp",
"java_godot_io_wrapper.cpp",
"jni_utils.cpp",
"android_keys_utils.cpp",
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index c8ed44d699..8711a4333c 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -686,7 +686,7 @@ void DisplayServerAndroid::process_hover(int p_type, Point2 p_pos) {
}
}
-void DisplayServerAndroid::process_mouse_event(int event_action, int event_android_buttons_mask, Point2 event_pos, float event_vertical_factor, float event_horizontal_factor) {
+void DisplayServerAndroid::process_mouse_event(int input_device, int event_action, int event_android_buttons_mask, Point2 event_pos, float event_vertical_factor, float event_horizontal_factor) {
int event_buttons_mask = _android_button_mask_to_godot_button_mask(event_android_buttons_mask);
switch (event_action) {
case AMOTION_EVENT_ACTION_BUTTON_PRESS:
@@ -694,8 +694,13 @@ void DisplayServerAndroid::process_mouse_event(int event_action, int event_andro
Ref<InputEventMouseButton> ev;
ev.instance();
_set_key_modifier_state(ev);
- ev->set_position(event_pos);
- ev->set_global_position(event_pos);
+ if ((input_device & AINPUT_SOURCE_MOUSE) == AINPUT_SOURCE_MOUSE) {
+ ev->set_position(event_pos);
+ ev->set_global_position(event_pos);
+ } else {
+ ev->set_position(hover_prev_pos);
+ ev->set_global_position(hover_prev_pos);
+ }
ev->set_pressed(event_action == AMOTION_EVENT_ACTION_BUTTON_PRESS);
int changed_button_mask = buttons_state ^ event_buttons_mask;
@@ -710,18 +715,29 @@ void DisplayServerAndroid::process_mouse_event(int event_action, int event_andro
Ref<InputEventMouseMotion> ev;
ev.instance();
_set_key_modifier_state(ev);
- ev->set_position(event_pos);
- ev->set_global_position(event_pos);
- ev->set_relative(event_pos - hover_prev_pos);
+ if ((input_device & AINPUT_SOURCE_MOUSE) == AINPUT_SOURCE_MOUSE) {
+ ev->set_position(event_pos);
+ ev->set_global_position(event_pos);
+ ev->set_relative(event_pos - hover_prev_pos);
+ hover_prev_pos = event_pos;
+ } else {
+ ev->set_position(hover_prev_pos);
+ ev->set_global_position(hover_prev_pos);
+ ev->set_relative(event_pos);
+ }
ev->set_button_mask(event_buttons_mask);
Input::get_singleton()->accumulate_input_event(ev);
- hover_prev_pos = event_pos;
} break;
case AMOTION_EVENT_ACTION_SCROLL: {
Ref<InputEventMouseButton> ev;
ev.instance();
- ev->set_position(event_pos);
- ev->set_global_position(event_pos);
+ if ((input_device & AINPUT_SOURCE_MOUSE) == AINPUT_SOURCE_MOUSE) {
+ ev->set_position(event_pos);
+ ev->set_global_position(event_pos);
+ } else {
+ ev->set_position(hover_prev_pos);
+ ev->set_global_position(hover_prev_pos);
+ }
ev->set_pressed(true);
buttons_state = event_buttons_mask;
if (event_vertical_factor > 0) {
@@ -809,6 +825,24 @@ void DisplayServerAndroid::process_gyroscope(const Vector3 &p_gyroscope) {
Input::get_singleton()->set_gyroscope(p_gyroscope);
}
+void DisplayServerAndroid::mouse_set_mode(MouseMode p_mode) {
+ if (mouse_mode == p_mode) {
+ return;
+ }
+
+ if (p_mode == MouseMode::MOUSE_MODE_CAPTURED) {
+ OS_Android::get_singleton()->get_godot_java()->get_godot_view()->request_pointer_capture();
+ } else {
+ OS_Android::get_singleton()->get_godot_java()->get_godot_view()->release_pointer_capture();
+ }
+
+ mouse_mode = p_mode;
+}
+
+DisplayServer::MouseMode DisplayServerAndroid::mouse_get_mode() const {
+ return mouse_mode;
+}
+
Point2i DisplayServerAndroid::mouse_get_position() const {
return hover_prev_pos;
}
diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h
index 7480eb8ebf..f1f1a6a278 100644
--- a/platform/android/display_server_android.h
+++ b/platform/android/display_server_android.h
@@ -70,6 +70,8 @@ private:
int buttons_state;
+ MouseMode mouse_mode;
+
bool keep_screen_on;
Vector<TouchPos> touch;
@@ -172,12 +174,15 @@ public:
void process_gyroscope(const Vector3 &p_gyroscope);
void process_touch(int p_event, int p_pointer, const Vector<TouchPos> &p_points);
void process_hover(int p_type, Point2 p_pos);
- void process_mouse_event(int event_action, int event_android_buttons_mask, Point2 event_pos, float event_vertical_factor = 0, float event_horizontal_factor = 0);
+ void process_mouse_event(int input_device, int event_action, int event_android_buttons_mask, Point2 event_pos, float event_vertical_factor = 0, float event_horizontal_factor = 0);
void process_double_tap(int event_android_button_mask, Point2 p_pos);
void process_scroll(Point2 p_pos);
void process_joy_event(JoypadEvent p_event);
void process_key_event(int p_keycode, int p_scancode, int p_unicode_char, bool p_pressed);
+ void mouse_set_mode(MouseMode p_mode);
+ MouseMode mouse_get_mode() const;
+
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
static Vector<String> get_rendering_drivers_func();
static void register_android_driver();
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
index 3bbe35091c..ad1dc53bc0 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
@@ -988,4 +988,9 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
public void initInputDevices() {
mRenderView.initInputDevices();
}
+
+ @Keep
+ private GodotRenderView getRenderView() { // used by native side to get renderView
+ return mRenderView;
+ }
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
index d731e080c4..2cd67933ee 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
@@ -144,6 +144,11 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
return inputHandler.onGenericMotionEvent(event) || super.onGenericMotionEvent(event);
}
+ @Override
+ public boolean onCapturedPointerEvent(MotionEvent event) {
+ return inputHandler.onGenericMotionEvent(event);
+ }
+
private void init(XRMode xrMode, boolean translucent, int depth, int stencil) {
setPreserveEGLContextOnPause(true);
setFocusableInTouchMode(true);
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
index 6cd5ca7b4e..d5e0345a9c 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
@@ -120,6 +120,11 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV
}
@Override
+ public boolean onCapturedPointerEvent(MotionEvent event) {
+ return mInputHandler.onGenericMotionEvent(event);
+ }
+
+ @Override
public void onResume() {
super.onResume();
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
index 6d5be312f1..b052cd9d92 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
@@ -245,7 +245,7 @@ public class GodotInputHandler implements InputDeviceListener {
}
});
return true;
- } else if ((event.getSource() & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {
+ } else if (event.isFromSource(InputDevice.SOURCE_MOUSE) || event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return handleMouseEvent(event);
}
@@ -462,6 +462,11 @@ public class GodotInputHandler implements InputDeviceListener {
}
});
}
+ case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_UP: {
+ // we can safely ignore these cases because they are always come beside ACTION_BUTTON_PRESS and ACTION_BUTTON_RELEASE
+ return true;
+ }
}
return false;
}
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index 5dc773fae2..03557b9017 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -251,9 +251,8 @@ void touch_preprocessing(JNIEnv *env, jclass clazz, jint input_device, jint ev,
tp.id = (int)p[0];
points.push_back(tp);
}
-
- if ((input_device & AINPUT_SOURCE_MOUSE) == AINPUT_SOURCE_MOUSE) {
- DisplayServerAndroid::get_singleton()->process_mouse_event(ev, buttons_mask, points[0].pos, vertical_factor, horizontal_factor);
+ if ((input_device & AINPUT_SOURCE_MOUSE) == AINPUT_SOURCE_MOUSE || (input_device & AINPUT_SOURCE_MOUSE_RELATIVE) == AINPUT_SOURCE_MOUSE_RELATIVE) {
+ DisplayServerAndroid::get_singleton()->process_mouse_event(input_device, ev, buttons_mask, points[0].pos, vertical_factor, horizontal_factor);
} else {
DisplayServerAndroid::get_singleton()->process_touch(ev, pointer, points);
}
diff --git a/platform/android/java_godot_view_wrapper.cpp b/platform/android/java_godot_view_wrapper.cpp
new file mode 100644
index 0000000000..6655dd9895
--- /dev/null
+++ b/platform/android/java_godot_view_wrapper.cpp
@@ -0,0 +1,66 @@
+/*************************************************************************/
+/* java_godot_view_wrapper.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 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 "java_godot_view_wrapper.h"
+
+#include "thread_jandroid.h"
+
+GodotJavaViewWrapper::GodotJavaViewWrapper(jobject godot_view) {
+ JNIEnv *env = ThreadAndroid::get_env();
+
+ _godot_view = env->NewGlobalRef(godot_view);
+
+ _cls = (jclass)env->NewGlobalRef(env->GetObjectClass(godot_view));
+
+ if (android_get_device_api_level() >= __ANDROID_API_O__) {
+ _request_pointer_capture = env->GetMethodID(_cls, "requestPointerCapture", "()V");
+ _release_pointer_capture = env->GetMethodID(_cls, "releasePointerCapture", "()V");
+ }
+}
+
+void GodotJavaViewWrapper::request_pointer_capture() {
+ if (_request_pointer_capture != 0) {
+ JNIEnv *env = ThreadAndroid::get_env();
+ env->CallVoidMethod(_godot_view, _request_pointer_capture);
+ }
+}
+
+void GodotJavaViewWrapper::release_pointer_capture() {
+ if (_request_pointer_capture != 0) {
+ JNIEnv *env = ThreadAndroid::get_env();
+ env->CallVoidMethod(_godot_view, _release_pointer_capture);
+ }
+}
+
+GodotJavaViewWrapper::~GodotJavaViewWrapper() {
+ JNIEnv *env = ThreadAndroid::get_env();
+ env->DeleteGlobalRef(_godot_view);
+ env->DeleteGlobalRef(_cls);
+}
diff --git a/core/io/file_access_buffered.h b/platform/android/java_godot_view_wrapper.h
index 7fd99b6373..4c8f6edad0 100644
--- a/core/io/file_access_buffered.h
+++ b/platform/android/java_godot_view_wrapper.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* file_access_buffered.h */
+/* java_godot_view_wrapper.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,64 +28,29 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef FILE_ACCESS_BUFFERED_H
-#define FILE_ACCESS_BUFFERED_H
+#ifndef GODOT_JAVA_GODOT_VIEW_WRAPPER_H
+#define GODOT_JAVA_GODOT_VIEW_WRAPPER_H
-#include "core/os/file_access.h"
-
-#include "core/string/ustring.h"
-
-class FileAccessBuffered : public FileAccess {
-public:
- enum {
- DEFAULT_CACHE_SIZE = 128 * 1024,
- };
+#include <android/log.h>
+#include <jni.h>
+// Class that makes functions in java/src/org/godotengine/godot/GodotView.java callable from C++
+class GodotJavaViewWrapper {
private:
- int cache_size = DEFAULT_CACHE_SIZE;
-
- int cache_data_left() const;
- mutable Error last_error;
-
-protected:
- Error set_error(Error p_error) const;
-
- mutable struct File {
- bool open = false;
- int size = 0;
- int offset = 0;
- String name;
- int access_flags = 0;
- } file;
+ jclass _cls;
- mutable struct Cache {
- Vector<uint8_t> buffer;
- int offset = 0;
- } cache;
+ jobject _godot_view;
- virtual int read_data_block(int p_offset, int p_size, uint8_t *p_dest = nullptr) const = 0;
-
- void set_cache_size(int p_size);
- int get_cache_size();
+ jmethodID _request_pointer_capture = 0;
+ jmethodID _release_pointer_capture = 0;
public:
- virtual size_t get_position() const; ///< get position in the file
- virtual size_t get_len() const; ///< get size of the file
-
- virtual void seek(size_t p_position); ///< seek to a given position
- virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
-
- virtual bool eof_reached() const;
-
- virtual uint8_t get_8() const;
- virtual int get_buffer(uint8_t *p_dest, int p_length) const; ///< get an array of bytes
-
- virtual bool is_open() const;
+ GodotJavaViewWrapper(jobject godot_view);
- virtual Error get_error() const;
+ void request_pointer_capture();
+ void release_pointer_capture();
- FileAccessBuffered() {}
- virtual ~FileAccessBuffered() {}
+ ~GodotJavaViewWrapper();
};
-#endif
+#endif //GODOT_JAVA_GODOT_VIEW_WRAPPER_H
diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp
index cff591d903..7919e47b5c 100644
--- a/platform/android/java_godot_wrapper.cpp
+++ b/platform/android/java_godot_wrapper.cpp
@@ -109,6 +109,16 @@ jobject GodotJavaWrapper::get_class_loader() {
}
}
+GodotJavaViewWrapper *GodotJavaWrapper::get_godot_view() {
+ if (_godot_view != nullptr) {
+ return _godot_view;
+ }
+ JNIEnv *env = ThreadAndroid::get_env();
+ jmethodID godot_view_getter = env->GetMethodID(godot_class, "getRenderView", "()Lorg/godotengine/godot/GodotRenderView;");
+ _godot_view = new GodotJavaViewWrapper(env->CallObjectMethod(godot_instance, godot_view_getter));
+ return _godot_view;
+}
+
void GodotJavaWrapper::on_video_init(JNIEnv *p_env) {
if (_on_video_init)
if (p_env == nullptr)
diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h
index e0c3809a64..c212e107cb 100644
--- a/platform/android/java_godot_wrapper.h
+++ b/platform/android/java_godot_wrapper.h
@@ -37,6 +37,7 @@
#include <android/log.h>
#include <jni.h>
+#include "java_godot_view_wrapper.h"
#include "string_android.h"
// Class that makes functions in java/src/org/godotengine/godot/Godot.java callable from C++
@@ -47,6 +48,8 @@ private:
jclass godot_class;
jclass activity_class;
+ GodotJavaViewWrapper *_godot_view = nullptr;
+
jmethodID _on_video_init = 0;
jmethodID _restart = 0;
jmethodID _finish = 0;
@@ -74,6 +77,7 @@ public:
jobject get_member_object(const char *p_name, const char *p_class, JNIEnv *p_env = nullptr);
jobject get_class_loader();
+ GodotJavaViewWrapper *get_godot_view();
void on_video_init(JNIEnv *p_env = nullptr);
void on_godot_main_loop_started(JNIEnv *p_env = nullptr);
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 25a8297a3d..8567d0392f 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -31,7 +31,6 @@
#include "os_android.h"
#include "core/config/project_settings.h"
-#include "core/io/file_access_buffered_fa.h"
#include "drivers/unix/dir_access_unix.h"
#include "drivers/unix/file_access_unix.h"
#include "file_access_android.h"
@@ -63,15 +62,13 @@ void OS_Android::initialize_core() {
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES);
else {
#ifdef USE_JAVA_FILE_ACCESS
- FileAccess::make_default<FileAccessBufferedFA<FileAccessJAndroid>>(FileAccess::ACCESS_RESOURCES);
+ FileAccess::make_default<FileAccessJAndroid>(FileAccess::ACCESS_RESOURCES);
#else
- //FileAccess::make_default<FileAccessBufferedFA<FileAccessAndroid> >(FileAccess::ACCESS_RESOURCES);
FileAccess::make_default<FileAccessAndroid>(FileAccess::ACCESS_RESOURCES);
#endif
}
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM);
- //FileAccessBufferedFA<FileAccessUnix>::make_default();
if (use_apk_expansion)
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_RESOURCES);
else
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp
index ebfcd7293e..8c976da58e 100644
--- a/platform/javascript/os_javascript.cpp
+++ b/platform/javascript/os_javascript.cpp
@@ -31,7 +31,6 @@
#include "os_javascript.h"
#include "core/debugger/engine_debugger.h"
-#include "core/io/file_access_buffered_fa.h"
#include "core/io/json.h"
#include "drivers/unix/dir_access_unix.h"
#include "drivers/unix/file_access_unix.h"
@@ -52,7 +51,6 @@
// Lifecycle
void OS_JavaScript::initialize() {
OS_Unix::initialize_core();
- FileAccess::make_default<FileAccessBufferedFA<FileAccessUnix>>(FileAccess::ACCESS_RESOURCES);
DisplayServerJavaScript::register_javascript_driver();
#ifdef MODULE_WEBSOCKET_ENABLED
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index c8c04f230e..633a5091de 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -183,7 +183,6 @@ void OS_Windows::initialize() {
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM);
- //FileAccessBufferedFA<FileAccessWindows>::make_default();
DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_RESOURCES);
DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_USERDATA);
DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_FILESYSTEM);
diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp
index 69e8e0b5bd..05bb13a1e0 100644
--- a/scene/resources/sky_material.cpp
+++ b/scene/resources/sky_material.cpp
@@ -568,7 +568,7 @@ PhysicalSkyMaterial::PhysicalSkyMaterial() {
code += "\tCOLOR = pow(color, vec3(1.0 / (1.2 + (1.2 * sun_fade))));\n";
code += "\tCOLOR *= exposure;\n";
code += "\t// Make optional, eliminates banding\n";
- code += "\tCOLOR += (hash(EYEDIR * 1741.9782) * 0.08 - 0.04) * 0.008 * dither_strength;\n";
+ code += "\tCOLOR += (hash(EYEDIR * 1741.9782) * 0.08 - 0.04) * 0.016 * dither_strength;\n";
code += "}\n";
shader = RS::get_singleton()->shader_create();
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
index dd8c36e737..a152f3d451 100644
--- a/tests/test_main.cpp
+++ b/tests/test_main.cpp
@@ -56,6 +56,7 @@
#include "test_pck_packer.h"
#include "test_physics_2d.h"
#include "test_physics_3d.h"
+#include "test_random_number_generator.h"
#include "test_rect2.h"
#include "test_render.h"
#include "test_shader_lang.h"
diff --git a/tests/test_random_number_generator.h b/tests/test_random_number_generator.h
new file mode 100644
index 0000000000..50ad5ee362
--- /dev/null
+++ b/tests/test_random_number_generator.h
@@ -0,0 +1,111 @@
+/*************************************************************************/
+/* test_random_number_generator.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 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 TEST_RANDOM_NUMBER_GENERATOR_H
+#define TEST_RANDOM_NUMBER_GENERATOR_H
+
+#include "core/math/random_number_generator.h"
+#include "tests/test_macros.h"
+
+namespace TestRandomNumberGenerator {
+
+TEST_CASE("[RandomNumberGenerator] Zero for first number immediately after seeding") {
+ Ref<RandomNumberGenerator> rng = memnew(RandomNumberGenerator);
+ rng->set_seed(0);
+ uint32_t n1 = rng->randi();
+ uint32_t n2 = rng->randi();
+ INFO("Initial random values: " << n1 << " " << n2);
+ CHECK(n1 != 0);
+
+ rng->set_seed(1);
+ uint32_t n3 = rng->randi();
+ uint32_t n4 = rng->randi();
+ INFO("Values after changing the seed: " << n3 << " " << n4);
+ CHECK(n3 != 0);
+}
+
+TEST_CASE("[RandomNumberGenerator] Restore state") {
+ Ref<RandomNumberGenerator> rng = memnew(RandomNumberGenerator);
+ rng->randomize();
+ uint64_t last_seed = rng->get_seed();
+ INFO("Current seed: " << last_seed);
+
+ rng->randi();
+ rng->randi();
+
+ CHECK_MESSAGE(rng->get_seed() == last_seed,
+ "The seed should remain the same after generating some numbers");
+
+ uint64_t saved_state = rng->get_state();
+ INFO("Current state: " << saved_state);
+
+ real_t f1_before = rng->randf();
+ real_t f2_before = rng->randf();
+ INFO("This seed produces: " << f1_before << " " << f2_before);
+
+ // Restore now.
+ rng->set_state(saved_state);
+
+ real_t f1_after = rng->randf();
+ real_t f2_after = rng->randf();
+ INFO("Resetting the state produces: " << f1_after << " " << f2_after);
+
+ String msg = "Should restore the sequence of numbers after resetting the state";
+ CHECK_MESSAGE(f1_before == f1_after, msg);
+ CHECK_MESSAGE(f2_before == f2_after, msg);
+}
+
+TEST_CASE("[RandomNumberGenerator] Restore from seed") {
+ Ref<RandomNumberGenerator> rng = memnew(RandomNumberGenerator);
+ rng->set_seed(0);
+ INFO("Current seed: " << rng->get_seed());
+ uint32_t s0_1_before = rng->randi();
+ uint32_t s0_2_before = rng->randi();
+ INFO("This seed produces: " << s0_1_before << " " << s0_2_before);
+
+ rng->set_seed(9000);
+ INFO("Current seed: " << rng->get_seed());
+ uint32_t s9000_1 = rng->randi();
+ uint32_t s9000_2 = rng->randi();
+ INFO("This seed produces: " << s9000_1 << " " << s9000_2);
+
+ rng->set_seed(0);
+ INFO("Current seed: " << rng->get_seed());
+ uint32_t s0_1_after = rng->randi();
+ uint32_t s0_2_after = rng->randi();
+ INFO("This seed produces: " << s0_1_after << " " << s0_2_after);
+
+ String msg = "Should restore the sequence of numbers after resetting the seed";
+ CHECK_MESSAGE(s0_1_before == s0_1_after, msg);
+ CHECK_MESSAGE(s0_2_before == s0_2_after, msg);
+}
+} // namespace TestRandomNumberGenerator
+
+#endif // TEST_RANDOM_NUMBER_GENERATOR_H