diff options
Diffstat (limited to 'main')
| -rw-r--r-- | main/main.cpp | 77 | ||||
| -rw-r--r-- | main/tests/test_class_db.cpp | 68 | ||||
| -rw-r--r-- | main/tests/test_math.cpp | 2 | ||||
| -rw-r--r-- | main/tests/test_oa_hash_map.cpp | 83 |
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; } |