summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/main.cpp77
-rw-r--r--main/tests/test_class_db.cpp68
-rw-r--r--main/tests/test_math.cpp2
-rw-r--r--main/tests/test_oa_hash_map.cpp83
4 files changed, 179 insertions, 51 deletions
diff --git a/main/main.cpp b/main/main.cpp
index f35e73cdc2..94dd895a26 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -139,7 +139,6 @@ static DisplayServer::ScreenOrientation window_orientation = DisplayServer::SCRE
static uint32_t window_flags = 0;
static Size2i window_size = Size2i(1024, 600);
static bool window_vsync_via_compositor = false;
-static bool disable_wintab = false;
static int init_screen = -1;
static bool init_fullscreen = false;
@@ -313,7 +312,13 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" --enable-vsync-via-compositor When vsync is enabled, vsync via the OS' window compositor (Windows only).\n");
OS::get_singleton()->print(" --disable-vsync-via-compositor Disable vsync via the OS' window compositor (Windows only).\n");
OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n");
- OS::get_singleton()->print(" --disable-wintab Disable WinTab API and always use Windows Ink API for the pen input (Windows only).\n");
+ OS::get_singleton()->print(" --tablet-driver Tablet input driver (");
+ for (int i = 0; i < OS::get_singleton()->get_tablet_driver_count(); i++) {
+ if (i != 0)
+ OS::get_singleton()->print(", ");
+ OS::get_singleton()->print("'%s'", OS::get_singleton()->get_tablet_driver_name(i).utf8().get_data());
+ }
+ OS::get_singleton()->print(") (Windows only).\n");
OS::get_singleton()->print("\n");
#endif
@@ -438,6 +443,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
String display_driver = "";
String audio_driver = "";
+ String tablet_driver = "";
String project_path = ".";
bool upwards = false;
String debug_uri = "";
@@ -590,8 +596,26 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
} else if (I->get() == "--gpu-abort") { // force windowed window
Engine::singleton->abort_on_gpu_errors = true;
- } else if (I->get() == "--disable-wintab") {
- disable_wintab = true;
+ } else if (I->get() == "--tablet-driver") {
+ if (I->next()) {
+ tablet_driver = I->next()->get();
+ bool found = false;
+ for (int i = 0; i < OS::get_singleton()->get_tablet_driver_count(); i++) {
+ if (tablet_driver == OS::get_singleton()->get_tablet_driver_name(i)) {
+ found = true;
+ }
+ }
+
+ if (!found) {
+ OS::get_singleton()->print("Unknown tablet driver '%s', aborting.\n", tablet_driver.utf8().get_data());
+ goto error;
+ }
+
+ N = I->next()->next();
+ } else {
+ OS::get_singleton()->print("Missing tablet driver argument, aborting.\n");
+ goto error;
+ }
} else if (I->get() == "--single-window") { // force single window
single_window = true;
@@ -1056,12 +1080,20 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->_vsync_via_compositor = window_vsync_via_compositor;
- if (!disable_wintab) {
- // No "--disable_wintab" option
- disable_wintab = GLOBAL_DEF("display/window/disable_wintab_api", false);
+ if (tablet_driver == "") { // specified in project.godot
+ tablet_driver = GLOBAL_DEF_RST("display/window/tablet_driver", OS::get_singleton()->get_tablet_driver_name(0));
}
- OS::get_singleton()->_disable_wintab = disable_wintab;
+ for (int i = 0; i < OS::get_singleton()->get_tablet_driver_count(); i++) {
+ if (tablet_driver == OS::get_singleton()->get_tablet_driver_name(i)) {
+ OS::get_singleton()->set_current_tablet_driver(OS::get_singleton()->get_tablet_driver_name(i));
+ break;
+ }
+ }
+
+ if (tablet_driver == "") {
+ OS::get_singleton()->set_current_tablet_driver(OS::get_singleton()->get_tablet_driver_name(0));
+ }
/* todo restore
OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/per_pixel_transparency/allowed", false);
@@ -1175,6 +1207,7 @@ error:
display_driver = "";
audio_driver = "";
+ tablet_driver = "";
project_path = "";
args.clear();
@@ -1532,7 +1565,11 @@ bool Main::start() {
} else if (args[i].length() && args[i][0] != '-' && positional_arg == "") {
positional_arg = args[i];
- if (args[i].ends_with(".scn") || args[i].ends_with(".tscn") || args[i].ends_with(".escn")) {
+ if (args[i].ends_with(".scn") ||
+ args[i].ends_with(".tscn") ||
+ args[i].ends_with(".escn") ||
+ args[i].ends_with(".res") ||
+ args[i].ends_with(".tres")) {
// Only consider the positional argument to be a scene path if it ends with
// a file extension associated with Godot scenes. This makes it possible
// for projects to parse command-line arguments for custom CLI arguments
@@ -1608,7 +1645,11 @@ bool Main::start() {
print_line("Loading docs...");
for (int i = 0; i < _doc_data_class_path_count; i++) {
- String path = doc_tool.plus_file(_doc_data_class_paths[i].path);
+ // Custom modules are always located by absolute path.
+ String path = _doc_data_class_paths[i].path;
+ if (path.is_rel_path()) {
+ path = doc_tool.plus_file(path);
+ }
String name = _doc_data_class_paths[i].name;
doc_data_classes[name] = path;
if (!checked_paths.has(path)) {
@@ -1921,6 +1962,16 @@ bool Main::start() {
ProjectSettings::get_singleton()->set_custom_property_info("rendering/canvas_textures/default_texture_repeat", PropertyInfo(Variant::INT, "rendering/canvas_textures/default_texture_repeat", PROPERTY_HINT_ENUM, "Disable,Enable,Mirror"));
}
+#ifdef TOOLS_ENABLED
+ if (editor) {
+ bool editor_embed_subwindows = EditorSettings::get_singleton()->get_setting("interface/editor/single_window_mode");
+
+ if (editor_embed_subwindows) {
+ sml->get_root()->set_embed_subwindows_hint(true);
+ }
+ }
+#endif
+
String local_game_path;
if (game_path != "" && !project_manager) {
local_game_path = game_path.replace("\\", "/");
@@ -1954,12 +2005,6 @@ bool Main::start() {
#ifdef TOOLS_ENABLED
if (editor) {
- bool editor_embed_subwindows = EditorSettings::get_singleton()->get_setting("interface/editor/single_window_mode");
-
- if (editor_embed_subwindows) {
- sml->get_root()->set_embed_subwindows_hint(true);
- }
-
if (game_path != GLOBAL_GET("application/run/main_scene") || !editor_node->has_scenes_in_session()) {
Error serr = editor_node->load_scene(local_game_path);
if (serr != OK) {
diff --git a/main/tests/test_class_db.cpp b/main/tests/test_class_db.cpp
index 4c00a09e9c..3171091402 100644
--- a/main/tests/test_class_db.cpp
+++ b/main/tests/test_class_db.cpp
@@ -44,21 +44,21 @@ enum class [[nodiscard]] TestResult{
PASS
};
-#define TEST_FAIL_COND_FATAL(m_cond, m_msg) \
- if (unlikely(m_cond)) { \
- ERR_PRINT(m_msg); \
- return TestResult::FAILED; \
- } else \
+#define TEST_FAIL_COND(m_cond, m_msg) \
+ if (unlikely(m_cond)) { \
+ ERR_PRINT(m_msg); \
+ return TestResult::FAILED; \
+ } else \
((void)0)
-#define TEST_FAIL_COND(m_cond, m_msg) \
+#define TEST_COND(m_cond, m_msg) \
if (unlikely(m_cond)) { \
ERR_PRINT(m_msg); \
__test_result__ = TestResult::FAILED; \
} else \
((void)0)
-#define TEST_CHECK_FATAL(m_test_expr) \
+#define TEST_FAIL_CHECK(m_test_expr) \
if (unlikely((m_test_expr) == TestResult::FAILED)) { \
return TestResult::FAILED; \
} else \
@@ -229,18 +229,18 @@ struct Context {
return elem ? &elem.value() : nullptr;
}
- bool has_type(const Context &p_context, const TypeReference &p_type_ref) const {
- if (p_context.builtin_types.find(p_type_ref.name) >= 0) {
+ bool has_type(const TypeReference &p_type_ref) const {
+ if (builtin_types.find(p_type_ref.name) >= 0) {
return true;
}
if (p_type_ref.is_enum) {
- if (p_context.enum_types.find(p_type_ref.name) >= 0) {
+ if (enum_types.find(p_type_ref.name) >= 0) {
return true;
}
// Enum not found. Most likely because none of its constants were bound, so it's empty. That's fine. Use int instead.
- return p_context.builtin_types.find(p_context.names_cache.int_type);
+ return builtin_types.find(names_cache.int_type);
}
return false;
@@ -370,10 +370,10 @@ TestResult validate_property(const Context &p_context, const ExposedClass &p_cla
const ExposedClass *prop_class = p_context.find_exposed_class(prop_type_ref);
if (prop_class) {
- TEST_FAIL_COND(prop_class->is_singleton,
+ TEST_COND(prop_class->is_singleton,
"Property type is a singleton: '" + p_class.name + "." + String(p_prop.name) + "'.");
} else {
- TEST_FAIL_COND(!p_context.has_type(p_context, prop_type_ref),
+ TEST_FAIL_COND(!p_context.has_type(prop_type_ref),
"Property type '" + prop_type_ref.name + "' not found: '" + p_class.name + "." + String(p_prop.name) + "'.");
}
@@ -382,7 +382,7 @@ TestResult validate_property(const Context &p_context, const ExposedClass &p_cla
const ArgumentData &idx_arg = getter->arguments.front()->get();
if (idx_arg.type.name != p_context.names_cache.int_type) {
// If not an int, it can be an enum
- TEST_FAIL_COND(p_context.enum_types.find(idx_arg.type.name) < 0,
+ TEST_COND(p_context.enum_types.find(idx_arg.type.name) < 0,
"Invalid type '" + idx_arg.type.name + "' for index argument of property getter: '" + p_class.name + "." + String(p_prop.name) + "'.");
}
}
@@ -394,7 +394,7 @@ TestResult validate_property(const Context &p_context, const ExposedClass &p_cla
if (idx_arg.type.name != p_context.names_cache.int_type) {
// Assume the index parameter is an enum
// If not an int, it can be an enum
- TEST_FAIL_COND(p_context.enum_types.find(idx_arg.type.name) < 0,
+ TEST_COND(p_context.enum_types.find(idx_arg.type.name) < 0,
"Invalid type '" + idx_arg.type.name + "' for index argument of property setter: '" + p_class.name + "." + String(p_prop.name) + "'.");
}
}
@@ -408,7 +408,7 @@ TestResult validate_method(const Context &p_context, const ExposedClass &p_class
const ExposedClass *return_class = p_context.find_exposed_class(p_method.return_type);
if (return_class) {
- TEST_FAIL_COND(return_class->is_singleton,
+ TEST_COND(return_class->is_singleton,
"Method return type is a singleton: '" + p_class.name + "." + p_method.name + "'.");
}
@@ -417,15 +417,15 @@ TestResult validate_method(const Context &p_context, const ExposedClass &p_class
const ExposedClass *arg_class = p_context.find_exposed_class(arg.type);
if (arg_class) {
- TEST_FAIL_COND(arg_class->is_singleton,
+ TEST_COND(arg_class->is_singleton,
"Argument type is a singleton: '" + arg.name + "' of method '" + p_class.name + "." + p_method.name + "'.");
} else {
- TEST_FAIL_COND(!p_context.has_type(p_context, arg.type),
+ TEST_FAIL_COND(!p_context.has_type(arg.type),
"Argument type '" + arg.type.name + "' not found: '" + arg.name + "' of method" + p_class.name + "." + p_method.name + "'.");
}
if (arg.has_defval) {
- TEST_FAIL_COND(!arg_default_value_is_assignable_to_type(p_context, arg.defval, arg.type),
+ TEST_COND(!arg_default_value_is_assignable_to_type(p_context, arg.defval, arg.type),
"Invalid default value for parameter '" + arg.name + "' of method '" + p_class.name + "." + p_method.name + "'.");
}
}
@@ -441,10 +441,10 @@ TestResult validate_signal(const Context &p_context, const ExposedClass &p_class
const ExposedClass *arg_class = p_context.find_exposed_class(arg.type);
if (arg_class) {
- TEST_FAIL_COND(arg_class->is_singleton,
+ TEST_COND(arg_class->is_singleton,
"Argument class is a singleton: '" + arg.name + "' of signal" + p_class.name + "." + p_signal.name + "'.");
} else {
- TEST_FAIL_COND(!p_context.has_type(p_context, arg.type),
+ TEST_FAIL_COND(!p_context.has_type(arg.type),
"Argument type '" + arg.type.name + "' not found: '" + arg.name + "' of signal" + p_class.name + "." + p_signal.name + "'.");
}
}
@@ -459,20 +459,20 @@ TestResult validate_class(const Context &p_context, const ExposedClass &p_expose
if (!is_derived_type) {
// Asserts about the base Object class
- TEST_FAIL_COND_FATAL(p_exposed_class.name != p_context.names_cache.object_class,
+ TEST_FAIL_COND(p_exposed_class.name != p_context.names_cache.object_class,
"Class '" + p_exposed_class.name + "' has no base class.");
- TEST_FAIL_COND_FATAL(!p_exposed_class.is_instantiable,
+ TEST_FAIL_COND(!p_exposed_class.is_instantiable,
"Object class is not instantiable.");
- TEST_FAIL_COND_FATAL(p_exposed_class.api_type != ClassDB::API_CORE,
+ TEST_FAIL_COND(p_exposed_class.api_type != ClassDB::API_CORE,
"Object class is API is not API_CORE.");
- TEST_FAIL_COND_FATAL(p_exposed_class.is_singleton,
+ TEST_FAIL_COND(p_exposed_class.is_singleton,
"Object class is registered as a singleton.");
}
- CRASH_COND_MSG(p_exposed_class.is_singleton && p_exposed_class.base != p_context.names_cache.object_class,
+ TEST_FAIL_COND(p_exposed_class.is_singleton && p_exposed_class.base != p_context.names_cache.object_class,
"Singleton base class '" + String(p_exposed_class.base) + "' is not Object, for class '" + p_exposed_class.name + "'.");
- CRASH_COND_MSG(is_derived_type && !p_context.exposed_classes.has(p_exposed_class.base),
+ TEST_FAIL_COND(is_derived_type && !p_context.exposed_classes.has(p_exposed_class.base),
"Base type '" + p_exposed_class.base.operator String() + "' does not exist, for class '" + p_exposed_class.name + "'.");
for (const List<PropertyData>::Element *F = p_exposed_class.properties.front(); F; F = F->next()) {
@@ -619,9 +619,9 @@ TestResult add_exposed_classes(Context &r_context) {
bool bad_reference_hint = !method.is_virtual && return_info.hint != PROPERTY_HINT_RESOURCE_TYPE &&
ClassDB::is_parent_class(return_info.class_name, r_context.names_cache.reference_class);
- TEST_FAIL_COND(bad_reference_hint, String() + "Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'." +
- " Are you returning a reference type by pointer? Method: '" +
- exposed_class.name + "." + method.name + "'.");
+ TEST_COND(bad_reference_hint, String() + "Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'." +
+ " Are you returning a reference type by pointer? Method: '" +
+ exposed_class.name + "." + method.name + "'.");
} else if (return_info.hint == PROPERTY_HINT_RESOURCE_TYPE) {
method.return_type.name = return_info.hint_string;
} else if (return_info.type == Variant::NIL && return_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
@@ -670,7 +670,7 @@ TestResult add_exposed_classes(Context &r_context) {
method.arguments.push_back(vararg);
}
- TEST_FAIL_COND(exposed_class.find_property_by_name(method.name),
+ TEST_COND(exposed_class.find_property_by_name(method.name),
"Method name conflicts with property: '" + String(class_name) + "." + String(method.name) + "'.");
// Classes starting with an underscore are ignored unless they're used as a property setter or getter
@@ -851,13 +851,13 @@ TestResult run_class_db_tests() {
Context context;
- TEST_CHECK_FATAL(add_exposed_classes(context));
+ TEST_FAIL_CHECK(add_exposed_classes(context));
add_builtin_types(context);
add_global_enums(context);
const ExposedClass *object_class = context.find_exposed_class(context.names_cache.object_class);
- TEST_FAIL_COND_FATAL(!object_class, "Object class not found.");
- TEST_FAIL_COND_FATAL(object_class->base != StringName(),
+ TEST_FAIL_COND(!object_class, "Object class not found.");
+ TEST_FAIL_COND(object_class->base != StringName(),
"Object class derives from another class: '" + object_class->base + "'.");
for (ExposedClasses::Element E = context.exposed_classes.front(); E; E = E.next()) {
diff --git a/main/tests/test_math.cpp b/main/tests/test_math.cpp
index 11aa164709..9e159798bb 100644
--- a/main/tests/test_math.cpp
+++ b/main/tests/test_math.cpp
@@ -482,7 +482,7 @@ MainLoop *test() {
float gb = (rgbe >> 9) & 0x1ff;
float bb = (rgbe >> 18) & 0x1ff;
float eb = (rgbe >> 27);
- float mb = Math::pow(2, eb - 15.0 - 9.0);
+ float mb = Math::pow(2.0, eb - 15.0 - 9.0);
float rd = rb * mb;
float gd = gb * mb;
float bd = bb * mb;
diff --git a/main/tests/test_oa_hash_map.cpp b/main/tests/test_oa_hash_map.cpp
index 719817baf4..9182f66b61 100644
--- a/main/tests/test_oa_hash_map.cpp
+++ b/main/tests/test_oa_hash_map.cpp
@@ -210,6 +210,89 @@ MainLoop *test() {
}
}
+ // Test map with 0 capacity.
+ {
+ OAHashMap<int, String> original_map(0);
+ original_map.set(1, "1");
+ OS::get_singleton()->print("OAHashMap 0 capacity initialization passed.\n");
+ }
+
+ // Test copy constructor.
+ {
+ OAHashMap<int, String> original_map;
+ original_map.set(1, "1");
+ original_map.set(2, "2");
+ original_map.set(3, "3");
+ original_map.set(4, "4");
+ original_map.set(5, "5");
+
+ OAHashMap<int, String> map_copy(original_map);
+
+ bool pass = true;
+ for (
+ OAHashMap<int, String>::Iterator it = original_map.iter();
+ it.valid;
+ it = original_map.next_iter(it)) {
+ if (map_copy.lookup_ptr(*it.key) == nullptr) {
+ pass = false;
+ }
+ if (*it.value != *map_copy.lookup_ptr(*it.key)) {
+ pass = false;
+ }
+ }
+ if (pass) {
+ OS::get_singleton()->print("OAHashMap copy constructor test passed.\n");
+ } else {
+ OS::get_singleton()->print("OAHashMap copy constructor test FAILED.\n");
+ }
+
+ map_copy.set(1, "Random String");
+ if (*map_copy.lookup_ptr(1) == *original_map.lookup_ptr(1)) {
+ OS::get_singleton()->print("OAHashMap copy constructor, atomic copy test FAILED.\n");
+ } else {
+ OS::get_singleton()->print("OAHashMap copy constructor, atomic copy test passed.\n");
+ }
+ }
+
+ // Test assign operator.
+ {
+ OAHashMap<int, String> original_map;
+ original_map.set(1, "1");
+ original_map.set(2, "2");
+ original_map.set(3, "3");
+ original_map.set(4, "4");
+ original_map.set(5, "5");
+
+ OAHashMap<int, String> map_copy(100000);
+ map_copy.set(1, "Just a string.");
+ map_copy = original_map;
+
+ bool pass = true;
+ for (
+ OAHashMap<int, String>::Iterator it = map_copy.iter();
+ it.valid;
+ it = map_copy.next_iter(it)) {
+ if (original_map.lookup_ptr(*it.key) == nullptr) {
+ pass = false;
+ }
+ if (*it.value != *original_map.lookup_ptr(*it.key)) {
+ pass = false;
+ }
+ }
+ if (pass) {
+ OS::get_singleton()->print("OAHashMap assign operation test passed.\n");
+ } else {
+ OS::get_singleton()->print("OAHashMap assign operation test FAILED.\n");
+ }
+
+ map_copy.set(1, "Random String");
+ if (*map_copy.lookup_ptr(1) == *original_map.lookup_ptr(1)) {
+ OS::get_singleton()->print("OAHashMap assign operation atomic copy test FAILED.\n");
+ } else {
+ OS::get_singleton()->print("OAHashMap assign operation atomic copy test passed.\n");
+ }
+ }
+
return nullptr;
}