diff --git a/example/analysis_options.yaml b/example/analysis_options.yaml new file mode 100644 index 0000000..26f7e43 --- /dev/null +++ b/example/analysis_options.yaml @@ -0,0 +1,3 @@ +analyzer: + errors: + todo: ignore diff --git a/example/android/app/src/main/res/drawable-v21/launch_background.xml b/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/example/android/app/src/main/res/values-night/styles.xml b/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..449a9f9 --- /dev/null +++ b/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/example/lib/demos/expander_fab_menu/expander_fab_menu.dart b/example/lib/demos/expander_fab_menu/expander_fab_menu.dart index bb9931a..4672c6a 100644 --- a/example/lib/demos/expander_fab_menu/expander_fab_menu.dart +++ b/example/lib/demos/expander_fab_menu/expander_fab_menu.dart @@ -21,6 +21,7 @@ class ExpanderFabMenu extends StatelessWidget { Icons.arrow_back, color: Colors.black, ), + onPressed: () {}, ), ), body: MyMenu( @@ -61,7 +62,6 @@ class _MyMenuState extends State with TickerProviderStateMixin { @override void initState() { super.initState(); - final dur = Duration(seconds: 1); // anim = AnimationController( // vsync: this, // duration: dur, @@ -173,12 +173,10 @@ class MyCoolMenuScene extends GSprite { button = MyButton(); } - GRect _position; double buttonY; GShape curtain; void updatePosition(GRect position) { - _position = position; button.x = position.x + position.width / 2; button.y = buttonY = position.y + position.height / 2; } @@ -220,7 +218,6 @@ class MyCoolMenuScene extends GSprite { } }, ); - } else { curtain.tween( duration: .5, @@ -288,22 +285,22 @@ class MyCoolMenuScene extends GSprite { doc: menuContainer, ); itm.alignPivot(); - itm.alpha=0; + itm.alpha = 0; itm.y = i * 34.0; items.add(itm); } menuContainer.alignPivot(); - menuContainer.setPosition(sw/2,sh/2); + menuContainer.setPosition(sw / 2, sh / 2); } void showMenuNow() { - var len = items.length ; + var len = items.length; for (var i = 0; i < items.length; ++i) { var itm = items[i]; itm.y = i * 34.0; - double ta = isOpen ? 1 : 0 ; - if( isOpen ){ - itm.tween(duration: .45, delay: .25 + ((len-1)-i) * .09, alpha: ta); + double ta = isOpen ? 1 : 0; + if (isOpen) { + itm.tween(duration: .45, delay: .25 + ((len - 1) - i) * .09, alpha: ta); } else { itm.tween(duration: .12, delay: 0, alpha: 0, overwrite: 1); } diff --git a/example/lib/demos/path_chart_stress/scene.dart b/example/lib/demos/path_chart_stress/scene.dart index abc4e92..cf80996 100644 --- a/example/lib/demos/path_chart_stress/scene.dart +++ b/example/lib/demos/path_chart_stress/scene.dart @@ -28,8 +28,6 @@ class PathChartScene extends GSprite { container.x = stage.stageWidth * .8; container.y = stage.stageHeight * .5; - var scaleR = 0.0; - var tw = container.x; stage.onEnterFrame.add((event) { // if (container.width > container.x + 100) { // tw = container.x + 100; @@ -87,8 +85,6 @@ class ChartSection extends GShape { stage.onEnterFrame.add((event) { if (++frameCount % 3 == 0) { addSlot(); - var maxPos = stage.stageWidth * .7; - var tempW = width; pivotX = width; // x = maxPos; // if (tempW > maxPos) { @@ -112,31 +108,6 @@ class ChartSection extends GShape { void addSlot() { ++numQuads; label.text = '$numQuads rects'; - var rects = List.generate(1, (index) { - var pw = Math.randomRange(20, 40); - var ph = Math.randomRange(20, 80); - var py = Math.randomRange( - lastRect.y - ph / 2, lastRect.y + lastRect.height / 2); - final rect = GRect(lastRect.right, py, pw, ph); - myPath = Path.combine( - PathOperation.union, - myPath, - Path()..addRect(rect.toNative()), - ); - - outputPath = myPath; - - // outputPath = Path.combine( - // PathOperation.intersect, - // outputPath, - // maskPath, - // ); - - // lastX += pw; - lastRect = rect; - return rect; - }); - graphics.clear(); graphics.beginFill(color.withOpacity(.3)); graphics.lineStyle(2, color); diff --git a/example/linux/.gitignore b/example/linux/.gitignore new file mode 100644 index 0000000..d3896c9 --- /dev/null +++ b/example/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/example/linux/CMakeLists.txt b/example/linux/CMakeLists.txt new file mode 100644 index 0000000..290c3e8 --- /dev/null +++ b/example/linux/CMakeLists.txt @@ -0,0 +1,106 @@ +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +set(BINARY_NAME "example") +set(APPLICATION_ID "com.example.example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Application build +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) +apply_standard_settings(${BINARY_NAME}) +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +add_dependencies(${BINARY_NAME} flutter_assemble) +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/example/linux/flutter/CMakeLists.txt b/example/linux/flutter/CMakeLists.txt new file mode 100644 index 0000000..a1da1b9 --- /dev/null +++ b/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,91 @@ +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) +pkg_check_modules(BLKID REQUIRED IMPORTED_TARGET blkid) +pkg_check_modules(LZMA REQUIRED IMPORTED_TARGET liblzma) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO + PkgConfig::BLKID + PkgConfig::LZMA +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + linux-x64 ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/example/linux/flutter/generated_plugin_registrant.cc b/example/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..d38195a --- /dev/null +++ b/example/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,9 @@ +// +// Generated file. Do not edit. +// + +#include "generated_plugin_registrant.h" + + +void fl_register_plugins(FlPluginRegistry* registry) { +} diff --git a/example/linux/flutter/generated_plugin_registrant.h b/example/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..9bf7478 --- /dev/null +++ b/example/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,13 @@ +// +// Generated file. Do not edit. +// + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/example/linux/flutter/generated_plugins.cmake b/example/linux/flutter/generated_plugins.cmake new file mode 100644 index 0000000..51436ae --- /dev/null +++ b/example/linux/flutter/generated_plugins.cmake @@ -0,0 +1,15 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) diff --git a/example/linux/main.cc b/example/linux/main.cc new file mode 100644 index 0000000..e7c5c54 --- /dev/null +++ b/example/linux/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/example/linux/my_application.cc b/example/linux/my_application.cc new file mode 100644 index 0000000..543eaca --- /dev/null +++ b/example/linux/my_application.cc @@ -0,0 +1,104 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen *screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } + else { + gtk_window_set_title(window, "example"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar ***arguments, int *exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject *object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + nullptr)); +} diff --git a/example/linux/my_application.h b/example/linux/my_application.h new file mode 100644 index 0000000..72271d5 --- /dev/null +++ b/example/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 10259a4..0ffa6c9 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: flutter: sdk: flutter flutter_icons: ^1.1.0 - flutter_svg: 0.18.1 + flutter_svg: ^0.21.0-nullsafety.0 graphx: path: ../ dev_dependencies: @@ -39,4 +39,4 @@ flutter: fonts: - family: pressstart fonts: - - asset: assets/fonts/pressstart.ttf \ No newline at end of file + - asset: assets/fonts/pressstart.ttf diff --git a/example/windows/.gitignore b/example/windows/.gitignore new file mode 100644 index 0000000..d492d0d --- /dev/null +++ b/example/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/example/windows/CMakeLists.txt b/example/windows/CMakeLists.txt new file mode 100644 index 0000000..abf9040 --- /dev/null +++ b/example/windows/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.15) +project(example LANGUAGES CXX) + +set(BINARY_NAME "example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/example/windows/flutter/CMakeLists.txt b/example/windows/flutter/CMakeLists.txt new file mode 100644 index 0000000..b02c548 --- /dev/null +++ b/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,103 @@ +cmake_minimum_required(VERSION 3.15) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/example/windows/flutter/generated_plugin_registrant.cc b/example/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..4bfa0f3 --- /dev/null +++ b/example/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,9 @@ +// +// Generated file. Do not edit. +// + +#include "generated_plugin_registrant.h" + + +void RegisterPlugins(flutter::PluginRegistry* registry) { +} diff --git a/example/windows/flutter/generated_plugin_registrant.h b/example/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..9846246 --- /dev/null +++ b/example/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,13 @@ +// +// Generated file. Do not edit. +// + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/example/windows/flutter/generated_plugins.cmake b/example/windows/flutter/generated_plugins.cmake new file mode 100644 index 0000000..4d10c25 --- /dev/null +++ b/example/windows/flutter/generated_plugins.cmake @@ -0,0 +1,15 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) diff --git a/example/windows/runner/CMakeLists.txt b/example/windows/runner/CMakeLists.txt new file mode 100644 index 0000000..977e38b --- /dev/null +++ b/example/windows/runner/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.15) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "run_loop.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/example/windows/runner/Runner.rc b/example/windows/runner/Runner.rc new file mode 100644 index 0000000..51812dc --- /dev/null +++ b/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#ifdef FLUTTER_BUILD_NUMBER +#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#else +#define VERSION_AS_NUMBER 1,0,0 +#endif + +#ifdef FLUTTER_BUILD_NAME +#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "A new Flutter project." "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2021 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "example.exe" "\0" + VALUE "ProductName", "example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/example/windows/runner/flutter_window.cpp b/example/windows/runner/flutter_window.cpp new file mode 100644 index 0000000..c422723 --- /dev/null +++ b/example/windows/runner/flutter_window.cpp @@ -0,0 +1,64 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(RunLoop* run_loop, + const flutter::DartProject& project) + : run_loop_(run_loop), project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opporutunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/example/windows/runner/flutter_window.h b/example/windows/runner/flutter_window.h new file mode 100644 index 0000000..b663ddd --- /dev/null +++ b/example/windows/runner/flutter_window.h @@ -0,0 +1,39 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "run_loop.h" +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow driven by the |run_loop|, hosting a + // Flutter view running |project|. + explicit FlutterWindow(RunLoop* run_loop, + const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The run loop driving events for this window. + RunLoop* run_loop_; + + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/example/windows/runner/main.cpp b/example/windows/runner/main.cpp new file mode 100644 index 0000000..b637809 --- /dev/null +++ b/example/windows/runner/main.cpp @@ -0,0 +1,42 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "run_loop.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + RunLoop run_loop; + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(&run_loop, project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + run_loop.Run(); + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/example/windows/runner/resource.h b/example/windows/runner/resource.h new file mode 100644 index 0000000..66a65d1 --- /dev/null +++ b/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/example/windows/runner/resources/app_icon.ico b/example/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000..c04e20c Binary files /dev/null and b/example/windows/runner/resources/app_icon.ico differ diff --git a/example/windows/runner/run_loop.cpp b/example/windows/runner/run_loop.cpp new file mode 100644 index 0000000..2d6636a --- /dev/null +++ b/example/windows/runner/run_loop.cpp @@ -0,0 +1,66 @@ +#include "run_loop.h" + +#include + +#include + +RunLoop::RunLoop() {} + +RunLoop::~RunLoop() {} + +void RunLoop::Run() { + bool keep_running = true; + TimePoint next_flutter_event_time = TimePoint::clock::now(); + while (keep_running) { + std::chrono::nanoseconds wait_duration = + std::max(std::chrono::nanoseconds(0), + next_flutter_event_time - TimePoint::clock::now()); + ::MsgWaitForMultipleObjects( + 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), + QS_ALLINPUT); + bool processed_events = false; + MSG message; + // All pending Windows messages must be processed; MsgWaitForMultipleObjects + // won't return again for items left in the queue after PeekMessage. + while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { + processed_events = true; + if (message.message == WM_QUIT) { + keep_running = false; + break; + } + ::TranslateMessage(&message); + ::DispatchMessage(&message); + // Allow Flutter to process messages each time a Windows message is + // processed, to prevent starvation. + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + // If the PeekMessage loop didn't run, process Flutter messages. + if (!processed_events) { + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + } +} + +void RunLoop::RegisterFlutterInstance( + flutter::FlutterEngine* flutter_instance) { + flutter_instances_.insert(flutter_instance); +} + +void RunLoop::UnregisterFlutterInstance( + flutter::FlutterEngine* flutter_instance) { + flutter_instances_.erase(flutter_instance); +} + +RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { + TimePoint next_event_time = TimePoint::max(); + for (auto instance : flutter_instances_) { + std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); + if (wait_duration != std::chrono::nanoseconds::max()) { + next_event_time = + std::min(next_event_time, TimePoint::clock::now() + wait_duration); + } + } + return next_event_time; +} diff --git a/example/windows/runner/run_loop.h b/example/windows/runner/run_loop.h new file mode 100644 index 0000000..000d362 --- /dev/null +++ b/example/windows/runner/run_loop.h @@ -0,0 +1,40 @@ +#ifndef RUNNER_RUN_LOOP_H_ +#define RUNNER_RUN_LOOP_H_ + +#include + +#include +#include + +// A runloop that will service events for Flutter instances as well +// as native messages. +class RunLoop { + public: + RunLoop(); + ~RunLoop(); + + // Prevent copying + RunLoop(RunLoop const&) = delete; + RunLoop& operator=(RunLoop const&) = delete; + + // Runs the run loop until the application quits. + void Run(); + + // Registers the given Flutter instance for event servicing. + void RegisterFlutterInstance( + flutter::FlutterEngine* flutter_instance); + + // Unregisters the given Flutter instance from event servicing. + void UnregisterFlutterInstance( + flutter::FlutterEngine* flutter_instance); + + private: + using TimePoint = std::chrono::steady_clock::time_point; + + // Processes all currently pending messages for registered Flutter instances. + TimePoint ProcessFlutterMessages(); + + std::set flutter_instances_; +}; + +#endif // RUNNER_RUN_LOOP_H_ diff --git a/example/windows/runner/runner.exe.manifest b/example/windows/runner/runner.exe.manifest new file mode 100644 index 0000000..c977c4a --- /dev/null +++ b/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/example/windows/runner/utils.cpp b/example/windows/runner/utils.cpp new file mode 100644 index 0000000..d19bdbb --- /dev/null +++ b/example/windows/runner/utils.cpp @@ -0,0 +1,64 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/example/windows/runner/utils.h b/example/windows/runner/utils.h new file mode 100644 index 0000000..3879d54 --- /dev/null +++ b/example/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/example/windows/runner/win32_window.cpp b/example/windows/runner/win32_window.cpp new file mode 100644 index 0000000..c10f08d --- /dev/null +++ b/example/windows/runner/win32_window.cpp @@ -0,0 +1,245 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/example/windows/runner/win32_window.h b/example/windows/runner/win32_window.h new file mode 100644 index 0000000..17ba431 --- /dev/null +++ b/example/windows/runner/win32_window.h @@ -0,0 +1,98 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/lib/src/core/scene_config.dart b/lib/src/core/scene_config.dart index 2f39727..fa4f497 100644 --- a/lib/src/core/scene_config.dart +++ b/lib/src/core/scene_config.dart @@ -51,17 +51,17 @@ class SceneConfig { /// re-builds the SceneController (the ScenePainter and the scene class). /// disposes and initializes all the scene. - bool rebuildOnHotReload; + bool? rebuildOnHotReload; /// If the GraphX [SceneController] will use keyboard events. - bool useKeyboard; + bool? useKeyboard; /// If this GraphX [SceneController] will use pointer (touch/mouse) events. - bool usePointer; + bool? usePointer; /// Will be overwritten to `true` if [autoUpdateAndRender] is set on any /// [ScenePainter] layer. - bool useTicker; + bool? useTicker; /// See [CustomPaint.willChange]. /// Rendering caching flag. @@ -71,7 +71,7 @@ class SceneConfig { /// All these flags overrides the value to `true`: /// [autoUpdateRender], [useTicker], [usePointer], [useKeyboard] /// - bool painterWillChange; + bool? painterWillChange; /// Avoids the scene from being disposed by the Widget. /// Meant to be used with `ScenePainter.useOwnCanvas=true` @@ -79,7 +79,7 @@ class SceneConfig { /// Picture (or Image eventually) by other [ScenePainter]s. /// Warning: Experimental /// - bool isPersistent = false; + bool? isPersistent = false; /// Default flag to make the engine update() the Stage and all /// his children (onEnterFrame), needed by [GTween] to run the tweens. @@ -91,7 +91,7 @@ class SceneConfig { /// And, unless you don't need external control over the rendering & update /// pipelines for the scene, or if you use a static scene, /// you should leave it as `true`. - bool autoUpdateRender = true; + bool? autoUpdateRender = true; SceneConfig({ this.rebuildOnHotReload = true, @@ -102,14 +102,19 @@ class SceneConfig { this.autoUpdateRender = true, this.painterWillChange, }) { - if (autoUpdateRender) useTicker = true; + if (autoUpdateRender ?? false) useTicker = true; } /// Utility method used by the [SceneBuilderWidget] to set the flag /// `CustomPaint.willChange` /// bool painterMightChange() { - if (useTicker || autoUpdateRender || usePointer || useKeyboard) return true; + if ((useTicker ?? false) || + (autoUpdateRender ?? false) || + (usePointer ?? false) || + (useKeyboard ?? false)) { + return true; + } return painterWillChange ?? false; } } diff --git a/lib/src/core/scene_controller.dart b/lib/src/core/scene_controller.dart index 1489392..8271623 100644 --- a/lib/src/core/scene_controller.dart +++ b/lib/src/core/scene_controller.dart @@ -19,14 +19,14 @@ class SceneController { /// `stage.onHotReload.add((){ /// // your logic here /// });` - Signal _onHotReload; + Signal? _onHotReload; Signal get onHotReload => _onHotReload ??= Signal(); - ScenePainter backScene, frontScene; + ScenePainter? backScene, frontScene; /// Access the `ticker` (if any) created by this SceneController. - GTicker get ticker { + GTicker? get ticker { if (_ticker == null) { throw 'You need to enable ticker usage with ' 'SceneBuilderWidget( useTicker=true ) or ' @@ -38,19 +38,19 @@ class SceneController { /// Access the keyboard manager instance associated with this /// [SceneController]. - KeyboardManager get keyboard => _keyboard; + KeyboardManager? get keyboard => _keyboard; /// Access the pointer manager instance associated with this /// [SceneController]. - PointerManager get pointer => _pointer; + PointerManager? get pointer => _pointer; - KeyboardManager _keyboard; + KeyboardManager? _keyboard; - PointerManager _pointer; + PointerManager? _pointer; - GTicker _ticker; + GTicker? _ticker; - InputConverter $inputConverter; + InputConverter? $inputConverter; SceneConfig get config => _config; @@ -58,7 +58,7 @@ class SceneController { /// gets widget's global coordinates. /// useful to compute interactions with children Widgets that gets - GRect Function() resolveWindowBounds; + GRect? Function()? resolveWindowBounds; int id = -1; @@ -76,9 +76,9 @@ class SceneController { /// constructor. SceneController({ - GSprite back, - GSprite front, - SceneConfig config, + GSprite? back, + GSprite? front, + SceneConfig? config, }) { assert(back != null || front != null); if (back != null) { @@ -99,9 +99,9 @@ class SceneController { setup(); if (_hasTicker()) { _ticker = GTicker(); - _ticker.onFrame.add(_onTick); + _ticker!.onFrame.add(_onTick); if (_anySceneAutoUpdate()) { - _ticker.resume(); + _ticker!.resume(); } } _initInput(); @@ -129,7 +129,7 @@ class SceneController { } void dispose() { - if (_config.isPersistent) { + if (_config.isPersistent ?? false) { return; } _onHotReload?.removeAll(); @@ -140,25 +140,25 @@ class SceneController { _isInited = false; } - CustomPainter buildBackPainter() => backScene?.buildPainter(); + CustomPainter? buildBackPainter() => backScene?.buildPainter(); - CustomPainter buildFrontPainter() => frontScene?.buildPainter(); + CustomPainter? buildFrontPainter() => frontScene?.buildPainter(); void _initInput() { - if (_config.useKeyboard) { + if (_config.useKeyboard ?? false) { _keyboard ??= KeyboardManager(); } - if (_config.usePointer) { + if (_config.usePointer ?? false) { _pointer ??= PointerManager(); } - if (_config.useKeyboard || _config.usePointer) { + if (_config.useKeyboard ?? false || (_config.usePointer ?? false)) { $inputConverter ??= InputConverter(_pointer, _keyboard); } } void reassembleWidget() { _onHotReload?.dispatch(); - if (_config.rebuildOnHotReload) { + if (_config.rebuildOnHotReload ?? false) { GTween.hotReload(); dispose(); @@ -167,11 +167,11 @@ class SceneController { } } - bool _sceneAutoUpdate(ScenePainter scene) => + bool _sceneAutoUpdate(ScenePainter? scene) => scene?.autoUpdateAndRender ?? false; bool _anySceneAutoUpdate() => _sceneAutoUpdate(backScene) || _sceneAutoUpdate(frontScene); - bool _hasTicker() => _anySceneAutoUpdate() || _config.useTicker; + bool _hasTicker() => _anySceneAutoUpdate() || (_config.useTicker ?? false); } diff --git a/lib/src/core/scene_painter.dart b/lib/src/core/scene_painter.dart index 1dbe1be..caa4412 100644 --- a/lib/src/core/scene_painter.dart +++ b/lib/src/core/scene_painter.dart @@ -7,7 +7,7 @@ import '../../graphx.dart'; class ScenePainter with EventDispatcherMixin { /// Current painter being processed. - static ScenePainter current; + static late ScenePainter current; /// access to SceneController defined in the Widget side. SceneController core; @@ -26,16 +26,16 @@ class ScenePainter with EventDispatcherMixin { /// Warning: Experimental state bool useOwnCanvas = false; bool _ownCanvasNeedsRepaint = false; - Canvas $canvas; + Canvas? $canvas; /// Size of the area available in `CustomPainter::paint()` Size size = Size.zero; /// Scene Layer's stage. The very first DisplayObject where the render /// display list starts. - Stage _stage; + Stage? _stage; - Stage get stage => _stage; + Stage? get stage => _stage; /// Defines when the Scene is ready and stage is accessible to GraphX root. /// Runs on the first "render". @@ -56,17 +56,17 @@ class ScenePainter with EventDispatcherMixin { /// Ticker callback, to access the current frame delta timestamp /// (in millisecond). - EventSignal _onUpdate; + EventSignal? _onUpdate; EventSignal get onUpdate => _onUpdate ??= EventSignal(); - ui.Picture _canvasPicture; + ui.Picture? _canvasPicture; var _mouseMoveInputDetected = false; var _lastMouseX = -1000000.0; var _lastMouseY = -1000000.0; var _lastMouseOut = false; - MouseInputData _lastMouseInput; + MouseInputData? _lastMouseInput; /// constructor. ScenePainter(this.core, this.root) { @@ -81,32 +81,33 @@ class ScenePainter with EventDispatcherMixin { void _paint(Canvas canvas, Size size) { if (this.size != size) { this.size = size; - _stage.$initFrameSize(size); + _stage!.$initFrameSize(size); } $canvas = canvas; if (!_isReady) { _isReady = true; _initMouseInput(); - _stage.addChild(root); + _stage!.addChild(root); _stage?.$onResized?.dispatch(); } if (useOwnCanvas) { _pictureFromCanvas(); } else { - _stage.paint($canvas); + _stage!.paint($canvas); } } void $setup() { makeCurrent(); + /// If needed, can be overridden later by the [root]. - autoUpdateAndRender = core.config.autoUpdateRender; + autoUpdateAndRender = core.config.autoUpdateRender ?? false; } void _createPicture() { final _recorder = ui.PictureRecorder(); final _canvas = Canvas(_recorder); - _stage.paint(_canvas); + _stage!.paint(_canvas); _canvasPicture = _recorder.endRecording(); } @@ -115,7 +116,7 @@ class ScenePainter with EventDispatcherMixin { /// Manages the `update()` and can request to redraw the CustomPainter. void tick(double time) { makeCurrent(); - if (autoUpdateAndRender || time != null) { + if (autoUpdateAndRender) { $currentFrameId++; $runTime += time; $update(time); @@ -134,7 +135,7 @@ class ScenePainter with EventDispatcherMixin { } $currentFrameDeltaTime = deltaTime; $accumulatedFrameDeltaTime += $currentFrameDeltaTime; - _stage.$tick(deltaTime); + _stage!.$tick(deltaTime); if (_hasPointer) { _detectMouseMove(); } @@ -153,9 +154,9 @@ class ScenePainter with EventDispatcherMixin { input.stagePosition.setTo(_lastMouseX, _lastMouseY); input.mouseOut = _lastMouseOut; if (_lastMouseInput != null) { - input.buttonDown = _lastMouseInput.buttonDown; - input.rawEvent = _lastMouseInput.rawEvent; - input.buttonsFlags = _lastMouseInput.buttonsFlags; + input.buttonDown = _lastMouseInput!.buttonDown; + input.rawEvent = _lastMouseInput!.rawEvent; + input.buttonsFlags = _lastMouseInput!.buttonsFlags; } _mouseInputHandler(input); } @@ -181,7 +182,7 @@ class ScenePainter with EventDispatcherMixin { } _lastMouseInput = input; - stage.captureMouseInput(input); + stage!.captureMouseInput(input); } /// Requests a new frame. @@ -200,7 +201,7 @@ class ScenePainter with EventDispatcherMixin { } void _initMouseInput() { - core?.pointer?.onInput?.add(_onInputHandler); + core.pointer?.onInput.add(_onInputHandler); } void _onInputHandler(PointerEventData e) { @@ -232,7 +233,7 @@ class ScenePainter with EventDispatcherMixin { _createPicture(); } if (_canvasPicture != null) { - $canvas.drawPicture(_canvasPicture); + $canvas!.drawPicture(_canvasPicture!); } } @@ -241,13 +242,13 @@ class ScenePainter with EventDispatcherMixin { _isReady = false; size = Size.zero; _stage?.dispose(); - core?.pointer?.onInput?.remove(_onInputHandler); + core.pointer?.onInput.remove(_onInputHandler); _onUpdate?.removeAll(); _onUpdate = null; super.dispose(); } - bool get _hasPointer => core?.pointer?.onInput != null; + bool get _hasPointer => core.pointer?.onInput != null; bool shouldRepaint() => needsRepaint; } diff --git a/lib/src/debug/display_debugger.dart b/lib/src/debug/display_debugger.dart index 9b01fb9..b22ee0d 100644 --- a/lib/src/debug/display_debugger.dart +++ b/lib/src/debug/display_debugger.dart @@ -30,7 +30,7 @@ class DisplayBoundsDebugger { ..strokeWidth = 1; final GDisplayObjectContainer _root; - ui.Canvas canvas; + ui.Canvas? canvas; static final GRect _sHelpRect = GRect(); DisplayBoundsDebugger(GDisplayObjectContainer root) : _root = root; @@ -59,8 +59,8 @@ class DisplayBoundsDebugger { final linePaint = _paint.clone(); linePaint.color = linePaint.color.withOpacity(.3); final rect = _sHelpRect.toNative(); - canvas.drawLine(rect.topLeft, rect.bottomRight, linePaint); - canvas.drawLine(rect.topRight, rect.bottomLeft, linePaint); - canvas.drawRect(rect, _paint); + canvas!.drawLine(rect.topLeft, rect.bottomRight, linePaint); + canvas!.drawLine(rect.topRight, rect.bottomLeft, linePaint); + canvas!.drawRect(rect, _paint); } } diff --git a/lib/src/display/bitmap.dart b/lib/src/display/bitmap.dart index ddad535..4f2a6bf 100644 --- a/lib/src/display/bitmap.dart +++ b/lib/src/display/bitmap.dart @@ -11,12 +11,13 @@ class GBitmap extends GDisplayObject { return '$runtimeType (Bitmap2)$msg'; } - GTexture _texture; - GTexture get texture => _texture; + GTexture? _texture; + GTexture? get texture => _texture; double $originalPivotX = 0, $originalPivotY = 0; + /// TODO: improve this process, make bounds work properly. - bool _hasScale9Grid; - double _buffScaleX, _buffScaleY; + late bool _hasScale9Grid; + double _buffScaleX = 0.0, _buffScaleY = 0.0; final GRect _cachedBounds = GRect(); final _paint = ui.Paint()..filterQuality = ui.FilterQuality.medium; ui.Paint get nativePaint => _paint; @@ -33,28 +34,28 @@ class GBitmap extends GDisplayObject { super.pivotY = value; } - set texture(GTexture value) { + set texture(GTexture? value) { if (_texture == value) return; _texture = value; if (_texture != null) { - pivotX = -_texture.pivotX + $originalPivotX; - pivotY = -_texture.pivotY + $originalPivotY; + pivotX = -_texture!.pivotX! + $originalPivotX; + pivotY = -_texture!.pivotY! + $originalPivotY; } requiresRedraw(); } - GBitmap([GTexture texture]) { + GBitmap([GTexture? texture]) { this.texture = texture; } @override - GRect getBounds(GDisplayObject targetSpace, [GRect out]) { + GRect getBounds(GDisplayObject? targetSpace, [GRect? out]) { out ??= GRect(); final matrix = _sHelperMatrix; matrix.identity(); getTransformationMatrix(targetSpace, matrix); if (texture != null) { - var rect = texture.getBounds(); + var rect = texture!.getBounds()!; out = MatrixUtils.getTransformedBoundsRect( matrix, rect, @@ -74,15 +75,15 @@ class GBitmap extends GDisplayObject { } @override - set colorize(ui.Color value) { + set colorize(ui.Color? value) { if ($colorize == value) return; super.colorize = value; _paint.colorFilter = - $hasColorize ? PainterUtils.getColorize($colorize) : null; + $hasColorize ? PainterUtils.getColorize($colorize!) : null; } @override - set filters(List value) { + set filters(List? value) { if ($filters == value) return; $filters = value; if ($filters == null) { @@ -92,9 +93,9 @@ class GBitmap extends GDisplayObject { } @override - void paint(ui.Canvas canvas) { + void paint(ui.Canvas? canvas) { if (texture == null) return; - _hasScale9Grid = texture.scale9Grid != null; + _hasScale9Grid = texture!.scale9Grid != null; if (_hasScale9Grid) { _adjustScaleGrid(); } @@ -102,9 +103,9 @@ class GBitmap extends GDisplayObject { } @override - void $applyPaint(ui.Canvas canvas) { + void $applyPaint(ui.Canvas? canvas) { if (hasFilters) { - for( var filter in filters ){ + for (var filter in filters!) { filter.update(); filter.resolvePaint(_paint); } @@ -119,9 +120,9 @@ class GBitmap extends GDisplayObject { super.pivotX = $originalPivotX * _buffScaleX; super.pivotY = $originalPivotY * _buffScaleY; _cachedBounds.x = _cachedBounds.y = 0; - _cachedBounds.width = texture.width * _buffScaleX; - _cachedBounds.height = texture.height * _buffScaleY; - texture.scale9GridDest = _cachedBounds; + _cachedBounds.width = texture!.width! * _buffScaleX; + _cachedBounds.height = texture!.height! * _buffScaleY; + texture!.scale9GridDest = _cachedBounds; setScale(1, 1); } } diff --git a/lib/src/display/display_object.dart b/lib/src/display/display_object.dart index f0bfbaf..0831b3e 100644 --- a/lib/src/display/display_object.dart +++ b/lib/src/display/display_object.dart @@ -9,10 +9,10 @@ abstract class GDisplayObject RenderSignalMixin, MouseSignalsMixin, DisplayMasking { - GDisplayObjectContainer $parent; - static GDisplayObject $currentDrag; - static GRect $currentDragBounds; - GPoint _dragCenterOffset; + GDisplayObjectContainer? $parent; + static GDisplayObject? $currentDrag; + static GRect? $currentDragBounds; + late GPoint _dragCenterOffset; /// Lets the user drag the specified sprite. /// The sprite remains draggable until explicitly stopped through a call to @@ -23,7 +23,7 @@ abstract class GDisplayObject /// the user first clicked the sprite (false). /// [bounds] Value relative to the coordinates of the Sprite's parent that /// specify a constraint rectangle for the Sprite. - void startDrag([bool lockCenter = false, GRect bounds]) { + void startDrag([bool lockCenter = false, GRect? bounds]) { if (!inStage || !$hasTouchableArea) { throw 'to drag an object, it has to be visible and enabled in the stage.'; } @@ -33,9 +33,9 @@ abstract class GDisplayObject $currentDragBounds = bounds; _dragCenterOffset = GPoint(); if (lockCenter) { - _dragCenterOffset.setTo(x - parent.mouseX, y - parent.mouseY); + _dragCenterOffset.setTo(x - parent!.mouseX, y - parent!.mouseY); } - stage.onMouseMove.add(_handleDrag); + stage!.onMouseMove.add(_handleDrag); } // DisplayObject get dropTarget { @@ -50,14 +50,14 @@ abstract class GDisplayObject void _handleDrag(MouseInputData input) { if (this != $currentDrag) { - stage?.onMouseMove?.remove(_handleDrag); + stage?.onMouseMove.remove(_handleDrag); } if ($currentDrag == null) { $currentDragBounds = null; return; } - var tx = $currentDrag.parent.mouseX + _dragCenterOffset.x; - var ty = $currentDrag.parent.mouseY + _dragCenterOffset.y; + var tx = $currentDrag!.parent!.mouseX + _dragCenterOffset.x; + var ty = $currentDrag!.parent!.mouseY + _dragCenterOffset.y; final rect = $currentDragBounds; if (rect != null) { tx = tx.clamp(rect.left, rect.right); @@ -68,7 +68,7 @@ abstract class GDisplayObject void stopDrag() { if (this == $currentDrag) { - stage.onMouseMove.remove(_handleDrag); + stage!.onMouseMove.remove(_handleDrag); $currentDrag = null; } } @@ -76,26 +76,26 @@ abstract class GDisplayObject bool $debugBounds = false; bool mouseUseShape = false; - List $filters; + List? $filters; - List get filters => $filters; + List? get filters => $filters; - set filters(List value) => $filters = value; + set filters(List? value) => $filters = value; - GDisplayObject $mouseDownObj; - GDisplayObject $mouseOverObj; + GDisplayObject? $mouseDownObj; + GDisplayObject? $mouseOverObj; double $lastClickTime = -1; bool useCursor = false; - ui.Color $colorize = kColorTransparent; + ui.Color? $colorize = kColorTransparent; - bool get $hasColorize => $colorize != null && $colorize.alpha > 0; + bool get $hasColorize => $colorize != null && $colorize!.alpha > 0; - ui.Color get colorize => $colorize; + ui.Color? get colorize => $colorize; - set colorize(ui.Color value) { + set colorize(ui.Color? value) { if ($colorize == value) return; $colorize = value; requiresRedraw(); @@ -127,7 +127,7 @@ abstract class GDisplayObject } void $dispatchMouseCallback( - MouseInputType type, + MouseInputType? type, GDisplayObject object, MouseInputData input, ) { @@ -198,7 +198,7 @@ abstract class GDisplayObject double get mouseX { if (inStage) { - return globalToLocal(_sHelperPoint.setTo(stage.pointer.mouseX, 0)).x; + return globalToLocal(_sHelperPoint.setTo(stage!.pointer!.mouseX, 0)).x; } else { throw 'To get mouseX object needs to be a descendant of Stage.'; } @@ -206,7 +206,7 @@ abstract class GDisplayObject double get mouseY { if (inStage) { - return globalToLocal(_sHelperPoint.setTo(0, stage.pointer.mouseY)).y; + return globalToLocal(_sHelperPoint.setTo(0, stage!.pointer!.mouseY)).y; } else { throw 'To get mouseY object needs to be a descendant of Stage.'; } @@ -217,14 +217,14 @@ abstract class GDisplayObject throw 'To get mousePosition, the object needs to be in the Stage.'; } return globalToLocal(_sHelperPoint.setTo( - stage.pointer.mouseX, - stage.pointer.mouseY, + stage!.pointer!.mouseX, + stage!.pointer!.mouseY, )); } /// You can store any user defined data in this property for easy access. - Object userData; - String name; + Object? userData; + String? name; double _x = 0, _y = 0, _scaleX = 1, _scaleY = 1, _rotation = 0; double _pivotX = 0, _pivotY = 0; @@ -270,7 +270,7 @@ abstract class GDisplayObject /// ``` /// A display object with no content (such as an empty sprite) has a width /// of 0, even if you try to set width to a different value. - double get width => getBounds($parent, _sHelperRect).width; + double get width => getBounds($parent, _sHelperRect)!.width; /// Indicates the height of the display object, in dp. /// The `height` is calculated based on the bounds of the content of the @@ -287,11 +287,11 @@ abstract class GDisplayObject /// ``` /// A display object with no content (such as an empty sprite) has a height /// of 0, even if you try to set height to a different value. - double get height => getBounds($parent, _sHelperRect).height; + double get height => getBounds($parent, _sHelperRect)!.height; - set width(double value) { + set width(double? value) { if (value == null) throw 'width can not be null'; - double actualW; + double? actualW; var zeroScale = _scaleX < 1e-8 && _scaleX > -1e-8; if (zeroScale) { scaleX = 1.0; @@ -299,12 +299,12 @@ abstract class GDisplayObject } else { actualW = (width / _scaleX).abs(); } - if (actualW != null) scaleX = value / actualW; + scaleX = value / actualW; } - set height(double value) { + set height(double? value) { if (value == null) throw 'height can not be null'; - double actualH; + double? actualH; var zeroScale = _scaleY < 1e-8 && _scaleY > -1e-8; if (zeroScale) { scaleY = 1.0; @@ -312,31 +312,31 @@ abstract class GDisplayObject } else { actualH = (height / _scaleY).abs(); } - if (actualH != null) scaleY = value / actualH; + scaleY = value / actualH; } - set x(double value) { + set x(double? value) { if (value == null) throw 'x can not be null'; if (_x == value) return; _x = value; $setTransformationChanged(); } - set y(double value) { + set y(double? value) { if (value == null) throw 'y can not be null'; if (_y == value) return; _y = value; $setTransformationChanged(); } - set scaleX(double value) { + set scaleX(double? value) { if (value == null) throw 'scaleX can not be null'; if (_scaleX == value) return; _scaleX = value; $setTransformationChanged(); } - set scaleY(double value) { + set scaleY(double? value) { if (value == null) throw 'scaleY can not be null'; if (_scaleY == value) return; _scaleY = value; @@ -345,31 +345,29 @@ abstract class GDisplayObject set pivotX(double value) { if (_pivotX == value) return; - _pivotX = value ?? 0.0; + _pivotX = value; $setTransformationChanged(); } set pivotY(double value) { if (_pivotY == value) return; - _pivotY = value ?? 0.0; + _pivotY = value; $setTransformationChanged(); } set skewX(double value) { - if (value == null) throw 'skewX can not be null'; if (_skewX == value) return; _skewX = value; $setTransformationChanged(); } set skewY(double value) { - if (value == null) throw 'skewY can not be null'; if (_skewY == value) return; _skewY = value; $setTransformationChanged(); } - set rotation(double value) { + set rotation(double? value) { if (value == null) throw 'rotation can not be null'; if (_rotation == value) return; _rotation = value; @@ -377,11 +375,8 @@ abstract class GDisplayObject } set rotationX(double value) { - if (value == null) { - throw 'rotationX can not be null'; - } if (_rotationX == value) return; - _rotationX = value ?? 0.0; + _rotationX = value; if (!_isWarned3d) _warn3d(); $setTransformationChanged(); } @@ -394,21 +389,15 @@ abstract class GDisplayObject } set rotationY(double value) { - if (value == null) { - throw 'rotationY can not be null'; - } if (_rotationY == value) return; - _rotationY = value ?? 0.0; + _rotationY = value; if (!_isWarned3d) _warn3d(); $setTransformationChanged(); } set z(double value) { - if (value == null) { - throw 'z can not be null'; - } if (_z == value) return; - _z = value ?? 0.0; + _z = value; if (!_isWarned3d) _warn3d(); $setTransformationChanged(); } @@ -418,11 +407,8 @@ abstract class GDisplayObject double get alpha => $alpha; set alpha(double value) { - if (value == null) { - throw 'alpha can not be null'; - } if ($alpha != value) { - value ??= 1; + // value ??= 1; $alpha = value.clamp(0.0, 1.0); requiresRedraw(); } @@ -433,8 +419,8 @@ abstract class GDisplayObject bool $matrixDirty = true; bool mouseEnabled = true; - GDisplayObject $maskee; - GShape $mask; + GDisplayObject? $maskee; + GShape? $mask; /// optimization. bool $hasTouchableArea = true; @@ -442,14 +428,14 @@ abstract class GDisplayObject bool get isMask => $maskee != null; - GShape get mask => $mask; + GShape? get mask => $mask; /// can be set on the Shape mask, or the maskee DisplayObject. bool maskInverted = false; - set mask(GShape value) { + set mask(GShape? value) { if ($mask != value) { - if ($mask != null) $mask.$maskee = null; + if ($mask != null) $mask!.$maskee = null; value?.$maskee = this; value?.$hasVisibleArea = false; $mask = value; @@ -512,7 +498,7 @@ abstract class GDisplayObject } void alignPivot([painting.Alignment alignment = painting.Alignment.center]) { - var bounds = getBounds(this, _sHelperRect); + var bounds = getBounds(this, _sHelperRect)!; if (bounds.isEmpty) return; var ax = 0.5 + alignment.x / 2; var ay = 0.5 + alignment.y / 2; @@ -522,24 +508,24 @@ abstract class GDisplayObject /// local bounds /// todo: should be cached. - GRect get bounds => getBounds(this); + GRect? get bounds => getBounds(this); - GRect getBounds(GDisplayObject targetSpace, [GRect out]) { + GRect? getBounds(GDisplayObject? targetSpace, [GRect? out]) { throw 'getBounds() is abstract in DisplayObject'; } - GPoint globalToLocal(GPoint globalPoint, [GPoint out]) { + GPoint globalToLocal(GPoint globalPoint, [GPoint? out]) { getTransformationMatrix(base, _sHelperMatrixAlt); _sHelperMatrixAlt.invert(); return _sHelperMatrixAlt.transformPoint(globalPoint, out); } - GPoint localToGlobal(GPoint localPoint, [GPoint out]) { + GPoint localToGlobal(GPoint localPoint, [GPoint? out]) { getTransformationMatrix(base, _sHelperMatrixAlt); return _sHelperMatrixAlt.transformPoint(localPoint, out); } - GMatrix _transformationMatrix; + GMatrix? _transformationMatrix; GMatrix get transformationMatrix { if (_transformationChanged || _transformationMatrix == null) { @@ -566,10 +552,10 @@ abstract class GDisplayObject skewX, skewY, rotation, - _transformationMatrix, + _transformationMatrix!, ); } - return _transformationMatrix; + return _transformationMatrix!; } set transformationMatrix(GMatrix matrix) { @@ -577,7 +563,7 @@ abstract class GDisplayObject requiresRedraw(); _transformationChanged = false; _transformationMatrix ??= GMatrix(); - _transformationMatrix.copyFrom(matrix); + _transformationMatrix!.copyFrom(matrix); _pivotX = _pivotY = 0; _x = matrix.tx; _y = matrix.ty; @@ -598,8 +584,8 @@ abstract class GDisplayObject } void $updateTransformationMatrices( - double x, - double y, + double? x, + double? y, double pivotX, double pivotY, double scaleX, @@ -618,8 +604,8 @@ abstract class GDisplayObject 0, 0, scaleY, - x - pivotX * scaleX, - y - pivotY * scaleY, + x! - pivotX * scaleX, + y! - pivotY * scaleY, ); } else { final cos = Math.cos(rotation); @@ -628,8 +614,8 @@ abstract class GDisplayObject final b = scaleX * sin; final c = scaleY * -sin; final d = scaleY * cos; - final tx = x - pivotX * a - pivotY * c; - final ty = y - pivotX * b - pivotY * d; + final tx = x! - pivotX * a - pivotY * c; + final ty = y! - pivotX * b - pivotY * d; out.setTo(a, b, c, d, tx, ty); } } else { @@ -637,7 +623,7 @@ abstract class GDisplayObject out.scale(scaleX, scaleY); out.skew(skewX, skewY); // MatrixUtils.skew(out, skewX, skewY); out.rotate(rotation); - out.translate(x, y); + out.translate(x!, y!); if (pivotX != 0 || pivotY != 0) { out.tx = x - out.a * pivotX - out.c * pivotY; out.ty = y - out.b * pivotX - out.d * pivotY; @@ -645,8 +631,8 @@ abstract class GDisplayObject } } - GMatrix getTransformationMatrix(GDisplayObject targetSpace, [GMatrix out]) { - GDisplayObject commonParent, currentObj; + GMatrix getTransformationMatrix(GDisplayObject? targetSpace, [GMatrix? out]) { + GDisplayObject? commonParent, currentObj; out?.identity(); out ??= GMatrix(); if (targetSpace == this) { @@ -659,7 +645,7 @@ abstract class GDisplayObject if (targetSpace == null || targetSpace == base) { currentObj = this; while (currentObj != targetSpace) { - out.concat(currentObj.transformationMatrix); + out.concat(currentObj!.transformationMatrix); currentObj = currentObj.$parent; } return out; @@ -677,7 +663,7 @@ abstract class GDisplayObject /// 2 - move up from this to common parent.```` currentObj = this; while (currentObj != commonParent) { - out.concat(currentObj.transformationMatrix); + out.concat(currentObj!.transformationMatrix); currentObj = currentObj.$parent; } @@ -687,7 +673,7 @@ abstract class GDisplayObject _sHelperMatrix.identity(); currentObj = targetSpace; while (currentObj != commonParent) { - _sHelperMatrix.concat(currentObj.transformationMatrix); + _sHelperMatrix.concat(currentObj!.transformationMatrix); currentObj = currentObj.$parent; } @@ -699,7 +685,7 @@ abstract class GDisplayObject static GDisplayObject _findCommonParent( GDisplayObject obj1, GDisplayObject obj2) { - var current = obj1; + GDisplayObject? current = obj1; /// TODO: use faster Hash access. while (current != null) { @@ -720,20 +706,20 @@ abstract class GDisplayObject return true; } if (maskRect != null) { - final isHit = maskRect.containsPoint(localPoint); + final isHit = maskRect!.containsPoint(localPoint); return maskRectInverted ? !isHit : isHit; } - if ($mask.inStage) { + if ($mask!.inStage) { getTransformationMatrix($mask, _sHelperMatrixAlt); } else { - _sHelperMatrixAlt.copyFrom($mask.transformationMatrix); + _sHelperMatrixAlt.copyFrom($mask!.transformationMatrix); _sHelperMatrixAlt.invert(); } var helperPoint = localPoint == _sHelperPoint ? GPoint() : _sHelperPoint; _sHelperMatrixAlt.transformPoint(localPoint, helperPoint); - final isHit = mask.hitTest(helperPoint) != null; + final isHit = mask!.hitTest(helperPoint) != null; // return maskInverted ? !isHit : isHit; return maskInverted ? !isHit : isHit; } @@ -743,38 +729,38 @@ abstract class GDisplayObject } /// `useShape` is meant to be used by `Shape.graphics`. - GDisplayObject hitTest(GPoint localPoint, [bool useShape = false]) { + GDisplayObject? hitTest(GPoint localPoint, [bool useShape = false]) { if (!$hasTouchableArea || !mouseEnabled) { return null; } if (($mask != null || maskRect != null) && !hitTestMask(localPoint)) { return null; } - if (getBounds(this, _sHelperRect).containsPoint(localPoint)) { + if (getBounds(this, _sHelperRect)!.containsPoint(localPoint)) { return this; } return null; } - GDisplayObjectContainer get parent => $parent; + GDisplayObjectContainer? get parent => $parent; GDisplayObject get base { var current = this; while (current.$parent != null) { - current = current.$parent; + current = current.$parent!; } return current; } bool get inStage => base is Stage; - Stage get stage => base is Stage ? base : null; + Stage? get stage => base is Stage ? base as Stage? : null; - GDisplayObject get root { + GDisplayObject? get root { var current = this; while (current.$parent != null) { if (current.$parent is Stage) return current; - current = current.$parent; + current = current.$parent!; } return null; } @@ -800,7 +786,7 @@ abstract class GDisplayObject void update(double delta) {} bool get hasFilters => filters?.isNotEmpty ?? false; - GRect $debugLastLayerBounds; + GRect? $debugLastLayerBounds; /// quick and dirty way to toggle saveLayer() feature for common /// display objects as well. @@ -808,14 +794,14 @@ abstract class GDisplayObject /// Paint() so no need to use an expensive saveLayer(). bool allowSaveLayer = false; - GRect getFilterBounds([GRect layerBounds, ui.Paint alphaPaint]) { + GRect? getFilterBounds([GRect? layerBounds, ui.Paint? alphaPaint]) { layerBounds ??= getBounds($parent); - if ($filters == null || $filters.isEmpty) { + if ($filters == null || $filters!.isEmpty) { return layerBounds; } - layerBounds = layerBounds.clone(); - GRect resultBounds; - for (var filter in $filters) { + layerBounds = layerBounds!.clone(); + GRect? resultBounds; + for (var filter in $filters!) { resultBounds ??= layerBounds.clone(); if (alphaPaint != null) { filter.update(); @@ -837,7 +823,7 @@ abstract class GDisplayObject /// Do not override this method as it applies the basic /// transformations. Override $applyPaint() if you wanna use /// `Canvas` directly. - void paint(ui.Canvas canvas) { + void paint(ui.Canvas? canvas) { if (!$hasVisibleArea || !visible) { return; } @@ -868,13 +854,13 @@ abstract class GDisplayObject DisplayBoundsDebugger.debugBoundsMode == DebugBoundsMode.internal && ($debugBounds || DisplayBoundsDebugger.debugAll); - GRect _cacheLocalBoundsRect; + GRect? _cacheLocalBoundsRect; if (showDebugBounds || _saveLayer) { // _cacheLocalBoundsRect = bounds.toNative(); _cacheLocalBoundsRect = bounds; } - List _composerFilters; + List? _composerFilters; var filterHidesObject = false; if (_saveLayer) { // TODO: static painter seems to have some issues, try local var later. @@ -890,18 +876,18 @@ abstract class GDisplayObject alphaPaint.maskFilter = null; if ($hasColorize) { alphaPaint.colorFilter = ui.ColorFilter.mode( - $colorize, + $colorize!, ui.BlendMode.srcATop, ); } - ui.Rect nativeLayerBounds; + ui.Rect? nativeLayerBounds; var layerBounds = getBounds($parent); if ($hasFilters) { /// TODO: Find a common implementation for filter bounds. // layerBounds = getFilterBounds(layerBounds, alphaPaint); - layerBounds = layerBounds.clone(); - GRect resultBounds; - for (var filter in $filters) { + layerBounds = layerBounds!.clone(); + GRect? resultBounds; + for (var filter in $filters!) { resultBounds ??= layerBounds.clone(); filter.update(); filter.expandBounds(layerBounds, resultBounds); @@ -917,18 +903,18 @@ abstract class GDisplayObject $debugLastLayerBounds = layerBounds; // canvas.saveLayer(layerBounds.toNative(), alphaPaint); if ($useSaveLayerBounds) { - nativeLayerBounds = layerBounds.toNative(); + nativeLayerBounds = layerBounds!.toNative(); } - canvas.saveLayer(nativeLayerBounds, alphaPaint); + canvas!.saveLayer(nativeLayerBounds, alphaPaint); } if (needSave) { // onPreTransform.dispatch(); - canvas.save(); - var m = transformationMatrix.toNative(); + canvas!.save(); + var m = transformationMatrix.toNative()!; canvas.transform(m.storage); if (_is3D) { /// TODO: experimental, just transforms - m = GMatrix().toNative(); + m = GMatrix().toNative()!; m.setEntry(3, 2, 0.004); m.rotateX(_rotationX); m.rotateY(_rotationY); @@ -940,11 +926,11 @@ abstract class GDisplayObject } if (hasMask) { - canvas.save(); + canvas!.save(); if (maskRect != null) { $applyMaskRect(canvas); } else { - mask.$applyPaint(canvas); + mask!.$applyPaint(canvas); } } @@ -964,22 +950,22 @@ abstract class GDisplayObject $onPostPaint?.dispatch(canvas); if (hasMask) { - canvas.restore(); + canvas!.restore(); } if (showDebugBounds) { final _paint = $debugBoundsPaint ?? _debugPaint; final linePaint = _paint.clone(); linePaint.color = linePaint.color.withOpacity(.3); - final rect = _cacheLocalBoundsRect.toNative(); - canvas.drawLine(rect.topLeft, rect.bottomRight, linePaint); + final rect = _cacheLocalBoundsRect!.toNative(); + canvas!.drawLine(rect.topLeft, rect.bottomRight, linePaint); canvas.drawLine(rect.topRight, rect.bottomLeft, linePaint); canvas.drawRect(rect, _paint); } if (needSave) { - canvas.restore(); + canvas!.restore(); } if (_saveLayer) { - canvas.restore(); + canvas!.restore(); } } @@ -988,11 +974,11 @@ abstract class GDisplayObject ..color = kColorMagenta ..strokeWidth = 1; - ui.Paint $debugBoundsPaint = _debugPaint.clone(); + ui.Paint? $debugBoundsPaint = _debugPaint.clone(); /// override this method for custom drawing using Flutter's API. /// Access `$canvas` from here. - void $applyPaint(ui.Canvas canvas) {} + void $applyPaint(ui.Canvas? canvas) {} @mustCallSuper void dispose() { @@ -1010,7 +996,7 @@ abstract class GDisplayObject } /// internal - void $setParent(GDisplayObjectContainer value) { + void $setParent(GDisplayObjectContainer? value) { var ancestor = value; while (ancestor != this && ancestor != null) { ancestor = ancestor.$parent; @@ -1039,7 +1025,7 @@ abstract class GDisplayObject $setTransformationChanged(); } - void setScale(double scaleX, [double scaleY]) { + void setScale(double scaleX, [double? scaleY]) { _scaleX = scaleX; _scaleY = scaleY ?? scaleX; $setTransformationChanged(); @@ -1051,8 +1037,8 @@ abstract class GDisplayObject /// transformations (x, y, scale, etc) if you intend to use in it's "original" /// form. ui.Picture createPicture( - [void Function(ui.Canvas) prePaintCallback, - void Function(ui.Canvas) postPaintCallback]) { + [void Function(ui.Canvas)? prePaintCallback, + void Function(ui.Canvas)? postPaintCallback]) { final r = ui.PictureRecorder(); final c = ui.Canvas(r); prePaintCallback?.call(c); @@ -1064,22 +1050,22 @@ abstract class GDisplayObject Future createImageTexture([ bool adjustOffset = true, double resolution = 1, - GRect rect, + GRect? rect, ]) async { final img = await createImage(adjustOffset, resolution, rect); var tx = GTexture.fromImage(img, resolution); - tx.pivotX = bounds.x; - tx.pivotY = bounds.y; + tx.pivotX = bounds!.x; + tx.pivotY = bounds!.y; return tx; } Future createImage([ bool adjustOffset = true, double resolution = 1, - GRect rect, + GRect? rect, ]) async { rect ??= getFilterBounds(); //getBounds($parent); - rect = rect.clone(); + rect = rect!.clone(); if (resolution != 1) { rect *= resolution; } @@ -1088,7 +1074,7 @@ abstract class GDisplayObject ui.Picture picture; if (needsAdjust) { picture = createPicture((canvas) { - if (adjustOffset) canvas.translate(-rect.left, -rect.top); + if (adjustOffset) canvas.translate(-rect!.left, -rect.top); if (resolution != 1) canvas.scale(resolution); }, (canvas) { if (adjustOffset) canvas.restore(); diff --git a/lib/src/display/display_object_container.dart b/lib/src/display/display_object_container.dart index 8920d52..8a3a0bf 100644 --- a/lib/src/display/display_object_container.dart +++ b/lib/src/display/display_object_container.dart @@ -41,7 +41,7 @@ abstract class GDisplayObjectContainer extends GDisplayObject { } @override - GRect getBounds(GDisplayObject targetSpace, [GRect out]) { + GRect? getBounds(GDisplayObject? targetSpace, [GRect? out]) { out ??= GRect(); final len = children.length; if (len == 0) { @@ -76,7 +76,7 @@ abstract class GDisplayObjectContainer extends GDisplayObject { return result; } final numChild = children.length; - GDisplayObject target; + GDisplayObject? target; for (var i = numChild - 1; i >= 0; --i) { var child = children[i]; if (child.isMask) continue; @@ -99,7 +99,7 @@ abstract class GDisplayObjectContainer extends GDisplayObject { } @override - GDisplayObject hitTest(GPoint localPoint, [bool useShape = false]) { + GDisplayObject? hitTest(GPoint localPoint, [bool useShape = false]) { if (!$hasTouchableArea || !mouseEnabled || !hitTestMask(localPoint)) { return null; } @@ -133,7 +133,6 @@ abstract class GDisplayObjectContainer extends GDisplayObject { } GDisplayObject addChildAt(GDisplayObject child, int index) { - if (child == null) throw "::child can't be null"; if (index < 0 || index > children.length) { throw RangeError('Invalid child index'); } @@ -209,7 +208,7 @@ abstract class GDisplayObjectContainer extends GDisplayObject { throw RangeError('Invalid child index'); } - GDisplayObject getChildByName(String name) { + GDisplayObject? getChildByName(String name) { for (final child in children) { if (child.name == name) return child; } @@ -237,7 +236,7 @@ abstract class GDisplayObjectContainer extends GDisplayObject { bool get hasChildren => children.isNotEmpty; - bool contains(GDisplayObject child, [bool recursive = true]) { + bool contains(GDisplayObject? child, [bool recursive = true]) { if (!recursive) return children.contains(child); while (child != null) { if (child == this) return true; @@ -267,8 +266,8 @@ abstract class GDisplayObjectContainer extends GDisplayObject { throw 'Invalid child index'; } - GDisplayObject removeChild(GDisplayObject child, [bool dispose = false]) { - if (child == null || child?.$parent != this) return null; + GDisplayObject? removeChild(GDisplayObject child, [bool dispose = false]) { + if (child.$parent != this) return null; final index = getChildIndex(child); if (index > -1) return removeChildAt(index, dispose); throw 'Invalid child index'; @@ -283,7 +282,7 @@ abstract class GDisplayObjectContainer extends GDisplayObject { } @override - void $applyPaint(ui.Canvas canvas) { + void $applyPaint(ui.Canvas? canvas) { if (!$hasVisibleArea) return; for (var child in children) { if (child.$hasVisibleArea) { @@ -304,7 +303,7 @@ abstract class GDisplayObjectContainer extends GDisplayObject { @mustCallSuper void dispose() { for (final child in children) { - child?.dispose(); + child.dispose(); } children.clear(); super.dispose(); diff --git a/lib/src/display/shape.dart b/lib/src/display/shape.dart index 838f553..dbe35c2 100644 --- a/lib/src/display/shape.dart +++ b/lib/src/display/shape.dart @@ -2,7 +2,7 @@ import 'dart:ui' as ui; import '../../graphx.dart'; class GShape extends GDisplayObject { - Graphics _graphics; + Graphics? _graphics; static final _sHelperMatrix = GMatrix(); @override @@ -14,7 +14,7 @@ class GShape extends GDisplayObject { Graphics get graphics => _graphics ??= Graphics(); @override - GRect getBounds(GDisplayObject targetSpace, [GRect out]) { + GRect? getBounds(GDisplayObject? targetSpace, [GRect? out]) { final matrix = _sHelperMatrix; matrix.identity(); getTransformationMatrix(targetSpace, matrix); @@ -33,24 +33,24 @@ class GShape extends GDisplayObject { // }); /// single bounds, all paths as 1 rect. return MatrixUtils.getTransformedBoundsRect( - matrix, _graphics.getBounds(out), out); + matrix, _graphics!.getBounds(out), out); } else { final pos = GDisplayObjectContainer.$sBoundsPoint; matrix.transformCoords(0, 0, pos); - out.setTo(pos.x, pos.y, 0, 0); + out!.setTo(pos.x, pos.y, 0, 0); } return out; } @override - GDisplayObject hitTest(GPoint localPoint, [bool useShape = false]) { + GDisplayObject? hitTest(GPoint localPoint, [bool useShape = false]) { if (!$hasTouchableArea || !mouseEnabled) { return null; } return (_graphics?.hitTest(localPoint, useShape) ?? false) ? this : null; } - static ui.Path _inverseHugePath; + static ui.Path? _inverseHugePath; static void _initInversePath() { if (_inverseHugePath != null) { return; @@ -58,22 +58,22 @@ class GShape extends GDisplayObject { _inverseHugePath = ui.Path(); final w = 100000.0; var r = Pool.getRect(-w / 2, -w / 2, w, w); - _inverseHugePath.addRect(r.toNative()); - _inverseHugePath.close(); + _inverseHugePath!.addRect(r.toNative()); + _inverseHugePath!.close(); } @override - void $applyPaint(ui.Canvas canvas) { + void $applyPaint(ui.Canvas? canvas) { if (isMask && _graphics != null) { GMatrix matrix; - var paths = _graphics.getPaths(); - if (inStage && $maskee.inStage) { + var paths = _graphics!.getPaths(); + if (inStage && $maskee!.inStage) { matrix = getTransformationMatrix($maskee); } else { matrix = transformationMatrix; } - var clipPath = paths.transform(matrix.toNative().storage); - final inverted = maskInverted || $maskee.maskInverted; + var clipPath = paths.transform(matrix.toNative()!.storage); + final inverted = maskInverted || $maskee!.maskInverted; if (inverted) { _initInversePath(); // var invPath = Graphics.stageRectPath; @@ -81,13 +81,13 @@ class GShape extends GDisplayObject { // invPath = invPath.shift(Offset(rect.x, rect.y)); if (SystemUtils.usingSkia) { clipPath = ui.Path.combine( - ui.PathOperation.difference, _inverseHugePath, clipPath); - canvas.clipPath(clipPath); + ui.PathOperation.difference, _inverseHugePath!, clipPath); + canvas!.clipPath(clipPath); } else { trace('Shape.maskInverted is unsupported in the current platform'); } } else { - canvas.clipPath(clipPath); + canvas!.clipPath(clipPath); } } else { _graphics?.isMask = isMask; diff --git a/lib/src/display/sprite.dart b/lib/src/display/sprite.dart index a6dc3b1..12ae3e2 100644 --- a/lib/src/display/sprite.dart +++ b/lib/src/display/sprite.dart @@ -11,31 +11,31 @@ class GSprite extends GDisplayObjectContainer { static final _sHelperMatrix = GMatrix(); - Graphics _graphics; + Graphics? _graphics; Graphics get graphics => _graphics ??= Graphics(); @override - GRect getBounds(GDisplayObject targetSpace, [GRect out]) { + GRect? getBounds(GDisplayObject? targetSpace, [GRect? out]) { out = super.getBounds(targetSpace, out); if (_graphics != null) { _sHelperMatrix.identity(); getTransformationMatrix(targetSpace, _sHelperMatrix); /// single bounds, all paths as 1 rect. - final graphicsBounds = _graphics.getBounds(); + final graphicsBounds = _graphics!.getBounds(); MatrixUtils.getTransformedBoundsRect( _sHelperMatrix, graphicsBounds, graphicsBounds, ); - out.expandToInclude(graphicsBounds); + out!.expandToInclude(graphicsBounds); } return out; } @override - GDisplayObject hitTest(GPoint localPoint, [bool useShape = false]) { + GDisplayObject? hitTest(GPoint localPoint, [bool useShape = false]) { if (!visible || !mouseEnabled) return null; var target = super.hitTest(localPoint); target ??= @@ -44,7 +44,7 @@ class GSprite extends GDisplayObjectContainer { } @override - void $applyPaint(ui.Canvas canvas) { + void $applyPaint(ui.Canvas? canvas) { if (!$hasVisibleArea) return; _graphics?.alpha = worldAlpha; _graphics?.paint(canvas); diff --git a/lib/src/display/stage.dart b/lib/src/display/stage.dart index 7d2797f..791ac7d 100644 --- a/lib/src/display/stage.dart +++ b/lib/src/display/stage.dart @@ -36,9 +36,9 @@ class Stage extends GDisplayObjectContainer return '$runtimeType'; } - ui.Size _size; - ui.Paint _backgroundPaint; - DisplayBoundsDebugger _boundsDebugger; + ui.Size? _size; + ui.Paint? _backgroundPaint; + late DisplayBoundsDebugger _boundsDebugger; /// Shortcut to access the owner [SceneController]. SceneController get controller => scene.core; @@ -47,15 +47,15 @@ class Stage extends GDisplayObjectContainer Signal get onHotReload => controller.onHotReload; /// The `backgroundPaint` hex color. - ui.Color get color => _backgroundPaint?.color; + ui.Color? get color => _backgroundPaint?.color; /// Sets the `backgroundPaint` Color. - set color(ui.Color value) { + set color(ui.Color? value) { if (value == null) { _backgroundPaint = null; } else { _backgroundPaint ??= ui.Paint(); - _backgroundPaint.color = value; + _backgroundPaint!.color = value; } } @@ -77,13 +77,13 @@ class Stage extends GDisplayObjectContainer } @override - void paint(ui.Canvas canvas) { + void paint(ui.Canvas? canvas) { /// scene start painting. if (maskBounds && _stageRectNative != null) { - canvas.clipRect(_stageRectNative); + canvas!.clipRect(_stageRectNative!); } if (_backgroundPaint != null) { - canvas.drawPaint(_backgroundPaint); + canvas!.drawPaint(_backgroundPaint!); } super.paint(canvas); if (DisplayBoundsDebugger.debugBoundsMode == DebugBoundsMode.stage) { @@ -91,11 +91,11 @@ class Stage extends GDisplayObjectContainer _boundsDebugger.render(); } if (showBoundsRect) { - canvas.drawPath(_stageBoundsRectPath, _stageBoundsRectPaint); + canvas!.drawPath(_stageBoundsRectPath, _stageBoundsRectPaint); } } - ui.Path _stageBoundsRectPath = ui.Path(); + final ui.Path _stageBoundsRectPath = ui.Path(); static final ui.Paint _stageBoundsRectPaint = ui.Paint() ..style = ui.PaintingStyle.stroke ..color = kColorBlack @@ -104,20 +104,25 @@ class Stage extends GDisplayObjectContainer final GRect _stageRect = GRect(); GRect get stageRect => _stageRect; - ui.Rect _stageRectNative; + ui.Rect? _stageRectNative; void $initFrameSize(ui.Size value) { if (value != _size) { _size = value; - if (_size.isEmpty) { + if (_size!.isEmpty) { trace( - "WARNING:\n\tStage has size <= 0 in width or height. If you rely on stage size for a responsive layout or rendering, make sure SceneBuilderWidget() has some child, or the parent is defining the constraints."); + // ignore: lines_longer_than_80_chars + "WARNING:\n\tStage has size <= 0 in width or height. " + "If you rely on stage size for a responsive layout or rendering," + " make sure SceneBuilderWidget() has some child," + " or the parent is defining the constraints.", + ); } _stageRectNative = - _stageRect.setTo(0, 0, _size.width, _size.height).toNative(); - _stageBoundsRectPath ??= ui.Path(); + _stageRect.setTo(0, 0, _size!.width, _size!.height).toNative(); + _stageBoundsRectPath; _stageBoundsRectPath.reset(); - _stageBoundsRectPath.addRect(_stageRectNative); + _stageBoundsRectPath.addRect(_stageRectNative!); _stageBoundsRectPath.close(); Graphics.updateStageRect(_stageRect); $onResized?.dispatch(); @@ -126,31 +131,31 @@ class Stage extends GDisplayObjectContainer /// Access the keyboard instance of the owner `SceneController`, /// Only available when [SceneConfig.useKeyboard] is true. - KeyboardManager get keyboard { - if (scene?.core?.keyboard == null) { + KeyboardManager? get keyboard { + if (scene.core.keyboard == null) { throw Exception( 'You need to enable keyboard capture, define useKeyboard=true ' - 'in your SceneController'); + 'in your SceneController'); } - return scene?.core?.keyboard; + return scene.core.keyboard; } /// Access the pointer (mouse or touch info) instance of the /// owner `SceneController`, /// Only available when [SceneConfig.usePointer] is true. - PointerManager get pointer { - if (scene?.core?.pointer == null) { + PointerManager? get pointer { + if (scene.core.pointer == null) { throw 'You need to enable pointer capture, define usePointer=true ' 'in your SceneController'; } - return scene?.core?.pointer; + return scene.core.pointer; } @override bool hitTouch(GPoint localPoint, [bool useShape = false]) => true; @override - GDisplayObject hitTest(GPoint localPoint, [bool useShapes = false]) { + GDisplayObject? hitTest(GPoint localPoint, [bool useShapes = false]) { if (!visible || !mouseEnabled) return null; /// location outside stage area, is not accepted. @@ -184,7 +189,7 @@ class Stage extends GDisplayObjectContainer } } - GRect getStageBounds(GDisplayObject targetSpace, [GRect out]) { + GRect getStageBounds(GDisplayObject targetSpace, [GRect? out]) { out ??= GRect(); out.setTo(0, 0, stageWidth, stageHeight); getTransformationMatrix(targetSpace, _sMatrix); @@ -209,8 +214,8 @@ class Stage extends GDisplayObjectContainer void dispose() { _size = null; _backgroundPaint = null; - scene?.core?.pointer?.dispose(); - scene?.core?.keyboard?.dispose(); + scene.core.pointer?.dispose(); + scene.core.keyboard?.dispose(); $disposeResizeSignals(); $disposeTickerSignals(); $disposeStagePointerSignals(); @@ -224,22 +229,22 @@ class Stage extends GDisplayObjectContainer double get height => throw 'Use `stage.stageHeight` instead.'; @override - set width(double value) => throw 'Cannot set width of stage'; + set width(double? value) => throw 'Cannot set width of stage'; @override - set height(double value) => throw 'Cannot set height of stage'; + set height(double? value) => throw 'Cannot set height of stage'; @override - set x(double value) => throw 'Cannot set x-coordinate of stage'; + set x(double? value) => throw 'Cannot set x-coordinate of stage'; @override - set y(double value) => throw 'Cannot set y-coordinate of stage'; + set y(double? value) => throw 'Cannot set y-coordinate of stage'; @override - set scaleX(double value) => throw 'Cannot scale stage'; + set scaleX(double? value) => throw 'Cannot scale stage'; @override - set scaleY(double value) => throw 'Cannot scale stage'; + set scaleY(double? value) => throw 'Cannot scale stage'; @override set pivotX(double value) => throw 'Cannot pivot stage'; @@ -254,5 +259,5 @@ class Stage extends GDisplayObjectContainer set skewY(double value) => throw 'Cannot skew stage'; @override - set rotation(double value) => throw 'Cannot rotate stage'; + set rotation(double? value) => throw 'Cannot rotate stage'; } diff --git a/lib/src/display/text.dart b/lib/src/display/text.dart index d59ac18..0b3bf2c 100644 --- a/lib/src/display/text.dart +++ b/lib/src/display/text.dart @@ -3,9 +3,9 @@ import 'package:flutter/painting.dart' as painting; import '../../graphx.dart'; class GText extends GDisplayObject { - ui.Paragraph _paragraph; + ui.Paragraph? _paragraph; - Signal _onFontLoaded; + Signal? _onFontLoaded; Signal get onFontLoaded => _onFontLoaded ??= Signal(); @@ -15,7 +15,7 @@ class GText extends GDisplayObject { final _alphaPaint = ui.Paint(); @override - GRect getBounds(GDisplayObject targetSpace, [GRect out]) { + GRect getBounds(GDisplayObject? targetSpace, [GRect? out]) { validate(); out ??= GRect(); out.setTo(0, 0, intrinsicWidth, textHeight); @@ -42,27 +42,27 @@ class GText extends GDisplayObject { // return r; // } - ui.Paragraph get paragraph => _paragraph; + ui.Paragraph? get paragraph => _paragraph; // ui.TextStyle _style; - painting.TextStyle _style; + painting.TextStyle? _style; - double _width; + double _width = 0.0; - ui.ParagraphBuilder _builder; - ui.ParagraphStyle _paragraphStyle; + late ui.ParagraphBuilder _builder; + ui.ParagraphStyle? _paragraphStyle; bool _invalidSize = true; bool _invalidBuilder = true; - String _text; - ui.Color backgroundColor; + String? _text; + ui.Color? backgroundColor; - ui.Color get color { - return _style.color; + ui.Color? get color { + return _style!.color; } - set color(ui.Color value) { - _style = _style.copyWith(color: value); + set color(ui.Color? value) { + _style = _style!.copyWith(color: value); _invalidBuilder = true; // _invalidateBuilder(); } @@ -77,7 +77,7 @@ class GText extends GDisplayObject { String get text => _text ?? ''; - set text(String value) { + set text(String? value) { if (_text == value) return; _text = value ?? ''; _invalidBuilder = true; @@ -88,7 +88,7 @@ class GText extends GDisplayObject { double get width => _width; @override - set width(double value) { + set width(double? value) { if (value == null || _width == value) return; _width = value; _invalidSize = true; @@ -158,15 +158,15 @@ class GText extends GDisplayObject { // } GText({ - String text, - ui.ParagraphStyle paragraphStyle, - painting.TextStyle textStyle, + String? text, + ui.ParagraphStyle? paragraphStyle, + painting.TextStyle? textStyle, double width = double.infinity, }) { - painting.PaintingBinding.instance.systemFonts.addListener(_fontLoaded); + painting.PaintingBinding.instance!.systemFonts.addListener(_fontLoaded); this.text = text; - _width = width ?? double.infinity; + _width = width; _invalidBuilder = true; _invalidSize = true; setTextStyle(textStyle ?? defaultTextStyle); @@ -182,32 +182,32 @@ class GText extends GDisplayObject { @override void dispose() { super.dispose(); - painting.PaintingBinding.instance.systemFonts.removeListener(_fontLoaded); + painting.PaintingBinding.instance!.systemFonts.removeListener(_fontLoaded); _onFontLoaded?.removeAll(); _onFontLoaded = null; } void setTextStyle(painting.TextStyle style) { - if (style == null || _style == style) return; + if (_style == style) return; _style = style; _invalidBuilder = true; } - painting.TextStyle getTextStyle() => _style; + painting.TextStyle? getTextStyle() => _style; - ui.ParagraphStyle getParagraphStyle() => _paragraphStyle; + ui.ParagraphStyle? getParagraphStyle() => _paragraphStyle; void setParagraphStyle(ui.ParagraphStyle style) { - if (style == null || _paragraphStyle == style) return; + if (_paragraphStyle == style) return; _paragraphStyle = style; _invalidBuilder = true; } void _invalidateBuilder() { _paragraphStyle ??= defaultParagraphStyle; - _builder = ui.ParagraphBuilder(_paragraphStyle); + _builder = ui.ParagraphBuilder(_paragraphStyle!); // if (_style != null) _builder.pushStyle(_style); - if (_style != null) _builder.pushStyle(_style.getTextStyle()); + if (_style != null) _builder.pushStyle(_style!.getTextStyle()); _builder.addText(_text ?? ''); _paragraph = _builder.build(); _invalidBuilder = false; @@ -227,14 +227,14 @@ class GText extends GDisplayObject { /// applies the painting after the DisplayObject transformations. /// Should be overriden by subclasses. @override - void $applyPaint(ui.Canvas canvas) { + void $applyPaint(ui.Canvas? canvas) { super.$applyPaint(canvas); if (_text == '') return; validate(); - if (backgroundColor != null && backgroundColor.alpha > 0) { - canvas.drawRect( + if (backgroundColor != null && backgroundColor!.alpha > 0) { + canvas!.drawRect( ui.Rect.fromLTWH(0, 0, intrinsicWidth, textHeight), - ui.Paint()..color = backgroundColor, + ui.Paint()..color = backgroundColor!, ); } if (_paragraph != null) { @@ -243,18 +243,18 @@ class GText extends GDisplayObject { // final alphaPaint = PainterUtils.getAlphaPaint($alpha); // final alphaPaint = _alphaPaint; // var bounds = Rect.fromLTWH(0, 0, textWidth, textHeight); - canvas.saveLayer(null, _alphaPaint); - canvas.drawParagraph(_paragraph, ui.Offset.zero); + canvas!.saveLayer(null, _alphaPaint); + canvas.drawParagraph(_paragraph!, ui.Offset.zero); canvas.restore(); } else { - canvas.drawParagraph(_paragraph, ui.Offset.zero); + canvas!.drawParagraph(_paragraph!, ui.Offset.zero); } } } @override set alpha(double value) { - final changed = value != $alpha && value != null; + final changed = value != $alpha; super.alpha = value; if (changed) { _alphaPaint.color = _alphaPaint.color.withOpacity($alpha); @@ -278,34 +278,33 @@ class GText extends GDisplayObject { /// Factory method to simplify the initialization of a StaticText instance. /// You can pass the parent object directly in the `doc` parameter. static GText build({ - String text, - GDisplayObjectContainer doc, - ui.Color color, + String? text, + GDisplayObjectContainer? doc, + ui.Color? color, double w = double.infinity, - ui.TextDecoration decoration, - ui.Color decorationColor, - ui.TextDecorationStyle decorationStyle, - double decorationThickness, - ui.FontWeight fontWeight, - ui.FontStyle fontStyle, - ui.TextBaseline textBaseline, - String fontFamily, - List fontFamilyFallback, - double fontSize, - double letterSpacing, - double wordSpacing, - double height, - ui.Locale locale, - ui.Paint background, - ui.Paint foreground, - String ellipsis, - int maxLines, - List shadows, - List fontFeatures, + ui.TextDecoration? decoration, + ui.Color? decorationColor, + ui.TextDecorationStyle? decorationStyle, + double? decorationThickness, + ui.FontWeight? fontWeight, + ui.FontStyle? fontStyle, + ui.TextBaseline? textBaseline, + String? fontFamily, + List? fontFamilyFallback, + double? fontSize, + double? letterSpacing, + double? wordSpacing, + double? height, + ui.Locale? locale, + ui.Paint? background, + ui.Paint? foreground, + String? ellipsis, + int? maxLines, + List? shadows, + List? fontFeatures, ui.TextAlign textAlign = ui.TextAlign.left, ui.TextDirection direction = ui.TextDirection.ltr, }) { - w ??= double.infinity; if (w == double.infinity && textAlign != ui.TextAlign.left) { throw "[StaticText] To use $textAlign you need to specify the width"; } @@ -335,10 +334,10 @@ class GText extends GDisplayObject { width: w, textStyle: style, paragraphStyle: ui.ParagraphStyle( - textAlign: textAlign, - textDirection: direction, maxLines: maxLines, ellipsis: ellipsis, + textAlign: textAlign, + textDirection: direction, ), ); doc?.addChild(tf); diff --git a/lib/src/events/callback_params.dart b/lib/src/events/callback_params.dart index c1b2874..491c1d0 100644 --- a/lib/src/events/callback_params.dart +++ b/lib/src/events/callback_params.dart @@ -1,14 +1,14 @@ class CallbackParams { - List positional; + List? positional; /// Symbol is represented by the literal # in Dart. /// So, if u need `({String name, int count})` in named parameters. /// You'd use {#name: 'roi', #count: 10}. - Map named; + Map? named; CallbackParams([this.positional, this.named]); - static CallbackParams parse(Object args) { + static CallbackParams? parse(Object? args) { if (args == null) return null; if (args is CallbackParams) return args; @@ -16,7 +16,7 @@ class CallbackParams { if (args is List) { return CallbackParams(args); } else if (args is Map) { - return CallbackParams(null, args); + return CallbackParams(null, args as Map?); } return CallbackParams([args]); diff --git a/lib/src/events/keyboard_data.dart b/lib/src/events/keyboard_data.dart index afa5809..0a30697 100644 --- a/lib/src/events/keyboard_data.dart +++ b/lib/src/events/keyboard_data.dart @@ -4,36 +4,36 @@ import 'package:flutter/widgets.dart'; enum KeyEventType { down, up } class KeyboardEventData { - final KeyEventType type; - final RawKeyEvent rawEvent; + final KeyEventType? type; + final RawKeyEvent? rawEvent; KeyboardEventData({this.type, this.rawEvent}); bool isPressed(LogicalKeyboardKey key) { - return rawEvent.isKeyPressed(key); + return rawEvent!.isKeyPressed(key); } bool isKey(LogicalKeyboardKey key) { - return rawEvent.logicalKey == key; + return rawEvent!.logicalKey == key; } } extension MyKeyEventExt on KeyboardEventData { bool get arrowLeft { // return rawEvent.isKeyPressed(LogicalKeyboardKey.arrowLeft); - return rawEvent.logicalKey == LogicalKeyboardKey.arrowLeft; + return rawEvent!.logicalKey == LogicalKeyboardKey.arrowLeft; } bool get arrowRight { - return rawEvent.logicalKey == LogicalKeyboardKey.arrowRight; + return rawEvent!.logicalKey == LogicalKeyboardKey.arrowRight; // return rawEvent.isKeyPressed(LogicalKeyboardKey.arrowRight); } bool get arrowUp { - return rawEvent.logicalKey == LogicalKeyboardKey.arrowUp; + return rawEvent!.logicalKey == LogicalKeyboardKey.arrowUp; } bool get arrowDown { - return rawEvent.logicalKey == LogicalKeyboardKey.arrowDown; + return rawEvent!.logicalKey == LogicalKeyboardKey.arrowDown; } } diff --git a/lib/src/events/mixins.dart b/lib/src/events/mixins.dart index d5c5753..e62751d 100644 --- a/lib/src/events/mixins.dart +++ b/lib/src/events/mixins.dart @@ -27,7 +27,7 @@ mixin EventDispatcherMixin implements Listenable { } mixin TickerSignalMixin { - EventSignal $onEnterFrame; + EventSignal? $onEnterFrame; EventSignal get onEnterFrame => $onEnterFrame ??= EventSignal(); @@ -39,7 +39,7 @@ mixin TickerSignalMixin { } mixin ResizeSignalMixin { - Signal $onResized; + Signal? $onResized; Signal get onResized => $onResized ??= Signal(); void $disposeResizeSignals() { @@ -49,19 +49,19 @@ mixin ResizeSignalMixin { } mixin DisplayListSignalsMixin { - Signal $onAdded; + Signal? $onAdded; Signal get onAdded => $onAdded ??= Signal(); - Signal $onRemoved; + Signal? $onRemoved; Signal get onRemoved => $onRemoved ??= Signal(); - Signal $onRemovedFromStage; + Signal? $onRemovedFromStage; Signal get onRemovedFromStage => $onRemovedFromStage ??= Signal(); - Signal $onAddedToStage; + Signal? $onAddedToStage; Signal get onAddedToStage => $onAddedToStage ??= Signal(); @@ -78,13 +78,14 @@ mixin DisplayListSignalsMixin { } mixin RenderSignalMixin { - EventSignal $onPrePaint; - EventSignal $onPostPaint; + EventSignal? $onPrePaint; + EventSignal? $onPostPaint; // EventSignal $onPaint; - EventSignal get onPrePaint => $onPrePaint ??= EventSignal(); + EventSignal get onPrePaint => $onPrePaint ??= EventSignal(); - EventSignal get onPostPaint => $onPostPaint ??= EventSignal(); + EventSignal get onPostPaint => + $onPostPaint ??= EventSignal(); // EventSignal get onPaint => $onPaint ??= EventSignal(); @@ -100,8 +101,8 @@ mixin RenderSignalMixin { /// use mouse signal for now. mixin StageMouseSignalsMixin { - EventSignal $onMouseLeave; - EventSignal $onMouseEnter; + EventSignal? $onMouseLeave; + EventSignal? $onMouseEnter; EventSignal get onMouseLeave => $onMouseLeave ??= EventSignal(); EventSignal get onMouseEnter => $onMouseEnter ??= EventSignal(); @@ -116,15 +117,15 @@ mixin StageMouseSignalsMixin { /// use mouse signal for now. mixin MouseSignalsMixin { - EventSignal $onRightMouseDown; - EventSignal $onMouseDoubleClick; - EventSignal $onMouseClick; - EventSignal $onMouseDown; - EventSignal $onMouseUp; - EventSignal $onMouseMove; - EventSignal $onMouseOut; - EventSignal $onMouseOver; - EventSignal $onMouseWheel; + EventSignal? $onRightMouseDown; + EventSignal? $onMouseDoubleClick; + EventSignal? $onMouseClick; + EventSignal? $onMouseDown; + EventSignal? $onMouseUp; + EventSignal? $onMouseMove; + EventSignal? $onMouseOut; + EventSignal? $onMouseOver; + EventSignal? $onMouseWheel; EventSignal get onMouseClick => $onMouseClick ??= EventSignal(); EventSignal get onMouseDoubleClick => @@ -160,12 +161,12 @@ mixin MouseSignalsMixin { } mixin PointerSignalsMixin { - EventSignal $onClick; - EventSignal $onDown; - EventSignal $onUp; - EventSignal $onHover; - EventSignal $onOut; - EventSignal $onScroll; + EventSignal? $onClick; + EventSignal? $onDown; + EventSignal? $onUp; + EventSignal? $onHover; + EventSignal? $onOut; + EventSignal? $onScroll; EventSignal get onClick => $onClick ??= EventSignal(); EventSignal get onDown => $onDown ??= EventSignal(); diff --git a/lib/src/events/mps.dart b/lib/src/events/mps.dart index 045d0a3..741fbf7 100644 --- a/lib/src/events/mps.dart +++ b/lib/src/events/mps.dart @@ -10,15 +10,15 @@ final mps = MPS(); /// - publish(N) = emit(N) /// Accepts a "once()" event like signals. class MPS { - final _cache = >{}; + final _cache = >{}; final _cacheOnce = >{}; void publishParams(String topic, CallbackParams args) { // final subs = _cache[topic]; // subs?.forEach((fn) => Function.apply(fn, args?.positional, args?.named)); - void _send(Function fn) => - Function.apply(fn, args?.positional, args?.named); + void _send(Function? fn) => + Function.apply(fn!, args.positional, args.named); _cache[topic]?.forEach(_send); _cacheOnce[topic]?.forEach(_send); @@ -27,7 +27,7 @@ class MPS { void publish1(String topic, T arg1) { // _cache[topic]?.forEach((fn) => fn.call(arg1)); - void _send(Function fn) => fn.call(arg1); + void _send(Function? fn) => fn!.call(arg1); _cache[topic]?.forEach(_send); _cacheOnce[topic]?.forEach(_send); _cacheOnce.remove(topic); @@ -35,7 +35,7 @@ class MPS { void publish2(String topic, T arg1, S arg2) { // _cache[topic]?.forEach((fn) => fn.call(arg1, arg2)); - void _send(Function fn) => fn.call(arg1, arg2); + void _send(Function? fn) => fn!.call(arg1, arg2); _cache[topic]?.forEach(_send); _cacheOnce[topic]?.forEach(_send); _cacheOnce.remove(topic); @@ -43,7 +43,7 @@ class MPS { void publish(String topic) { // _cache[topic]?.forEach((fn) => fn.call()); - void _send(Function fn) => fn.call(); + void _send(Function? fn) => fn!.call(); _cache[topic]?.forEach(_send); _cacheOnce[topic]?.forEach(_send); _cacheOnce.remove(topic); @@ -72,8 +72,8 @@ class MPS { if (!_cacheOnce.containsKey(topic)) { _cacheOnce[topic] = []; } - if (!_cacheOnce[topic].contains(callback)) { - _cacheOnce[topic].add(callback); + if (!_cacheOnce[topic]!.contains(callback)) { + _cacheOnce[topic]!.add(callback); return true; } return false; @@ -84,16 +84,16 @@ class MPS { _cache[topic] = []; // cache[topic] = LinkedList(); } - if (!_cache[topic].contains(callback)) { + if (!_cache[topic]!.contains(callback)) { // cache[topic].add(Callback(callback)); - _cache[topic].add(callback); + _cache[topic]!.add(callback); return true; } return false; } bool unsubscribe(String topic, Function callback) { - final subs = _cache[topic]; + final subs = _cache[topic]!; return subs.remove(callback); // subs.remove(Callback._hash[callback]); // int len = subs?.length ?? 0; @@ -114,53 +114,53 @@ class MPS { return _cacheOnce[topic]?.length ?? 0; } - void off(String topic, Function callback) { + void off(String topic, Function? callback) { _cache[topic]?.remove(callback); _cacheOnce[topic]?.remove(callback); } MPS emit(String topic) { - void _send(Function fn) => fn.call(); + void _send(Function? fn) => fn!.call(); _cache[topic]?.forEach(_send); _cacheOnce[topic]?.forEach(_send); - _cacheOnce?.remove(topic); + _cacheOnce.remove(topic); return this; } - MPS on(String topic, Function callback) { + MPS on(String topic, Function? callback) { if (!_cache.containsKey(topic)) { _cache[topic] = []; } - if (!_cache[topic].contains(callback)) { - _cache[topic].add(callback); + if (!_cache[topic]!.contains(callback)) { + _cache[topic]!.add(callback); } return this; } void emit1(String topic, T arg1) { - void _send(Function fn) => fn.call(arg1); + void _send(Function? fn) => fn!.call(arg1); _cache[topic]?.forEach(_send); _cacheOnce[topic]?.forEach(_send); _cacheOnce.remove(topic); } void emit2(String topic, T arg1, S arg2) { - void _send(Function fn) => fn.call(arg1, arg2); + void _send(Function? fn) => fn!.call(arg1, arg2); _cache[topic]?.forEach(_send); _cacheOnce[topic]?.forEach(_send); _cacheOnce.remove(topic); } void emit3(String topic, A arg1, B arg2, C arg3) { - void _send(Function fn) => fn.call(arg1, arg2, arg3); + void _send(Function? fn) => fn!.call(arg1, arg2, arg3); _cache[topic]?.forEach(_send); _cacheOnce[topic]?.forEach(_send); _cacheOnce.remove(topic); } void emitParams(String topic, CallbackParams args) { - void _send(Function fn) => - Function.apply(fn, args?.positional, args?.named); + void _send(Function? fn) => + Function.apply(fn!, args.positional, args.named); _cache[topic]?.forEach(_send); _cacheOnce[topic]?.forEach(_send); _cacheOnce.remove(topic); diff --git a/lib/src/events/pointer_data.dart b/lib/src/events/pointer_data.dart index 7ff9fe9..668fcc6 100644 --- a/lib/src/events/pointer_data.dart +++ b/lib/src/events/pointer_data.dart @@ -17,11 +17,11 @@ enum PointerEventType { class PointerEventData { final double stageX; final double stageY; - final PointerEventType type; + final PointerEventType? type; final PointerEvent rawEvent; /// local position in DisplayObject - GPoint localPosition; + late GPoint localPosition; double get localX => localPosition.x; @@ -32,7 +32,7 @@ class PointerEventData { /// 300 milliseconds for double click static int doubleClickTime = 300; - PointerEventData({this.type, this.rawEvent}) + PointerEventData({this.type, required this.rawEvent}) : stageX = rawEvent.localPosition.dx, stageY = rawEvent.localPosition.dy { localPosition = GPoint(stageX, stageY); @@ -40,14 +40,14 @@ class PointerEventData { int get time => rawEvent.timeStamp.inMilliseconds; - Offset get scrollDelta { + Offset? get scrollDelta { if (rawEvent is PointerScrollEvent) { return (rawEvent as PointerScrollEvent).scrollDelta; } return null; } - GPoint get windowPosition => GPoint.fromNative(rawEvent.original.position); + GPoint get windowPosition => GPoint.fromNative(rawEvent.original!.position); GPoint get stagePosition => GPoint.fromNative(rawEvent.localPosition); @@ -66,8 +66,8 @@ class PointerEventData { /// new properties. /// TODO: decide how to name mouse/pointer events. - GDisplayObject target; - GDisplayObject dispatcher; + GDisplayObject? target; + GDisplayObject? dispatcher; bool captured = false; bool mouseOut = false; @@ -127,23 +127,23 @@ class MouseInputData { } /// display objects - GDisplayObject target; - GDisplayObject dispatcher; - MouseInputType type; + GDisplayObject? target; + GDisplayObject? dispatcher; + MouseInputType? type; bool buttonDown = false; bool mouseOut = false; double time = 0; - PointerEventData rawEvent; + PointerEventData? rawEvent; /// defines which button is pressed... - int buttonsFlags; + int? buttonsFlags; bool get isSecondaryDown => - buttonsFlags & kSecondaryButton == kSecondaryButton; + buttonsFlags! & kSecondaryButton == kSecondaryButton; - bool get isPrimaryDown => buttonsFlags & kPrimaryButton == kPrimaryButton; + bool get isPrimaryDown => buttonsFlags! & kPrimaryButton == kPrimaryButton; - bool get isTertiaryDown => buttonsFlags & 0x04 == 0x04; + bool get isTertiaryDown => buttonsFlags! & 0x04 == 0x04; GPoint get stagePosition => _stagePosition; final GPoint _stagePosition = GPoint(); @@ -155,16 +155,16 @@ class MouseInputData { double get localY => localPosition.y; - double get windowX => rawEvent?.rawEvent?.original?.position?.dx ?? 0; + double get windowX => rawEvent?.rawEvent.original?.position.dx ?? 0; - double get windowY => rawEvent?.rawEvent?.original?.position?.dy ?? 0; + double get windowY => rawEvent?.rawEvent.original?.position.dy ?? 0; - double get stageX => _stagePosition?.x ?? 0; + double get stageX => _stagePosition.x; - double get stageY => _stagePosition?.y ?? 0; + double get stageY => _stagePosition.y; GPoint get localDelta { - final d = rawEvent?.rawEvent?.localDelta; + final d = rawEvent?.rawEvent.localDelta; if (d == null) { return _localDelta.setEmpty(); } @@ -172,11 +172,11 @@ class MouseInputData { } static int uniqueId = 0; - int uid; + int? uid; MouseInputData({this.target, this.dispatcher, this.type}); MouseInputData clone( - GDisplayObject target, GDisplayObject dispatcher, MouseInputType type) { + GDisplayObject target, GDisplayObject dispatcher, MouseInputType? type) { var input = MouseInputData( target: target, dispatcher: dispatcher, @@ -205,7 +205,7 @@ class MouseInputData { // } // int get time => rawEvent.rawEvent.timeStamp.inMilliseconds; - static MouseInputType fromNativeType(PointerEventType nativeType) { + static MouseInputType fromNativeType(PointerEventType? nativeType) { if (nativeType == PointerEventType.down) { return MouseInputType.down; } else if (nativeType == PointerEventType.up) { diff --git a/lib/src/events/signal.dart b/lib/src/events/signal.dart index 44c726f..acbc6a7 100644 --- a/lib/src/events/signal.dart +++ b/lib/src/events/signal.dart @@ -17,12 +17,12 @@ class Signal { void add(Function callback) { // if (callback == null || _listenersOnce.contains(callback)) return; - if (callback == null || has(callback)) return; + if (has(callback)) return; _listeners.add(callback); } void addOnce(Function callback) { - if (callback == null || _listeners.contains(callback)) return; + if (_listeners.contains(callback)) return; _listenersOnce.add(callback); } @@ -44,22 +44,22 @@ class Signal { void dispatch() { final len = _listeners.length; for (_iterDispatchers = 0; _iterDispatchers < len; ++_iterDispatchers) { - _listeners[_iterDispatchers]?.call(); + _listeners[_iterDispatchers].call(); } final lenCount = _listenersOnce.length; for (var i = 0; i < lenCount; i++) { - _listenersOnce.removeAt(0)?.call(); + _listenersOnce.removeAt(0).call(); } } void dispatchWithData(dynamic data) { final len = _listeners.length; for (_iterDispatchers = 0; _iterDispatchers < len; ++_iterDispatchers) { - _listeners[_iterDispatchers]?.call(data); + _listeners[_iterDispatchers].call(data); } final lenCount = _listenersOnce.length; for (var i = 0; i < lenCount; i++) { - _listenersOnce.removeAt(i)?.call(data); + _listenersOnce.removeAt(i).call(data); } } } @@ -81,12 +81,12 @@ class EventSignal { bool hasListeners() => _listeners.isNotEmpty || _listenersOnce.isNotEmpty; void add(EventSignalCallback callback) { - if (callback == null || has(callback)) return; + if (has(callback)) return; _listeners.add(callback); } void addOnce(EventSignalCallback callback) { - if (callback == null || _listeners.contains(callback)) return; + if (_listeners.contains(callback)) return; _listenersOnce.add(callback); } @@ -94,9 +94,9 @@ class EventSignal { final idx = _listeners.indexOf(callback); if (idx > -1) { if (idx <= _iterDispatchers) _iterDispatchers--; - _listeners?.removeAt(idx); + _listeners.removeAt(idx); } else { - _listenersOnce?.remove(callback); + _listenersOnce.remove(callback); } } @@ -108,10 +108,10 @@ class EventSignal { void dispatch(T data) { for (var i = 0; i < _listeners.length; ++i) { // if (id > 0) print('Calling ::: $i - ${_listeners.length}'); - _listeners[i]?.call(data); + _listeners[i].call(data); } for (var i = 0; i < _listenersOnce.length; i++) { - _listenersOnce?.removeAt(i)?.call(data); + _listenersOnce.removeAt(i).call(data); } } } diff --git a/lib/src/extensions/display_object.dart b/lib/src/extensions/display_object.dart index 0af3291..5648b78 100644 --- a/lib/src/extensions/display_object.dart +++ b/lib/src/extensions/display_object.dart @@ -3,23 +3,23 @@ import '../../graphx.dart'; extension DisplayObjectHelpers on GDisplayObject { void centerInStage() { if (!inStage) return; - setPosition(stage.stageWidth / 2, stage.stageHeight / 2); + setPosition(stage!.stageWidth / 2, stage!.stageHeight / 2); } void setProps({ - Object x, - Object y, - Object scaleX, - Object scaleY, - Object scale, - Object rotation, - Object pivotX, - Object pivotY, - Object width, - Object height, - Object skewX, - Object skewY, - Object alpha, + Object? x, + Object? y, + Object? scaleX, + Object? scaleY, + Object? scale, + Object? rotation, + Object? pivotX, + Object? pivotY, + Object? width, + Object? height, + Object? skewX, + Object? skewY, + Object? alpha, double delay = 0, }) { tween( diff --git a/lib/src/geom/color_matrix.dart b/lib/src/geom/color_matrix.dart index bd3f085..0e7d932 100644 --- a/lib/src/geom/color_matrix.dart +++ b/lib/src/geom/color_matrix.dart @@ -50,11 +50,11 @@ class ColorMatrix { // ignore: non_constant_identifier_names static final int LENGTH = IDENTITY_MATRIX.length; - final _storage = List(25); + final _storage = List.filled(25, null); - ColorMatrix([List matrix]) { + ColorMatrix([List? matrix]) { matrix = _fixMatrix(matrix); - copyMatrix(((matrix.length == LENGTH) ? matrix : IDENTITY_MATRIX)); + copyMatrix(((matrix!.length == LENGTH) ? matrix : IDENTITY_MATRIX)); } // public methods: @@ -77,7 +77,7 @@ class ColorMatrix { } void adjustBrightness(double percent) { - if (percent == null || percent == 0 || percent.isNaN) return; + if (percent == 0 || percent.isNaN) return; if (percent >= -1 && percent <= 1) { percent *= 100; } @@ -96,7 +96,7 @@ class ColorMatrix { } void adjustContrast(double percent) { - if (percent == null || percent == 0 || percent.isNaN) return; + if (percent == 0 || percent.isNaN) return; if (percent >= -1 && percent <= 1) { percent *= 100; } @@ -132,7 +132,7 @@ class ColorMatrix { } void adjustSaturation(double percent) { - if (percent == null || percent == 0 || percent.isNaN) return; + if (percent == 0 || percent.isNaN) return; if (percent >= -1 && percent <= 1) { percent *= 100; } @@ -156,7 +156,7 @@ class ColorMatrix { } void adjustHue(double percent) { - if (percent == null || percent == 0 || percent.isNaN) return; + if (percent == 0 || percent.isNaN) return; if (percent >= -1 && percent <= 1) { percent *= 180; } @@ -192,9 +192,9 @@ class ColorMatrix { ]); } - void concat(List pMatrix) { + void concat(List? pMatrix) { pMatrix = _fixMatrix(pMatrix); - if (pMatrix.length != LENGTH) return; + if (pMatrix!.length != LENGTH) return; multiplyMatrix(pMatrix); } @@ -204,20 +204,20 @@ class ColorMatrix { String toString() => "ColorMatrix [ ${_storage.join(" , ")} ]"; /// return a length 20 array (5x4): - List get storage => + List get storage => _storage.sublist(0, math.min(_storage.length, 20)).toList(); /// private methods: /// copy the specified matrix's values to this matrix: - void copyMatrix(List pMatrix) { + void copyMatrix(List? pMatrix) { for (var i = 0; i < LENGTH; i++) { - _storage[i] = pMatrix[i]; + _storage[i] = pMatrix![i]; } } /// multiplies one matrix against another: - void multiplyMatrix(List pMatrix) { - var col = List(25); + void multiplyMatrix(List? pMatrix) { + var col = List.filled(25, null); for (var i = 0; i < 5; i++) { for (var j = 0; j < 5; j++) { @@ -226,7 +226,7 @@ class ColorMatrix { for (var j = 0; j < 5; j++) { var val = 0.0; for (var k = 0; k < 5; k++) { - val += pMatrix[j + k * 5] * col[k]; + val += pMatrix![j + k * 5]! * col[k]!; } _storage[j + i * 5] = val; } @@ -239,7 +239,7 @@ class ColorMatrix { math.min(pLimit, math.max(-pLimit, pVal)); /// makes sure matrixes are 5x5 (25 long): - List _fixMatrix([List pMatrix]) { + List? _fixMatrix([List? pMatrix]) { if (pMatrix == null) return IDENTITY_MATRIX; if (pMatrix.length < LENGTH) { pMatrix = List.from(pMatrix) diff --git a/lib/src/geom/gxmatrix.dart b/lib/src/geom/gxmatrix.dart index 4983d5c..57fb0f5 100644 --- a/lib/src/geom/gxmatrix.dart +++ b/lib/src/geom/gxmatrix.dart @@ -3,16 +3,16 @@ import 'package:flutter/material.dart'; import 'geom.dart'; class GMatrix { - double a, b, c, d, tx, ty; - Matrix4 _native; + double a = 0.0, b = 0.0, c = 0.0, d = 0.0, tx = 0.0, ty = 0.0; + Matrix4? _native; @override String toString() { return 'GxMatrix {a: $a, b: $b, c: $c, d: $d, tx: $tx, ty: $ty}'; } - Matrix4 toNative() { + Matrix4? toNative() { _native ??= Matrix4.identity(); - _native.setValues(a, b, 0, 0, c, d, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1); + _native!.setValues(a, b, 0, 0, c, d, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1); return _native; } @@ -143,16 +143,16 @@ class GMatrix { GMatrix concat(GMatrix matrix) { double a1, c1, tx1; - a1 = a * matrix.a + b * matrix.c; - b = a * matrix.b + b * matrix.d; + a1 = a * matrix.a+ b* matrix.c; + b = a* matrix.b+ b* matrix.d; a = a1; - c1 = c * matrix.a + d * matrix.c; - d = c * matrix.b + d * matrix.d; + c1 = c* matrix.a+ d* matrix.c; + d = c* matrix.b+ d* matrix.d; c = c1; - tx1 = tx * matrix.a + ty * matrix.c + matrix.tx; - ty = tx * matrix.b + ty * matrix.d + matrix.ty; + tx1 = tx* matrix.a+ ty* matrix.c+ matrix.tx; + ty = tx* matrix.b+ ty* matrix.d+ matrix.ty; tx = tx1; return this; @@ -186,26 +186,26 @@ class GMatrix { //} GMatrix invert() { - var n = a * d - b * c; + var n = a* d- b* c; if (n == 0) { a = b = c = d = 0; tx = -tx; ty = -ty; } else { n = 1 / n; - var a1 = d * n; - d = a * n; + var a1 = d* n; + d = a* n; a = a1; b *= -n; c *= -n; - var tx1 = -a * tx - c * ty; - ty = -b * tx - d * ty; + var tx1 = -a* tx- c* ty; + ty = -b* tx- d* ty; tx = tx1; } return this; } - GMatrix scale(double scaleX, [double scaleY]) { + GMatrix scale(double scaleX, [double? scaleY]) { scaleY ??= scaleX; a *= scaleX; b *= scaleY; @@ -225,12 +225,12 @@ class GMatrix { var sinY = math.sin(skewY); var cosY = math.cos(skewY); setTo( - a * cosY - b * sinX, - a * sinY + b * cosX, - c * cosY - d * sinX, - c * sinY + d * cosX, - tx * cosY - ty * sinX, - tx * sinY + ty * cosX, + a* cosY - b* sinX, + a* sinY + b* cosX, + c* cosY - d* sinX, + c* sinY + d* cosX, + tx* cosY - ty* sinX, + tx* sinY + ty* cosX, ); } @@ -238,16 +238,16 @@ class GMatrix { final cos = math.cos(angle); final sin = math.sin(angle); - var a1 = a * cos - b * sin; - b = a * sin + b * cos; + var a1 = a* cos - b* sin; + b = a* sin + b* cos; a = a1; - var c1 = c * cos - d * sin; - d = c * sin + d * cos; + var c1 = c* cos - d* sin; + d = c* sin + d* cos; c = c1; - var tx1 = tx * cos - ty * sin; - ty = tx * sin + ty * cos; + var tx1 = tx* cos - ty* sin; + ty = tx* sin + ty* cos; tx = tx1; } @@ -257,26 +257,26 @@ class GMatrix { return this; } - GPoint transformPoint(GPoint point, [GPoint out]) { + GPoint transformPoint(GPoint point, [GPoint? out]) { return transformCoords(point.x, point.y, out); } - GPoint transformInversePoint(GPoint point, [GPoint out]) { + GPoint transformInversePoint(GPoint point, [GPoint? out]) { return transformInverseCoords(point.x, point.y, out); } - GPoint transformInverseCoords(double x, double y, [GPoint out]) { + GPoint transformInverseCoords(double x, double y, [GPoint? out]) { out ??= GPoint(); - final id = 1 / ((a * d) + (c * -b)); - out.x = (d * id * x) + (-c * id * y) + (((ty * c) - (tx * d)) * id); - out.y = (a * id * y) + (-b * id * x) + (((-ty * a) + (tx * b)) * id); + final id = 1 / ((a* d) + (c* -b)); + out.x = (d* id * x) + (-c* id * y) + (((ty* c) - (tx* d)) * id); + out.y = (a* id * y) + (-b* id * x) + (((-ty* a) + (tx* b)) * id); return out; } - GPoint transformCoords(double x, double y, [GPoint out]) { + GPoint transformCoords(double x, double y, [GPoint? out]) { out ??= GPoint(); - out.x = a * x + c * y + tx; - out.y = d * y + b * x + ty; + out.x = a* x + c* y + tx; + out.y = d* y + b* x + ty; return out; } } diff --git a/lib/src/geom/gxrect.dart b/lib/src/geom/gxrect.dart index 431d7f7..b11c139 100644 --- a/lib/src/geom/gxrect.dart +++ b/lib/src/geom/gxrect.dart @@ -18,7 +18,7 @@ class GRect { return Rect.fromLTWH(x, y, width, height); } - double x, y, width, height; + double x = 0.0, y = 0.0, width = 0.0, height = 0.0; double get bottom => y + height; @@ -54,10 +54,10 @@ class GRect { return this; } - static List _sHelperPositions; + static List? _sHelperPositions; static final _sHelperPoint = GPoint(); - GRect getBounds(GMatrix matrix, [GRect out]) { + GRect getBounds(GMatrix matrix, [GRect? out]) { out ??= GRect(); var minX = 10000000.0; var maxX = -10000000.0; @@ -74,10 +74,10 @@ class GRect { return out.setTo(minX, minY, maxX - minX, maxY - minY); } - List getPositions([List out]) { + List getPositions([List? out]) { out ??= List.generate(4, (i) => GPoint()); for (var i = 0; i < 4; ++i) { - out[i] ??= GPoint(); + out[i]; } out[2].x = out[0].x = left; out[1].y = out[0].y = top; @@ -181,16 +181,16 @@ class GRect { } /// --- Round Rect implementation --- - GxRectCornerRadius _corners; + GxRectCornerRadius? _corners; bool get hasCorners => _corners?.isNotEmpty ?? false; - GxRectCornerRadius get corners { + GxRectCornerRadius? get corners { _corners ??= GxRectCornerRadius(); return _corners; } - set corners(GxRectCornerRadius value) => _corners = value; + set corners(GxRectCornerRadius? value) => _corners = value; - RRect toRoundNative() => corners.toNative(this); + RRect toRoundNative() => corners!.toNative(this); /// Creates a GxRect from a `RRect` assigning the `GxRectCornerRadius` /// properties from the tr, tl, br, bl radiusX axis. @@ -200,7 +200,7 @@ class GRect { nativeRect.top, nativeRect.width, nativeRect.height, - )..corners.setTo( + )..corners!.setTo( nativeRect.tlRadiusX, nativeRect.trRadiusX, nativeRect.brRadiusX, diff --git a/lib/src/input/input_converter.dart b/lib/src/input/input_converter.dart index a2a3324..8f85cd6 100644 --- a/lib/src/input/input_converter.dart +++ b/lib/src/input/input_converter.dart @@ -8,28 +8,28 @@ import 'keyboard_manager.dart'; import 'pointer_manager.dart'; class InputConverter { - final PointerManager pointer; - final KeyboardManager keyboard; + final PointerManager? pointer; + final KeyboardManager? keyboard; InputConverter(this.pointer, this.keyboard); /// mouse stuffs. void pointerEnter(PointerEnterEvent event) { - pointer.$process(PointerEventData( + pointer!.$process(PointerEventData( type: PointerEventType.enter, rawEvent: event, )); } void pointerExit(PointerExitEvent event) { - pointer.$process(PointerEventData( + pointer!.$process(PointerEventData( type: PointerEventType.exit, rawEvent: event, )); } void pointerHover(PointerHoverEvent event) { - pointer.$process(PointerEventData( + pointer!.$process(PointerEventData( type: PointerEventType.hover, rawEvent: event, )); @@ -38,35 +38,35 @@ class InputConverter { /// touchable stuffs. void pointerSignal(PointerSignalEvent event) { - pointer.$process(PointerEventData( + pointer!.$process(PointerEventData( type: PointerEventType.scroll, rawEvent: event as PointerScrollEvent, )); } void pointerMove(PointerMoveEvent event) { - pointer.$process(PointerEventData( + pointer!.$process(PointerEventData( type: PointerEventType.move, rawEvent: event, )); } void pointerCancel(PointerCancelEvent event) { - pointer.$process(PointerEventData( + pointer!.$process(PointerEventData( type: PointerEventType.cancel, rawEvent: event, )); } void pointerUp(PointerUpEvent event) { - pointer.$process(PointerEventData( + pointer!.$process(PointerEventData( type: PointerEventType.up, rawEvent: event, )); } void pointerDown(PointerDownEvent event) { - pointer.$process(PointerEventData( + pointer!.$process(PointerEventData( type: PointerEventType.down, rawEvent: event, )); @@ -74,7 +74,7 @@ class InputConverter { void handleKey(RawKeyEvent event) { final isDown = event is RawKeyDownEvent; - keyboard.$process(KeyboardEventData( + keyboard!.$process(KeyboardEventData( type: isDown ? KeyEventType.down : KeyEventType.up, rawEvent: event, )); diff --git a/lib/src/input/keyboard_manager.dart b/lib/src/input/keyboard_manager.dart index 43ac18e..06399f2 100644 --- a/lib/src/input/keyboard_manager.dart +++ b/lib/src/input/keyboard_manager.dart @@ -4,7 +4,7 @@ import 'package:flutter/services.dart'; import '../../graphx.dart'; class KeyboardManager { - FocusNode _focusNode; + FocusNode? _focusNode; FocusNode get focusNode => _focusNode ??= FocusNode(); @@ -17,12 +17,12 @@ class KeyboardManager { } EventSignal get onDown => _onDown ??= EventSignal(); - EventSignal _onDown; + EventSignal? _onDown; EventSignal get onUp => _onUp ??= EventSignal(); - EventSignal _onUp; + EventSignal? _onUp; - KeyboardEventData _lastEvent; + KeyboardEventData? _lastEvent; bool isPressed(LogicalKeyboardKey key) { return _lastEvent?.rawEvent?.isKeyPressed(key) ?? false; @@ -39,9 +39,9 @@ class KeyboardManager { void $process(KeyboardEventData event) { _lastEvent = event; if (event.type == KeyEventType.down) { - _onDown?.dispatch(event); + _onDown?.dispatch(event as T); } else { - _onUp?.dispatch(event); + _onUp?.dispatch(event as T); } } } diff --git a/lib/src/input/mouse.dart b/lib/src/input/mouse.dart index 1b7dfb4..317337f 100644 --- a/lib/src/input/mouse.dart +++ b/lib/src/input/mouse.dart @@ -6,14 +6,14 @@ export 'package:flutter/rendering.dart' show SystemMouseCursor; /// Accessible from `pointer_manager.dart` abstract class GMouse { - static SystemMouseCursor _cursor; - static SystemMouseCursor _lastCursor; + static SystemMouseCursor? _cursor; + static SystemMouseCursor? _lastCursor; - static SystemMouseCursor get cursor => _cursor; + static SystemMouseCursor? get cursor => _cursor; static void setClickCursor()=> cursor = SystemMouseCursors.click; - static set cursor(SystemMouseCursor value) { + static set cursor(SystemMouseCursor? value) { value ??= SystemMouseCursors.basic; if (_cursor == value) return; if (_cursor != SystemMouseCursors.none) { @@ -24,7 +24,7 @@ abstract class GMouse { 'activateSystemCursor', { 'device': 1, - 'kind': cursor.kind, + 'kind': cursor!.kind, }, ); } diff --git a/lib/src/input/pointer_manager.dart b/lib/src/input/pointer_manager.dart index c8b7541..9f61dbf 100644 --- a/lib/src/input/pointer_manager.dart +++ b/lib/src/input/pointer_manager.dart @@ -4,9 +4,9 @@ import 'package:flutter/services.dart'; import '../../graphx.dart'; class PointerManager { - SystemMouseCursor get cursor => _cursor; + SystemMouseCursor? get cursor => _cursor; - set cursor(SystemMouseCursor val) { + set cursor(SystemMouseCursor? val) { val ??= SystemMouseCursors.basic; if (_cursor == val) return; if (_cursor != SystemMouseCursors.none) { @@ -19,7 +19,7 @@ class PointerManager { 'activateSystemCursor', { 'device': 1, - 'kind': cursor.kind, + 'kind': cursor!.kind, }, ); } @@ -36,37 +36,37 @@ class PointerManager { cursor = val ? _lastCursor : SystemMouseCursors.none; } - SystemMouseCursor _cursor; - SystemMouseCursor _lastCursor; + SystemMouseCursor? _cursor; + SystemMouseCursor? _lastCursor; EventSignal get onInput => _onInput ??= EventSignal(); - EventSignal _onInput; + EventSignal? _onInput; EventSignal get onDown => _onDown ??= EventSignal(); - EventSignal _onDown; + EventSignal? _onDown; EventSignal get onUp => _onUp ??= EventSignal(); - EventSignal _onUp; + EventSignal? _onUp; EventSignal get onCancel => _onCancel ??= EventSignal(); - EventSignal _onCancel; + EventSignal? _onCancel; EventSignal get onMove => _onMove ??= EventSignal(); - EventSignal _onMove; + EventSignal? _onMove; EventSignal get onScroll => _onScroll ??= EventSignal(); - EventSignal _onScroll; + EventSignal? _onScroll; EventSignal get onHover => _onHover ??= EventSignal(); - EventSignal _onHover; + EventSignal? _onHover; EventSignal get onExit => _onExit ??= EventSignal(); - EventSignal _onExit; + EventSignal? _onExit; EventSignal get onEnter => _onEnter ??= EventSignal(); - EventSignal _onEnter; + EventSignal? _onEnter; - PointerEventData _lastEvent; + PointerEventData? _lastEvent; final Map _signalMapper = {}; PointerManager() { @@ -82,16 +82,16 @@ class PointerManager { _signalMapper[PointerEventType.exit] = () => _onExit; } - bool get isDown => _lastEvent?.rawEvent?.down ?? false; + bool get isDown => _lastEvent?.rawEvent.down ?? false; - double get mouseX => _lastEvent?.rawEvent?.localPosition?.dx ?? 0; + double get mouseX => _lastEvent?.rawEvent.localPosition.dx ?? 0; - double get mouseY => _lastEvent?.rawEvent?.localPosition?.dy ?? 0; + double get mouseY => _lastEvent?.rawEvent.localPosition.dy ?? 0; void $process(PointerEventData event) { final signal = _signalMapper[event.type](); _lastEvent = event; - onInput?.dispatch(event); + onInput.dispatch(event as T); signal?.dispatch(event); } @@ -105,6 +105,6 @@ class PointerManager { _onHover?.removeAll(); _onExit?.removeAll(); _onEnter?.removeAll(); - _lastEvent=null; + _lastEvent = null; } } diff --git a/lib/src/io/network_image_loader.dart b/lib/src/io/network_image_loader.dart index efbd18d..5909a01 100644 --- a/lib/src/io/network_image_loader.dart +++ b/lib/src/io/network_image_loader.dart @@ -11,19 +11,19 @@ class NetworkImageEvent { int bytesLoaded = 0; /// only svg responses. - String svgString; - SvgData svgData; + String? svgString; + SvgData? svgData; - double get percentLoaded => bytesLoaded / contentLength; - Image image; + double get percentLoaded => bytesLoaded / contentLength!; + Image? image; double scale = 1; - GTexture _texture; + GTexture? _texture; final http.BaseResponse response; - GTexture get texture { + GTexture? get texture { if (image == null) return null; - _texture ??= GTexture.fromImage(image, scale); + _texture ??= GTexture.fromImage(image!, scale); return _texture; } @@ -32,10 +32,10 @@ class NetworkImageEvent { bool get isImage => image != null; bool get isSvg => svgString != null; - int get contentLength => response.contentLength; + int? get contentLength => response.contentLength; int get statusCode => response.statusCode; - String get reasonPhrase => response.reasonPhrase; - http.BaseRequest get request => response.request; + String? get reasonPhrase => response.reasonPhrase; + http.BaseRequest? get request => response.request; Map get headers => response.headers; bool get isError => statusCode > 300; @@ -57,12 +57,12 @@ class NetworkImageLoader { static Future load( String url, { - int width, - int height, + int? width, + int? height, double scale = 1, - Function(NetworkImageEvent) onComplete, - Function(NetworkImageEvent) onProgress, - Function(NetworkImageEvent) onError, + Function(NetworkImageEvent)? onComplete, + Function(NetworkImageEvent)? onProgress, + Function(NetworkImageEvent)? onError, }) async { Completer completer = Completer(); var loadedBytes = []; @@ -73,52 +73,60 @@ class NetworkImageLoader { var response = _client.send(_request); void dispatchError(NetworkImageEvent eventData) { if (onError != null) { - onError?.call(eventData); + onError.call(eventData); completer.complete(eventData); } else { completer.completeError(eventData); } } - response.asStream().listen((r) { - var eventData = NetworkImageEvent(r); - eventData.scale = scale; - r.stream.listen((chunk) { - loadedBytes.addAll(chunk); - bytesLoaded += chunk.length; - eventData.bytesLoaded = bytesLoaded; - onProgress?.call(eventData); - }, onError: (error) { - dispatchError(eventData); - }, onDone: () async { - if (eventData.isError) { - dispatchError(eventData); - return null; - } - var bytes = Uint8List.fromList(loadedBytes); - final codec = await instantiateImageCodec( - bytes, - allowUpscaling: false, - targetWidth: width, - targetHeight: height, + response.asStream().listen( + (r) { + var eventData = NetworkImageEvent(r); + eventData.scale = scale; + r.stream.listen( + (chunk) { + loadedBytes.addAll(chunk); + bytesLoaded += chunk.length; + eventData.bytesLoaded = bytesLoaded; + onProgress?.call(eventData); + }, + onError: (error) { + dispatchError(eventData); + }, + onDone: () async { + if (eventData.isError) { + dispatchError(eventData); + return null; + } + var bytes = Uint8List.fromList(loadedBytes); + final codec = await instantiateImageCodec( + bytes, + allowUpscaling: false, + targetWidth: width, + targetHeight: height, + ); + eventData.image = (await codec.getNextFrame()).image; + onComplete?.call(eventData); + completer.complete(eventData); + //TODO fix this + // return eventData; + + // Save the file + // File file = new File('$dir/$filename'); + // final Uint8List bytes = Uint8List(r.contentLength); + // int offset = 0; + // for (List chunk in chunks) { + // bytes.setRange(offset, offset + chunk.length, chunk); + // offset += chunk.length; + // } + // await file.writeAsBytes(bytes); + // return; + }, ); - eventData.image = (await codec.getNextFrame()).image; - onComplete?.call(eventData); - completer.complete(eventData); - return eventData; - // Save the file - // File file = new File('$dir/$filename'); - // final Uint8List bytes = Uint8List(r.contentLength); - // int offset = 0; - // for (List chunk in chunks) { - // bytes.setRange(offset, offset + chunk.length, chunk); - // offset += chunk.length; - // } - // await file.writeAsBytes(bytes); - // return; - }); - }); - return completer.future; + }, + ); + return completer.future as FutureOr; // var result = await client.get(url); // var bytes = result.bodyBytes; // final codec = await instantiateImageCodec( diff --git a/lib/src/io/resource_loader.dart b/lib/src/io/resource_loader.dart index cdcdaf7..40ab762 100644 --- a/lib/src/io/resource_loader.dart +++ b/lib/src/io/resource_loader.dart @@ -9,7 +9,7 @@ import 'network_image_loader.dart'; abstract class ResourceLoader { static Map svgs = {}; - static Map textures = {}; + static Map textures = {}; static Map atlases = {}; static Map gifs = {}; @@ -18,7 +18,7 @@ abstract class ResourceLoader { vo.dispose(); } for (var vo in textures.values) { - vo.dispose(); + vo!.dispose(); } for (var vo in atlases.values) { vo.dispose(); @@ -28,26 +28,26 @@ abstract class ResourceLoader { } } - static GTexture getTexture(String cacheId) { + static GTexture? getTexture(String cacheId) { return textures[cacheId]; } - static SvgData getSvg(String cacheId) { + static SvgData? getSvg(String cacheId) { return svgs[cacheId]; } - static GTextureAtlas getAtlas(String cacheId) { + static GTextureAtlas? getAtlas(String cacheId) { return atlases[cacheId]; } - static GifAtlas getGif(String cacheId) { + static GifAtlas? getGif(String cacheId) { return gifs[cacheId]; } - static Future loadGif( + static Future loadGif( String path, { double resolution = 1.0, - String cacheId, + String? cacheId, }) async { if (cacheId != null && gifs.containsKey(cacheId)) { return gifs[cacheId]; @@ -56,7 +56,6 @@ abstract class ResourceLoader { final data = await rootBundle.load(path); final bytes = Uint8List.view(data.buffer); final codec = await ui.instantiateImageCodec(bytes, allowUpscaling: false); - resolution ??= GTextureUtils.resolution; final atlas = GifAtlas(); atlas.scale = resolution; @@ -73,12 +72,12 @@ abstract class ResourceLoader { return atlas; } - static Future loadNetworkTextureSimple( + static Future loadNetworkTextureSimple( String url, { - int width, - int height, + int? width, + int? height, double resolution = 1.0, - String cacheId, + String? cacheId, }) async { if (cacheId != null && textures.containsKey(cacheId)) { return textures[cacheId]; @@ -123,15 +122,15 @@ abstract class ResourceLoader { // return response.svgData; // } - static Future loadNetworkTexture( + static Future loadNetworkTexture( String url, { - int width, - int height, + int? width, + int? height, double resolution = 1.0, - String cacheId, - Function(NetworkImageEvent) onComplete, - Function(NetworkImageEvent) onProgress, - Function(NetworkImageEvent) onError, + String? cacheId, + Function(NetworkImageEvent)? onComplete, + Function(NetworkImageEvent)? onProgress, + Function(NetworkImageEvent)? onError, }) async { if (cacheId != null && textures.containsKey(cacheId)) { return textures[cacheId]; @@ -151,10 +150,10 @@ abstract class ResourceLoader { return response.texture; } - static Future loadTexture( + static Future loadTexture( String path, [ double resolution = 1.0, - String cacheId, + String? cacheId, ]) async { if (cacheId != null && textures.containsKey(cacheId)) { return textures[cacheId]; @@ -175,11 +174,11 @@ abstract class ResourceLoader { // return svgs[cacheId]; // } - static Future loadTextureAtlas( + static Future loadTextureAtlas( String imagePath, { - String dataPath, + String? dataPath, double resolution = 1.0, - String cacheId, + String? cacheId, }) async { if (cacheId != null && atlases.containsKey(cacheId)) { return atlases[cacheId]; @@ -210,8 +209,8 @@ abstract class ResourceLoader { /// load local assets. static Future loadImage( String path, { - int targetWidth, - int targetHeight, + int? targetWidth, + int? targetHeight, }) async { final data = await rootBundle.load(path); final bytes = Uint8List.view(data.buffer); diff --git a/lib/src/log/trace.dart b/lib/src/log/trace.dart index ce729f8..040c1e9 100644 --- a/lib/src/log/trace.dart +++ b/lib/src/log/trace.dart @@ -17,7 +17,7 @@ String _tagPaddingChar = ', '; /// [tagPaddingCount] should be applied manually if you wanna have a cleaner /// tabulated view. void traceConfig({ - String customTag, + String? customTag, int tagPaddingCount = 0, String tagPaddingChar = ' ', bool showFilename = false, @@ -30,12 +30,12 @@ void traceConfig({ _tagPaddingCount = tagPaddingCount; _tagPaddingChar = tagPaddingChar; _customTag = customTag ?? 'graphx™🌀'; - _showFilename = showFilename ?? false; - _showLinenumber = showLinenumber ?? false; - _showClassname = showClassname ?? false; - _showMethodname = showMethodname ?? false; - _showOutsideTag = showOutsideTag ?? false; - _separator = argsSeparator ?? ', '; + _showFilename = showFilename; + _showLinenumber = showLinenumber; + _showClassname = showClassname; + _showMethodname = showMethodname; + _showOutsideTag = showOutsideTag; + _separator = argsSeparator; _useStack = _showFilename || _showClassname || _showMethodname; } @@ -43,16 +43,17 @@ void traceConfig({ /// `trace` works. It has up to 10 arguments slots so you can pass any type of /// object to be printed. The way trace() shows output in the console can be /// defined with [traceConfig()]. -void trace(Object arg1, [ - Object arg2, - Object arg3, - Object arg4, - Object arg5, - Object arg6, - Object arg7, - Object arg8, - Object arg9, - Object arg10, +void trace( + Object arg1, [ + Object? arg2, + Object? arg3, + Object? arg4, + Object? arg5, + Object? arg6, + Object? arg7, + Object? arg8, + Object? arg9, + Object? arg10, ]) { ++_traceCount; final outputList = [ @@ -118,8 +119,7 @@ String _stackCommon(String stack) { var callLine = locationParts[1]; var filename = filePath.substring( filePath.lastIndexOf('/') + 1, filePath.lastIndexOf('.')); - String methodName, - className = ''; + String methodName, className = ''; var output = ''; //ˇ if (_showFilename) { output += '$filename '; @@ -138,7 +138,7 @@ String _stackCommon(String stack) { className = elements.removeAt(0); methodName = elements.join('.'); methodName = - '${methodName.replaceAll(_anonymousMethodTag, '<⁕>')}$_sufixCall'; + '${methodName.replaceAll(_anonymousMethodTag, '<⁕>')}$_sufixCall'; if (_showClassname) { output += '‣ $className '; } @@ -147,4 +147,4 @@ String _stackCommon(String stack) { } } return output; -} \ No newline at end of file +} diff --git a/lib/src/math.dart b/lib/src/math.dart index c88d7d6..09346ed 100644 --- a/lib/src/math.dart +++ b/lib/src/math.dart @@ -83,6 +83,8 @@ abstract class Math { /// Evaluates `a` and `b` and returns the largest value. static final max = m.max; + // * OLD code + // static final max = m.max as T Function(T, T); /// Evaluates `a` and `b` and returns the smallest value. static final min = m.min; @@ -92,22 +94,22 @@ abstract class Math { /// Returns the ceiling of the specified number or expression. /// Parameter `keepDouble` enforces the return type to be `double`. - static num ceil(double value, [bool keepDouble = true]) { - return keepDouble ? value?.ceilToDouble() : value?.ceil(); + static num? ceil(double value, [bool keepDouble = true]) { + return keepDouble ? value.ceilToDouble() : value.ceil(); } /// Returns the floor of the number or expression specified in the parameter /// `value`. /// Parameter `keepDouble` enforces the return type to be `double`. - static num floor(double value, [bool keepDouble = true]) { - return keepDouble ? value?.floorToDouble() : value?.floor(); + static num? floor(double value, [bool keepDouble = true]) { + return keepDouble ? value.floorToDouble() : value.floor(); } /// Rounds the value of the parameter `value` up or down to the nearest /// integer and returns the value. /// Parameter `keepDouble` enforces the return type to be `double`. - static num round(double value, [bool keepDouble = true]) { - return keepDouble ? value?.roundToDouble() : value?.round(); + static num? round(double value, [bool keepDouble = true]) { + return keepDouble ? value.roundToDouble() : value.round(); } /// Computes and returns an absolute value for the number specified by @@ -147,7 +149,7 @@ abstract class Math { static double randomRangeClamp(num min, num max, num clamp) => (randomRange(min.toDouble(), max.toDouble()) / clamp.toDouble()) .roundToDouble() * - clamp.toDouble(); + clamp.toDouble(); /// Returns a pseudo-random `int` number between parameters `min` and /// `max`, clamping the returned value to `clamp`. @@ -155,7 +157,7 @@ abstract class Math { /// And `min` > `max`. static int randomRangeIntClamp(num min, num max, num clamp) => (randomRangeInt(min.toInt(), max.toInt()) / clamp.toInt()).round() * - clamp.toInt(); + clamp.toInt(); static double norm(num value, num min, num max) { return (value - min) / (max - min); diff --git a/lib/src/render/filters/blur_filter.dart b/lib/src/render/filters/blur_filter.dart index 3e570d9..16f64e6 100644 --- a/lib/src/render/filters/blur_filter.dart +++ b/lib/src/render/filters/blur_filter.dart @@ -17,7 +17,7 @@ class GBaseFilter { void buildFilter() {} bool get isValid => true; - GRect layerBounds; + GRect? layerBounds; void expandBounds(GRect layerBounds, GRect outputBounds) { this.layerBounds = layerBounds; } @@ -51,8 +51,8 @@ class GBlurFilter extends GBaseFilter { this.blurY = blurY; } - ui.MaskFilter _maskFilter; - ui.ImageFilter _imageFilter; + ui.MaskFilter? _maskFilter; + ui.ImageFilter? _imageFilter; final _rect = GRect(); GRect get filterRect => _rect; @@ -76,7 +76,7 @@ class GBlurFilter extends GBaseFilter { /// if it goes under a threshold (I tried .2 and lower), it flickers. /// idk which logic uses, but 1.0 seems like a stable min number for the /// mask. - _maskFilter = ui.MaskFilter.blur(style ?? ui.BlurStyle.inner, maxBlur); + _maskFilter = ui.MaskFilter.blur(style, maxBlur); _imageFilter = ui.ImageFilter.blur(sigmaX: _blurX, sigmaY: _blurY); } diff --git a/lib/src/render/filters/color_filter.dart b/lib/src/render/filters/color_filter.dart index 7359fcd..23ec3e2 100644 --- a/lib/src/render/filters/color_filter.dart +++ b/lib/src/render/filters/color_filter.dart @@ -48,7 +48,7 @@ class GColorFilters { } class GColorMatrixFilter extends GBaseFilter { - ColorFilter colorFilter; + ColorFilter? colorFilter; GColorMatrixFilter(this.colorFilter); diff --git a/lib/src/render/filters/composer_filter.dart b/lib/src/render/filters/composer_filter.dart index ed3fe90..c93eeb6 100644 --- a/lib/src/render/filters/composer_filter.dart +++ b/lib/src/render/filters/composer_filter.dart @@ -9,7 +9,7 @@ class GComposerFilter extends GBaseFilter { @override void resolvePaint(ui.Paint paint) {} - void process(ui.Canvas canvas, Function applyPaint, [int processCount = 1]) { + void process(ui.Canvas? canvas, Function applyPaint, [int processCount = 1]) { /// todo: figure the area. // canvas.saveLayer(null, paint); // canvas.translate(_dx, _dy); diff --git a/lib/src/render/filters/dropshadow_filter.dart b/lib/src/render/filters/dropshadow_filter.dart index 67470e1..b8e2500 100644 --- a/lib/src/render/filters/dropshadow_filter.dart +++ b/lib/src/render/filters/dropshadow_filter.dart @@ -27,7 +27,7 @@ class GDropShadowFilter extends GComposerFilter { Color get color => _color; double _dx = 0, _dy = 0; - set color(Color value) { + set color(Color? value) { if (_color == value) return; _color = value ?? kColorBlack; dirty = true; @@ -41,7 +41,6 @@ class GDropShadowFilter extends GComposerFilter { } set distance(double value) { - value ??= 0; if (_distance == value) return; _distance = value; _calculatePosition(); @@ -81,9 +80,9 @@ class GDropShadowFilter extends GComposerFilter { this.hideObject = hideObject; } - ColorFilter _colorFilter; - MaskFilter _maskFilter; - ImageFilter _imageFilter; + ColorFilter? _colorFilter; + MaskFilter? _maskFilter; + ImageFilter? _imageFilter; final _rect = GRect(); GRect get filterRect => _rect; @@ -117,7 +116,7 @@ class GDropShadowFilter extends GComposerFilter { /// if it goes under a threshold (I tried .2 and lower), it flickers. /// idk which logic uses, but 1.0 seems like a stable min number for the /// mask. - _maskFilter = MaskFilter.blur(style ?? BlurStyle.inner, maxBlur); + _maskFilter = MaskFilter.blur(style, maxBlur); _imageFilter = ImageFilter.blur( sigmaX: Math.max(_blurX, _minBlur), sigmaY: Math.max(_blurY, _minBlur), @@ -132,8 +131,8 @@ class GDropShadowFilter extends GComposerFilter { } @override - void process(Canvas canvas, Function applyPaint, [int processCount = 1]) { - canvas.saveLayer(null, paint); + void process(Canvas? canvas, Function applyPaint, [int processCount = 1]) { + canvas!.saveLayer(null, paint); // final bb = layerBounds.clone(); // bb.inflate(_strength, _strength); canvas.translate(_dx, _dy); diff --git a/lib/src/render/filters/glow_filter.dart b/lib/src/render/filters/glow_filter.dart index 6031658..739fbd5 100644 --- a/lib/src/render/filters/glow_filter.dart +++ b/lib/src/render/filters/glow_filter.dart @@ -23,7 +23,7 @@ class GlowFilter extends GComposerFilter { ui.Color get color => _color; - set color(ui.Color value) { + set color(ui.Color? value) { if (_color == value) return; _color = value ?? kColorBlack; dirty = true; @@ -53,9 +53,9 @@ class GlowFilter extends GComposerFilter { this.hideObject = hideObject; } - ui.ColorFilter _colorFilter; - ui.MaskFilter _maskFilter; - ui.ImageFilter _imageFilter; + ui.ColorFilter? _colorFilter; + ui.MaskFilter? _maskFilter; + ui.ImageFilter? _imageFilter; final _rect = GRect(); @@ -81,7 +81,7 @@ class GlowFilter extends GComposerFilter { maxBlur = Math.max(_blurX, _blurY) / 2; if (maxBlur < 1) maxBlur = 1; } - _maskFilter = ui.MaskFilter.blur(style ?? ui.BlurStyle.normal, maxBlur); + _maskFilter = ui.MaskFilter.blur(style, maxBlur); _imageFilter = ui.ImageFilter.blur(sigmaX: _blurX, sigmaY: _blurY); _colorFilter = ui.ColorFilter.mode( _color.withAlpha(255), @@ -98,13 +98,13 @@ class GlowFilter extends GComposerFilter { // var _iterations = 0; @override - void process(ui.Canvas canvas, Function applyPaint, [int processCount = 1]) { + void process(ui.Canvas? canvas, Function applyPaint, [int processCount = 1]) { // trace('rect is: ', _outBounds); // var a = GxRect(0, 0, layerBounds.width - layerBounds.x, // layerBounds.height - layerBounds.y); // trace(layerBounds, _rect); // canvas.saveLayer(layerBounds.toNative(), paint); - canvas.saveLayer(null, paint); + canvas!.saveLayer(null, paint); applyPaint(canvas); canvas.restore(); if (++processCount <= iterations) { diff --git a/lib/src/render/graphics.dart b/lib/src/render/graphics.dart index a1a71a4..1d3a5d6 100644 --- a/lib/src/render/graphics.dart +++ b/lib/src/render/graphics.dart @@ -10,17 +10,17 @@ enum GradientType { } class Graphics with RenderUtilMixin implements GxRenderable { - final _drawingQueue = []; - GraphicsDrawingData _currentDrawing = GraphicsDrawingData(null, Path()); + final _drawingQueue = []; + GraphicsDrawingData? _currentDrawing = GraphicsDrawingData(null, Path()); double alpha = 1; static final GMatrix _helperMatrix = GMatrix(); - Graphics mask; + Graphics? mask; bool isMask = false; - Path get _path => _currentDrawing.path; + Path? get _path => _currentDrawing!.path; static final Path stageRectPath = Path(); @@ -31,16 +31,16 @@ class Graphics with RenderUtilMixin implements GxRenderable { void dispose() { mask = null; - _drawingQueue?.clear(); + _drawingQueue.clear(); _currentDrawing = null; } - List get drawingQueue => _drawingQueue; + List get drawingQueue => _drawingQueue; void copyFrom(Graphics other, [bool deepClone = false]) { _drawingQueue.clear(); for (final command in other._drawingQueue) { - _drawingQueue.add(command.clone(deepClone, deepClone)); + _drawingQueue.add(command!.clone(deepClone, deepClone)); } mask = other.mask; alpha = other.alpha; @@ -52,7 +52,7 @@ class Graphics with RenderUtilMixin implements GxRenderable { /// a bigger CPU hit. /// In [Graphics] "paths" are separated by [Paint] drawing commands: /// [beginFill()] and [lineStyle()] - List getAllBounds([List out]) { + List getAllBounds([List? out]) { out ??= []; for (var e in _drawingQueue) { final pathRect = e?.path?.getBounds(); @@ -63,8 +63,8 @@ class Graphics with RenderUtilMixin implements GxRenderable { } @override - GRect getBounds([GRect out]) { - Rect r; + GRect getBounds([GRect? out]) { + Rect? r; for (var e in _drawingQueue) { final pathRect = e?.path?.getBounds(); if (pathRect == null) break; @@ -90,7 +90,7 @@ class Graphics with RenderUtilMixin implements GxRenderable { localPoint.y, ); for (var e in _drawingQueue) { - if (e.path.contains(point)) return true; + if (e!.path!.contains(point)) return true; } return false; } else { @@ -111,7 +111,7 @@ class Graphics with RenderUtilMixin implements GxRenderable { Graphics beginBitmapFill( GTexture texture, [ - GMatrix matrix, + GMatrix? matrix, bool repeat = false, bool smooth = false, ]) { @@ -122,13 +122,13 @@ class Graphics with RenderUtilMixin implements GxRenderable { var tileMode = !repeat ? TileMode.clamp : TileMode.repeated; matrix ??= _helperMatrix; fill.shader = ImageShader( - texture.root, + texture.root!, tileMode, tileMode, - matrix.toNative().storage, + matrix.toNative()!.storage, ); _addFill(fill); - _currentDrawing.shaderTexture = texture; + _currentDrawing!.shaderTexture = texture; return this; } @@ -162,11 +162,11 @@ class Graphics with RenderUtilMixin implements GxRenderable { double thickness = 0.0, Color color = kColorBlack, bool pixelHinting = true, - StrokeCap caps, - StrokeJoin joints, + StrokeCap? caps, + StrokeJoin? joints, double miterLimit = 3.0, ]) { - alpha ??= 1.0; + alpha; alpha = alpha.clamp(0.0, 1.0); final paint = Paint(); paint.style = PaintingStyle.stroke; @@ -188,12 +188,12 @@ class Graphics with RenderUtilMixin implements GxRenderable { Graphics beginGradientFill( GradientType type, List colors, { - List ratios, - Alignment begin, - Alignment end, + List? ratios, + Alignment? begin, + Alignment? end, double rotation = 0, TileMode tileMode = TileMode.clamp, - Rect gradientBox, + Rect? gradientBox, /// only radial double radius = 0.5, @@ -221,9 +221,9 @@ class Graphics with RenderUtilMixin implements GxRenderable { paint.isAntiAlias = true; _addFill(paint); if (gradientBox != null) { - _currentDrawing.fill.shader = gradient.createShader(gradientBox); + _currentDrawing!.fill!.shader = gradient.createShader(gradientBox); } else { - _currentDrawing.gradient = gradient; + _currentDrawing!.gradient = gradient; } return this; } @@ -231,9 +231,9 @@ class Graphics with RenderUtilMixin implements GxRenderable { Gradient _createGradient( GradientType type, List colors, [ - List ratios, - Alignment begin, - Alignment end, + List? ratios, + Alignment? begin, + Alignment? end, double rotation = 0, /// only radial @@ -287,9 +287,9 @@ class Graphics with RenderUtilMixin implements GxRenderable { Graphics lineGradientStyle( GradientType type, List colors, { - List ratios, - Alignment begin, - Alignment end, + List? ratios, + Alignment? begin, + Alignment? end, double rotation = 0, /// only `GradientType.radial` @@ -301,14 +301,14 @@ class Graphics with RenderUtilMixin implements GxRenderable { double sweepEndAngle = 6.2832, /// manually define the bounding box of the Gradient shader. - Rect gradientBox, + Rect? gradientBox, /// when the gradient box is different than the object bounds, you can /// see the `tileMode` behaviour. TileMode tileMode = TileMode.clamp, }) { /// actual paint must be stroke. - assert(_currentDrawing.fill.style == PaintingStyle.stroke); + assert(_currentDrawing!.fill!.style == PaintingStyle.stroke); final gradient = _createGradient( type, @@ -324,48 +324,48 @@ class Graphics with RenderUtilMixin implements GxRenderable { tileMode, ); if (gradientBox != null) { - _currentDrawing.fill.shader = gradient.createShader(gradientBox); + _currentDrawing!.fill!.shader = gradient.createShader(gradientBox); } else { - _currentDrawing.gradient = gradient; + _currentDrawing!.gradient = gradient; } return this; } Graphics lineBitmapStyle( GTexture texture, [ - GMatrix matrix, + GMatrix? matrix, bool repeat = true, bool smooth = false, ]) { /// actual paint must be stroke. - assert(_currentDrawing.fill.style == PaintingStyle.stroke); + assert(_currentDrawing!.fill!.style == PaintingStyle.stroke); if (_holeMode) return this; - final fill = _currentDrawing.fill; + final fill = _currentDrawing!.fill!; fill.isAntiAlias = smooth; var tileMode = !repeat ? TileMode.clamp : TileMode.repeated; matrix ??= _helperMatrix; fill.shader = ImageShader( - texture.root, + texture.root!, tileMode, tileMode, - matrix.toNative().storage, + matrix.toNative()!.storage, ); // _addFill(fill); return this; } Graphics moveTo(double x, double y) { - _path.moveTo(x, y); + _path!.moveTo(x, y); return this; } Graphics lineTo(double x, double y) { - _path.lineTo(x, y); + _path!.lineTo(x, y); return this; } Graphics closePath() { - _path.close(); + _path!.close(); return this; } @@ -377,7 +377,8 @@ class Graphics with RenderUtilMixin implements GxRenderable { double anchorX, double anchorY, ) { - _path.cubicTo(controlX1, controlY1, controlX2, controlY2, anchorX, anchorY); + _path! + .cubicTo(controlX1, controlY1, controlX2, controlY2, anchorX, anchorY); return this; } @@ -387,7 +388,7 @@ class Graphics with RenderUtilMixin implements GxRenderable { double anchorX, double anchorY, ) { - _path.quadraticBezierTo(controlX, controlY, anchorX, anchorY); + _path!.quadraticBezierTo(controlX, controlY, anchorX, anchorY); return this; } @@ -400,9 +401,9 @@ class Graphics with RenderUtilMixin implements GxRenderable { bool relative = false, ]) { if (!relative) { - _path.conicTo(controlX, controlY, anchorX, anchorY, weight); + _path!.conicTo(controlX, controlY, anchorX, anchorY, weight); } else { - _path.relativeConicTo(controlX, controlY, anchorX, anchorY, weight); + _path!.relativeConicTo(controlX, controlY, anchorX, anchorY, weight); } return this; } @@ -410,13 +411,13 @@ class Graphics with RenderUtilMixin implements GxRenderable { Graphics drawCircle(double x, double y, double radius) { final pos = Offset(x, y); final circ = Rect.fromCircle(center: pos, radius: radius); - _path.addOval(circ); + _path!.addOval(circ); return this; } Graphics drawEllipse(double x, double y, double radiusX, double radiusY) { final pos = Offset(x, y); - _path.addOval( + _path!.addOval( Rect.fromCenter( center: pos, width: radiusX * 2, @@ -427,13 +428,13 @@ class Graphics with RenderUtilMixin implements GxRenderable { } Graphics drawGRect(GRect rect) { - _path.addRect(rect.toNative()); + _path!.addRect(rect.toNative()); return this; } Graphics drawRect(double x, double y, double width, double height) { final r = Rect.fromLTWH(x, y, width, height); - _path.addRect(r); + _path!.addRect(r); return this; } @@ -447,7 +448,7 @@ class Graphics with RenderUtilMixin implements GxRenderable { double bottomLeftRadius = 0, double bottomRightRadius = 0, ]) { - _path.addRRect( + _path!.addRRect( RRect.fromLTRBAndCorners( x, y, @@ -468,7 +469,7 @@ class Graphics with RenderUtilMixin implements GxRenderable { double width, double height, double ellipseWidth, [ - double ellipseHeight, + double? ellipseHeight, ]) { final r = RRect.fromLTRBXY( x, @@ -478,17 +479,17 @@ class Graphics with RenderUtilMixin implements GxRenderable { ellipseWidth, ellipseHeight ?? ellipseWidth, ); - _path.addRRect(r); + _path!.addRRect(r); return this; } Graphics drawPoly(List points, [bool closePolygon = true]) { final len = points.length; - final list = List(len); + final list = List.filled(len, null); for (var i = 0; i < len; ++i) { list[i] = points[i].toNative(); } - _path.addPolygon(list, true); + _path!.addPolygon(list as List, true); return this; } @@ -496,7 +497,7 @@ class Graphics with RenderUtilMixin implements GxRenderable { final offset = Offset(x, y); if (modifyPreviousPaths) { for (var command in _drawingQueue) { - command?.path = command?.path?.shift(offset); + command?.path = command.path?.shift(offset); } } else { _currentDrawing?.path = _currentDrawing?.path?.shift(offset); @@ -511,7 +512,7 @@ class Graphics with RenderUtilMixin implements GxRenderable { double startAngle, double sweepAngle, ) { - _path.addArc( + _path!.addArc( Rect.fromCenter( center: Offset(cx, cy), width: radiusX * 2, @@ -533,14 +534,14 @@ class Graphics with RenderUtilMixin implements GxRenderable { ]) { if (sweepAngle == 0) return this; if (!moveTo) { - _path.arcTo( + _path!.arcTo( Rect.fromCircle(center: Offset(cx, cy), radius: radius), startAngle, sweepAngle, false, ); } else { - _path.addArc( + _path!.addArc( Rect.fromCircle(center: Offset(cx, cy), radius: radius), startAngle, sweepAngle, @@ -560,7 +561,7 @@ class Graphics with RenderUtilMixin implements GxRenderable { ]) { if (radius == 0) return this; if (relativeMoveTo) { - _path.arcToPoint( + _path!.arcToPoint( Offset(endX, endY), radius: Radius.circular(radius), clockwise: clockwise, @@ -568,7 +569,7 @@ class Graphics with RenderUtilMixin implements GxRenderable { rotation: rotation, ); } else { - _path.relativeArcToPoint( + _path!.relativeArcToPoint( Offset(endX, endY), radius: Radius.circular(radius), clockwise: clockwise, @@ -587,14 +588,14 @@ class Graphics with RenderUtilMixin implements GxRenderable { int sides, [ double rotation = 0, ]) { - final points = List(sides); + final points = List.filled(sides, Offset(0, 0)); final rel = 2 * Math.PI / sides; for (var i = 1; i <= sides; ++i) { final px = x + radius * Math.cos(i * rel + rotation); final py = y + radius * Math.sin(i * rel + rotation); points[i - 1] = Offset(px, py); } - _path.addPolygon(points, true); + _path!.addPolygon(points as List, true); return this; } @@ -603,7 +604,7 @@ class Graphics with RenderUtilMixin implements GxRenderable { double y, int points, double radius, [ - double innerRadius, + double? innerRadius, double rotation = 0, ]) { innerRadius ??= radius / 2; @@ -619,7 +620,7 @@ class Graphics with RenderUtilMixin implements GxRenderable { y + (r * Math.sin(a)), )); } - _path.addPolygon(polys, true); + _path!.addPolygon(polys, true); return this; } @@ -640,24 +641,24 @@ class Graphics with RenderUtilMixin implements GxRenderable { Graphics endHole([bool applyToCurrentQueue = false]) { _holeMode = false; // apply to previous elements. - if (!_currentDrawing.isHole) { + if (!_currentDrawing!.isHole) { throw "Can't endHole() without starting a beginHole() command."; // return this; } - final _holePath = _path; + final _holePath = _path!; _holePath.close(); _currentDrawing = _drawingQueue.last; if (!applyToCurrentQueue) { - _currentDrawing.path = Path.combine( + _currentDrawing!.path = Path.combine( PathOperation.difference, - _path, + _path!, _holePath, ); } else { for (final cmd in _drawingQueue) { - cmd.path = Path.combine( + cmd!.path = Path.combine( PathOperation.difference, - cmd.path, + cmd.path!, _holePath, ); } @@ -668,11 +669,11 @@ class Graphics with RenderUtilMixin implements GxRenderable { void paintWithFill(Canvas canvas, Paint fill) { if (!_isVisible) return; for (var graph in _drawingQueue) { - if (graph.hasPicture) { - canvas.drawPicture(graph.picture); + if (graph!.hasPicture) { + canvas.drawPicture(graph.picture!); return; } - canvas.drawPath(graph.path, fill); + canvas.drawPath(graph.path!, fill); } } @@ -681,7 +682,7 @@ class Graphics with RenderUtilMixin implements GxRenderable { if (SystemUtils.usingSkia) { for (var graph in _drawingQueue) { /// unsupported on web. - output = Path.combine(PathOperation.union, output, graph.path); + output = Path.combine(PathOperation.union, output, graph!.path!); } } else { trace('Graphics.getPaths() is unsupported in the current platform.'); @@ -690,11 +691,11 @@ class Graphics with RenderUtilMixin implements GxRenderable { } @override - void paint(Canvas canvas) { + void paint(Canvas? canvas) { // TODO : add mask support. if (isMask) { for (var graph in _drawingQueue) { - canvas.clipPath(graph.path, doAntiAlias: false); + canvas!.clipPath(graph!.path!, doAntiAlias: false); } return; } @@ -703,51 +704,51 @@ class Graphics with RenderUtilMixin implements GxRenderable { // trace("en", _drawingQueue.length); for (var graph in _drawingQueue) { - if (graph.hasPicture) { - canvas.drawPicture(graph.picture); + if (graph!.hasPicture) { + canvas!.drawPicture(graph.picture!); break; } - final fill = graph.fill; + final fill = graph.fill!; final baseColor = fill.color; if (baseColor.alpha == 0) break; /// calculate gradient. if (graph.hasGradient) { - Rect _bounds; + Rect? _bounds; if (graph.hasVertices) { - _bounds = graph.vertices.getBounds(); + _bounds = graph.vertices!.getBounds(); } else { - _bounds = graph.path.getBounds(); + _bounds = graph.path!.getBounds(); } /// TODO: try if this works to change the gradient /// opacity from the Shape. fill.color = baseColor.withOpacity(alpha); - fill.shader = graph.gradient.createShader(_bounds); + fill.shader = graph.gradient!.createShader(_bounds!); } else { if (alpha != 1) { fill.color = baseColor.withOpacity(baseColor.opacity * alpha); } } if (graph.hasVertices) { - if (graph.vertices.uvtData != null && graph.shaderTexture != null) { - graph.vertices.calculateUvt(graph.shaderTexture); + if (graph.vertices!.uvtData != null && graph.shaderTexture != null) { + graph.vertices!.calculateUvt(graph.shaderTexture); } if (fill.style == PaintingStyle.stroke) { - canvas.drawRawPoints( + canvas!.drawRawPoints( ui.PointMode.lines, - graph.vertices.rawPoints, + graph.vertices!.rawPoints!, fill, ); } else { - canvas.drawVertices( - graph.vertices.rawData, - graph.vertices.blendMode ?? BlendMode.src, + canvas!.drawVertices( + graph.vertices!.rawData!, + graph.vertices!.blendMode, fill, ); } } else { - canvas.drawPath(graph.path, fill); + canvas!.drawPath(graph.path!, fill); } fill.color = baseColor; @@ -756,8 +757,8 @@ class Graphics with RenderUtilMixin implements GxRenderable { void _addFill(Paint fill) { /// same type, create path. - Path path; - if (_currentDrawing.isSameType(fill)) { + Path? path; + if (_currentDrawing!.isSameType(fill)) { path = Path(); } else { path = _currentDrawing?.path; @@ -779,11 +780,11 @@ class Graphics with RenderUtilMixin implements GxRenderable { void pushData( GraphicsDrawingData data, [ bool asCurrent = false, - double x, - double y, + double? x, + double? y, ]) { if (x != null && y != null && data.path != null) { - data.path = data.path.shift(Offset(x, y)); + data.path = data.path!.shift(Offset(x, y)); } _drawingQueue.add(data); if (asCurrent) _currentDrawing = data; @@ -792,7 +793,7 @@ class Graphics with RenderUtilMixin implements GxRenderable { /// removes the last `GraphicsDrawingData` from the drawing queue... /// This should be used only if you are operating with `Path` and `Paint` /// directly. - GraphicsDrawingData popData() { + GraphicsDrawingData? popData() { return _drawingQueue.removeLast(); } @@ -815,9 +816,9 @@ class Graphics with RenderUtilMixin implements GxRenderable { Path path, [ double x = 0, double y = 0, - GMatrix transform, + GMatrix? transform, ]) { - _path.addPath( + _path!.addPath( path, Offset(x, y), matrix4: transform?.toNative()?.storage, @@ -830,16 +831,16 @@ class Graphics with RenderUtilMixin implements GxRenderable { /// Doesn't use a Path(), but drawVertices()... Graphics drawTriangles( List vertices, [ - List indices, - List uvtData, - List hexColors, + List? indices, + List? uvtData, + List? hexColors, BlendMode blendMode = BlendMode.src, Culling culling = Culling.positive, ]) { /// will only work if it has a fill. assert(_currentDrawing != null); - assert(_currentDrawing.fill != null); - _currentDrawing.vertices = _GraphVertices( + assert(_currentDrawing!.fill != null); + _currentDrawing!.vertices = _GraphVertices( ui.VertexMode.triangles, vertices, indices, @@ -853,19 +854,19 @@ class Graphics with RenderUtilMixin implements GxRenderable { } class GraphicsDrawingData { - Path path; - Paint fill; + Path? path; + Paint? fill; - Gradient gradient; - ui.Picture picture; + Gradient? gradient; + ui.Picture? picture; bool isHole = false; /// for drawVertices() BlendMode blendMode = BlendMode.src; - _GraphVertices vertices; + _GraphVertices? vertices; /// temporal storage to use with _GraphVertices - GTexture shaderTexture; + GTexture? shaderTexture; bool get hasVertices => vertices != null; @@ -883,7 +884,7 @@ class GraphicsDrawingData { bool clonePath = false, ]) { final _fill = cloneFill ? fill?.clone() : fill; - final _path = clonePath ? (path != null ? Path.from(path) : null) : path; + final _path = clonePath ? (path != null ? Path.from(path!) : null) : path; final _vertices = vertices; return GraphicsDrawingData(_fill, _path) ..gradient = gradient @@ -892,11 +893,11 @@ class GraphicsDrawingData { ..vertices = _vertices; } - bool isSameType(Paint otherFill) => fill?.style == otherFill?.style ?? false; + bool isSameType(Paint otherFill) => fill?.style == otherFill.style; } extension ExtSkiaPaintCustom on Paint { - Paint clone([Paint out]) { + Paint clone([Paint? out]) { out ??= Paint(); out.maskFilter = maskFilter; out.blendMode = blendMode; @@ -919,20 +920,20 @@ extension ExtSkiaPaintCustom on Paint { } class _GraphVertices { - List vertices, uvtData, adjustedUvtData; - List colors, indices; + List? vertices, uvtData, adjustedUvtData; + List? colors, indices; BlendMode blendMode; VertexMode mode; - Path _path; - Rect _bounds; - bool _normalizedUvt; + Path? _path; + Rect? _bounds; + late bool _normalizedUvt; - Float32List _rawPoints; + Float32List? _rawPoints; - Float32List get rawPoints { + Float32List? get rawPoints { if (_rawPoints != null) return _rawPoints; var points = _GraphUtils.getTrianglePoints(this); - _rawPoints = Float32List.fromList(points); + _rawPoints = Float32List.fromList(points as List); return _rawPoints; } @@ -949,14 +950,14 @@ class _GraphVertices { this.culling = Culling.positive, ]) { _normalizedUvt = false; - final len = uvtData.length; + final len = uvtData!.length; if (uvtData != null && len > 6) { for (var i = 0; i < 6; ++i) { - if (uvtData[i] <= 2.0) { + if (uvtData![i]! <= 2.0) { _normalizedUvt = true; } } - if (uvtData[len - 2] <= 2.0 || uvtData[len - 1] <= 2.0) { + if (uvtData![len - 2]! <= 2.0 || uvtData![len - 1]! <= 2.0) { _normalizedUvt = true; } } @@ -968,7 +969,7 @@ class _GraphVertices { _bounds = null; } - Rect getBounds() { + Rect? getBounds() { if (_bounds != null) return _bounds; _bounds = computePath().getBounds(); return _bounds; @@ -976,22 +977,23 @@ class _GraphVertices { Path computePath() => _path ??= _GraphUtils.getPathFromVertices(this); - ui.Vertices _rawData; + ui.Vertices? _rawData; - ui.Vertices get rawData { + ui.Vertices? get rawData { if (_rawData != null) return _rawData; // calculateCulling(); - Float32List _textureCoordinates; - Int32List _colors; - Uint16List _indices; + Float32List? _textureCoordinates; + Int32List? _colors; + Uint16List? _indices; if (uvtData != null && adjustedUvtData != null) { - _textureCoordinates = Float32List.fromList(adjustedUvtData); + _textureCoordinates = + Float32List.fromList(adjustedUvtData as List); } - if (colors != null) _colors = Int32List.fromList(colors); - if (indices != null) _indices = Uint16List.fromList(indices); + if (colors != null) _colors = Int32List.fromList(colors!); + if (indices != null) _indices = Uint16List.fromList(indices!); _rawData = ui.Vertices.raw( VertexMode.triangles, - Float32List.fromList(vertices), + Float32List.fromList(vertices as List), textureCoordinates: _textureCoordinates, colors: _colors, indices: _indices, @@ -999,18 +1001,18 @@ class _GraphVertices { return _rawData; } - void calculateUvt(GTexture shaderTexture) { + void calculateUvt(GTexture? shaderTexture) { if (uvtData == null) return; if (!_normalizedUvt) { adjustedUvtData = uvtData; } else { /// make a ratio of the image size - var imgW = shaderTexture.width; + var imgW = shaderTexture!.width; var imgH = shaderTexture.height; - adjustedUvtData = List(uvtData.length); - for (var i = 0; i < uvtData.length; i += 2) { - adjustedUvtData[i] = uvtData[i] * imgW; - adjustedUvtData[i + 1] = uvtData[i + 1] * imgH; + adjustedUvtData = List.filled(uvtData!.length, null); + for (var i = 0; i < uvtData!.length; i += 2) { + adjustedUvtData![i] = uvtData![i]! * imgW!; + adjustedUvtData![i + 1] = uvtData![i + 1]! * imgH!; } } } @@ -1020,25 +1022,25 @@ class _GraphVertices { var offsetX = 0.0, offsetY = 0.0; var ind = indices; var v = vertices; - var l = indices.length; + var l = indices!.length; while (i < l) { var _a = i; var _b = i + 1; var _c = i + 2; - var iax = ind[_a] * 2; + var iax = ind![_a] * 2; var iay = ind[_a] * 2 + 1; var ibx = ind[_b] * 2; var iby = ind[_b] * 2 + 1; var icx = ind[_c] * 2; var icy = ind[_c] * 2 + 1; - var x1 = v[iax] - offsetX; - var y1 = v[iay] - offsetY; - var x2 = v[ibx] - offsetX; - var y2 = v[iby] - offsetY; - var x3 = v[icx] - offsetX; - var y3 = v[icy] - offsetY; + var x1 = v![iax]! - offsetX; + var y1 = v[iay]! - offsetY; + var x2 = v[ibx]! - offsetX; + var y2 = v[iby]! - offsetY; + var x3 = v[icx]! - offsetX; + var y3 = v[icy]! - offsetY; switch (culling) { case Culling.positive: @@ -1089,23 +1091,23 @@ class _GraphUtils { static Path getPathFromVertices(_GraphVertices v) { var path = _helperPath; path.reset(); - var pos = v.vertices; + var pos = v.vertices!; var len = pos.length; final points = []; for (var i = 0; i < len; i += 2) { - points.add(Offset(pos[i], pos[i + 1])); + points.add(Offset(pos[i]!, pos[i + 1]!)); } path.addPolygon(points, true); return path; } - static List getTrianglePoints(_GraphVertices v) { + static List getTrianglePoints(_GraphVertices v) { var ver = v.vertices; var ind = v.indices; if (ind == null) { /// calculate - var len = ver.length; - var out = List(len * 2); + var len = ver!.length; + var out = List.filled(len * 2, null); var j = 0; for (var i = 0; i < len; i += 6) { out[j++] = ver[i + 0]; @@ -1124,7 +1126,7 @@ class _GraphUtils { return out; } else { var len = ind.length; - var out = List(len * 4); + var out = List.filled(len * 4, null); var j = 0; for (var i = 0; i < len; i += 3) { var i0 = ind[i + 0]; @@ -1133,7 +1135,7 @@ class _GraphUtils { var v0 = i0 * 2; var v1 = i1 * 2; var v2 = i2 * 2; - out[j++] = ver[v0]; + out[j++] = ver![v0]; out[j++] = ver[v0 + 1]; out[j++] = ver[v1]; out[j++] = ver[v1 + 1]; diff --git a/lib/src/render/icon.dart b/lib/src/render/icon.dart index 10e4ddd..27793a5 100644 --- a/lib/src/render/icon.dart +++ b/lib/src/render/icon.dart @@ -9,7 +9,7 @@ class GIcon extends GDisplayObject { final _localBounds = GRect(); @override - GRect getBounds(GDisplayObject targetSpace, [GRect out]) { + GRect getBounds(GDisplayObject? targetSpace, [GRect? out]) { _sHelperMatrix.identity(); getTransformationMatrix(targetSpace, _sHelperMatrix); var r = MatrixUtils.getTransformedBoundsRect( @@ -21,20 +21,20 @@ class GIcon extends GDisplayObject { } @override - GDisplayObject hitTest(GPoint localPoint, [bool useShape = false]) { + GDisplayObject? hitTest(GPoint localPoint, [bool useShape = false]) { if (!visible || !mouseEnabled) return null; return _localBounds.containsPoint(localPoint) ? this : null; } - widgets.IconData _data; - double _size; - ui.Color _color; + widgets.IconData? _data; + double _size = 0.0; + ui.Color? _color; bool _invalidStyle = false; - ui.Color get color => _color; + ui.Color? get color => _color; - set color(ui.Color value) { + set color(ui.Color? value) { if (value == _color) return; _color = value; _invalidStyle = true; @@ -46,14 +46,14 @@ class GIcon extends GDisplayObject { set size(double value) { if (value == _size) return; _size = value; - _localBounds?.setTo(0, 0, size, size); + _localBounds.setTo(0, 0, size, size); _invalidStyle = true; requiresRedraw(); } - widgets.IconData get data => _data; + widgets.IconData? get data => _data; - set data(widgets.IconData value) { + set data(widgets.IconData? value) { if (value == _data) return; _data = value; _invalidStyle = true; @@ -62,7 +62,7 @@ class GIcon extends GDisplayObject { GIcon( widgets.IconData data, [ - ui.Color color = kColorWhite, + ui.Color color = kColorWhite, double size = 24.0, ]) { _data = data; @@ -79,12 +79,12 @@ class GIcon extends GDisplayObject { requiresRedraw(); } - ui.Paragraph _paragraph; - ui.ParagraphBuilder _builder; - ui.TextStyle _style; + ui.Paragraph? _paragraph; + late ui.ParagraphBuilder _builder; + late ui.TextStyle _style; - ui.Paint _paint; - ui.Shadow _shadow; + ui.Paint? _paint; + ui.Shadow? _shadow; void setPaint(ui.Paint value) { _paint = value; @@ -105,24 +105,24 @@ class GIcon extends GDisplayObject { fontSize: _size, fontFamily: _resolveFontFamily(), foreground: _paint, - shadows: _shadow != null ? [_shadow] : null, + shadows: _shadow != null ? [_shadow!] : null, ); _builder = ui.ParagraphBuilder(ui.ParagraphStyle()); // _builder.pop(); _builder.pushStyle(_style); - final charCode = String.fromCharCode(_data.codePoint); + final charCode = String.fromCharCode(_data!.codePoint); _builder.addText(charCode); _paragraph = _builder.build(); - _paragraph.layout(ui.ParagraphConstraints(width: double.infinity)); + _paragraph!.layout(ui.ParagraphConstraints(width: double.infinity)); _invalidStyle = false; } - String _resolveFontFamily() { + String? _resolveFontFamily() { if (data == null) return null; - if (data.fontPackage == null) { - return data.fontFamily; + if (data!.fontPackage == null) { + return data!.fontFamily; } else { - return 'packages/${data.fontPackage}/${data.fontFamily}'; + return 'packages/${data!.fontPackage}/${data!.fontFamily}'; } } @@ -131,14 +131,14 @@ class GIcon extends GDisplayObject { } @override - void $applyPaint(ui.Canvas canvas) { + void $applyPaint(ui.Canvas? canvas) { if (data == null) return; if (_invalidStyle) { _invalidStyle = false; _updateStyle(); } if (_paragraph != null) { - canvas.drawParagraph(_paragraph, ui.Offset.zero); + canvas!.drawParagraph(_paragraph!, ui.Offset.zero); } } } diff --git a/lib/src/render/movie_clip.dart b/lib/src/render/movie_clip.dart index 0ee6b59..75cd0ea 100644 --- a/lib/src/render/movie_clip.dart +++ b/lib/src/render/movie_clip.dart @@ -18,9 +18,9 @@ class GMovieClip extends GBitmap { /// stops the playback when reaching this frame. int targetFrame = -1; - GBitmap bitmap; + GBitmap? bitmap; - Signal _onFramesComplete; + Signal? _onFramesComplete; Signal get onFramesComplete => _onFramesComplete ??= Signal(); @@ -31,16 +31,16 @@ class GMovieClip extends GBitmap { set fps(double value) => speed = 1 / value; - GMovieClip({List frames, double fps = 30}) { + GMovieClip({required List frames, double fps = 30}) { setFrameTextures(frames); this.fps = fps; } - List _frameTextures; + List? _frameTextures; List setFrameTextures(List list) { - _frameTextures = list ?? []; - frameCount = list?.length ?? 0; + _frameTextures = list; + frameCount = list.length; currentFrame = 0; texture = list.isNotEmpty ? list[0] : null; return list; @@ -50,7 +50,7 @@ class GMovieClip extends GBitmap { if (_frameTextures == null) return; currentFrame = frame; currentFrame %= frameCount; - texture = _frameTextures[currentFrame]; + texture = _frameTextures![currentFrame]; } void gotoAndPlay(int frame, {int lastFrame = -1}) { @@ -105,7 +105,7 @@ class GMovieClip extends GBitmap { if (targetFrame > -1 && currentFrame == targetFrame) { playing = false; } - texture = _frameTextures[currentFrame]; + texture = _frameTextures![currentFrame]; } accumulatedTime %= speed; } diff --git a/lib/src/render/particles/simple_particle.dart b/lib/src/render/particles/simple_particle.dart index 3f6a1c0..d9aa684 100644 --- a/lib/src/render/particles/simple_particle.dart +++ b/lib/src/render/particles/simple_particle.dart @@ -1,11 +1,19 @@ -import 'dart:ui' as ui ; +import 'dart:ui' as ui; import '../../../graphx.dart'; class GSimpleParticle { - GSimpleParticle $next; - GSimpleParticle $prev; - - double x, y, rotation, scaleX, scaleY, alpha, red, green, blue; + GSimpleParticle? $next; + GSimpleParticle? $prev; + + double x = 0.0, + y = 0.0, + rotation = 0.0, + scaleX = 0.0, + scaleY = 0.0, + alpha = 0.0, + red = 0.0, + green = 0.0, + blue = 0.0; double velocityX = 0; double velocityY = 0; @@ -19,17 +27,20 @@ class GSimpleParticle { double initialVelocityAngular = 0; double initialAccelerationX = 0; double initialAccelerationY = 0; - double initialAlpha, initialRed, initialBlue, initialGreen; - double endAlpha, endRed, endBlue, endGreen; - double alphaDif, redDif, blueDif, greenDif; - double scaleDif; + double initialAlpha = 0.0, + initialRed = 0.0, + initialBlue = 0.0, + initialGreen = 0.0; + double endAlpha = 0.0, endRed = 0.0, endBlue = 0.0, endGreen = 0.0; + double alphaDif = 0.0, redDif = 0.0, blueDif = 0.0, greenDif = 0.0; + late double scaleDif; double accumulatedEnergy = 0; - GSimpleParticle $nextInstance; + GSimpleParticle? $nextInstance; int id = 0; - GTexture texture; - static GSimpleParticle $availableInstance; + GTexture? texture; + static GSimpleParticle? $availableInstance; static int $instanceCount = 0; ui.Color get color { @@ -53,7 +64,7 @@ class GSimpleParticle { static void precache(int count) { if (count < $instanceCount) return; - var cached = get(); + GSimpleParticle? cached = get(); while ($instanceCount < count) { var n = get(); n.$prev = cached; @@ -62,7 +73,7 @@ class GSimpleParticle { while (cached != null) { var d = cached; cached = d.$prev; - d?.dispose(); + d.dispose(); } } @@ -124,8 +135,7 @@ class GSimpleParticle { if (emitter.dispersionAngle != 0 || emitter.dispersionAngleVariance != 0) { var dispersionAngle = emitter.dispersionAngle; if (emitter.dispersionAngleVariance > 0) { - dispersionAngle += - emitter.dispersionAngleVariance * Math.random(); + dispersionAngle += emitter.dispersionAngleVariance * Math.random(); } var _sin = Math.sin(dispersionAngle); var _cos = Math.cos(dispersionAngle); @@ -215,10 +225,10 @@ class GSimpleParticle { void dispose() { if ($next != null) { - $next.$prev = $prev; + $next!.$prev = $prev; } if ($prev != null) { - $prev.$next = $next; + $prev!.$next = $next; } $next = null; $prev = null; diff --git a/lib/src/render/particles/simple_particle_system.dart b/lib/src/render/particles/simple_particle_system.dart index 78601c3..a941b1f 100644 --- a/lib/src/render/particles/simple_particle_system.dart +++ b/lib/src/render/particles/simple_particle_system.dart @@ -16,7 +16,7 @@ class GSimpleParticleSystem extends GDisplayObject { } @override - GRect getBounds(GDisplayObject targetSpace, [GRect out]) { + GRect getBounds(GDisplayObject? targetSpace, [GRect? out]) { final matrix = _sHelperMatrix; matrix.identity(); getTransformationMatrix(targetSpace, matrix); @@ -73,7 +73,7 @@ class GSimpleParticleSystem extends GDisplayObject { double dispersionAngle = 0; double dispersionAngleVariance = 0; bool paused = false; - GTexture texture; + GTexture? texture; int get initialColor { final r = (initialRed * 0xff).toInt() << 16; @@ -107,8 +107,8 @@ class GSimpleParticleSystem extends GDisplayObject { int $activeParticles = 0; double $lastUpdateTime = 0; - GSimpleParticle $firstParticle; - GSimpleParticle $lastParticle; + GSimpleParticle? $firstParticle; + GSimpleParticle? $lastParticle; void _setInitialParticlePosition(GSimpleParticle p) { p.x = useWorldSpace ? x : 0; @@ -151,12 +151,12 @@ class GSimpleParticleSystem extends GDisplayObject { void _setPivot() { /// used (texture.width)... - particlePivotX = texture.nativeWidth.toDouble() * .5; - particlePivotY = texture.nativeHeight.toDouble() * .5; + particlePivotX = texture!.nativeWidth.toDouble() * .5; + particlePivotY = texture!.nativeHeight.toDouble() * .5; } - double particlePivotX; - double particlePivotY; + double? particlePivotX; + late double particlePivotY; void forceBurst() { var currentEmission = @@ -204,7 +204,7 @@ class GSimpleParticleSystem extends GDisplayObject { } @override - void paint(ui.Canvas canvas) { + void paint(ui.Canvas? canvas) { if (!$hasVisibleArea) return; if (useWorldSpace) { render(canvas); @@ -214,28 +214,28 @@ class GSimpleParticleSystem extends GDisplayObject { } @override - void $applyPaint(ui.Canvas canvas) { + void $applyPaint(ui.Canvas? canvas) { render(canvas); } bool useAlphaOnColorFilter = false; - void Function(ui.Canvas, ui.Paint) drawCallback; + void Function(ui.Canvas?, ui.Paint)? drawCallback; final nativePaint = ui.Paint() ..color = kColorBlack ..filterQuality = ui.FilterQuality.low; - void render(ui.Canvas canvas) { + void render(ui.Canvas? canvas) { if (texture == null) return; var particle = $firstParticle; while (particle != null) { var next = particle.$next; - double tx, ty, sx, sy; + double? tx, ty, sx, sy; tx = particle.x; ty = particle.y; - sx = particle.scaleX / texture.scale; - sy = particle.scaleY / texture.scale; + sx = particle.scaleX/ texture!.scale!; + sy = particle.scaleY/ texture!.scale!; if (useWorldSpace) { sx *= scaleX; sy *= scaleY; @@ -252,20 +252,20 @@ class GSimpleParticleSystem extends GDisplayObject { var filterColor = useAlphaOnColorFilter ? _color : _color.withOpacity(1); nativePaint.colorFilter = ui.ColorFilter.mode(filterColor, particleBlendMode); - canvas.save(); + canvas!.save(); canvas.translate(tx, ty); canvas.rotate(particle.rotation); canvas.scale(sx, sy); - canvas.translate(-particlePivotX, -particlePivotY); + canvas.translate(-particlePivotX!, -particlePivotY); // $canvas.scale(particle.scaleX, particle.scaleY); // $canvas.rotate(particle.rotation); /// render in canvas. if (drawCallback != null) { - drawCallback(canvas, nativePaint); + drawCallback!(canvas, nativePaint); // $canvas.drawImage(texture.source, Offset.zero, nativePaint); } else { - canvas.drawImage(texture.root, ui.Offset.zero, nativePaint); + canvas.drawImage(texture!.root!, ui.Offset.zero, nativePaint); } // $canvas.drawImage(texture.source, Offset(tx, ty), nativePaint); canvas.restore(); @@ -284,7 +284,7 @@ class GSimpleParticleSystem extends GDisplayObject { var p = GSimpleParticle.get(); if ($firstParticle != null) { p.$next = $firstParticle; - $firstParticle.$prev = p; + $firstParticle!.$prev = p; $firstParticle = p; } else { $firstParticle = p; @@ -294,8 +294,8 @@ class GSimpleParticleSystem extends GDisplayObject { } void $deactivateParticle(GSimpleParticle particle) { - if (particle == $lastParticle) $lastParticle = $lastParticle.$prev; - if (particle == $firstParticle) $firstParticle = $firstParticle.$next; + if (particle == $lastParticle) $lastParticle = $lastParticle!.$prev; + if (particle == $firstParticle) $firstParticle = $firstParticle!.$next; particle.dispose(); } @@ -304,7 +304,7 @@ class GSimpleParticleSystem extends GDisplayObject { @override void dispose() { while ($firstParticle != null) { - $deactivateParticle($firstParticle); + $deactivateParticle($firstParticle!); } ScenePainter.current.onUpdate.remove(update); super.dispose(); @@ -312,7 +312,7 @@ class GSimpleParticleSystem extends GDisplayObject { void clear() { while ($firstParticle != null) { - $deactivateParticle($firstParticle); + $deactivateParticle($firstParticle!); } } } diff --git a/lib/src/render/svg_shape.dart b/lib/src/render/svg_shape.dart index 948ed4d..98d896d 100644 --- a/lib/src/render/svg_shape.dart +++ b/lib/src/render/svg_shape.dart @@ -7,7 +7,7 @@ class GSvgShape extends GDisplayObject { static final GMatrix _sHelperMatrix = GMatrix(); static final GPoint _sHelperPoint = GPoint(); - Color _tint; + Color? _tint; /// play nice with Colorization. BlendMode _blendMode = BlendMode.srcATop; @@ -16,9 +16,9 @@ class GSvgShape extends GDisplayObject { bool _invalidColor = false; - Color get tint => _tint; + Color? get tint => _tint; - set tint(Color value) { + set tint(Color? value) { _tint = value; _invalidColor = true; usePaint = true; @@ -41,18 +41,18 @@ class GSvgShape extends GDisplayObject { } bool _isValid = false; - SvgData _data; + SvgData? _data; - SvgData get data => _data; + SvgData? get data => _data; - set data(SvgData value) { + set data(SvgData? value) { if (_data == value) return; _data = value; _isValid = _data?.hasContent ?? false; requiresRedraw(); } - GSvgShape(SvgData data) { + GSvgShape(SvgData? data) { this.data = data; } @@ -66,12 +66,12 @@ class GSvgShape extends GDisplayObject { } @override - GRect getBounds(GDisplayObject targetSpace, [GRect out]) { + GRect? getBounds(GDisplayObject? targetSpace, [GRect? out]) { final matrix = _sHelperMatrix; matrix.identity(); getTransformationMatrix(targetSpace, matrix); if (_isValid) { - var r = _data.size; + var r = _data!.size; out = MatrixUtils.getTransformedBoundsRect( matrix, r, @@ -79,7 +79,7 @@ class GSvgShape extends GDisplayObject { ); } else { matrix.transformCoords(0, 0, _sHelperPoint); - out.setTo(_sHelperPoint.x, _sHelperPoint.y, 0, 0); + out!.setTo(_sHelperPoint.x, _sHelperPoint.y, 0, 0); } return out; } @@ -96,38 +96,38 @@ class GSvgShape extends GDisplayObject { } @override - void paint(Canvas canvas) { + void paint(Canvas? canvas) { if (!_isValid) return; super.paint(canvas); } @override - void $applyPaint(Canvas canvas) { + void $applyPaint(Canvas? canvas) { var _saveLayer = $alpha != 1 || usePaint; if (_saveLayer) { if (_invalidColor) _validateColor(); - final rect = getBounds(this).toNative(); - canvas.saveLayer(rect, _paint); + final rect = getBounds(this)!.toNative(); + canvas!.saveLayer(rect, _paint); } - canvas.drawPicture(_data.picture); + canvas!.drawPicture(_data!.picture!); if (_saveLayer) { canvas.restore(); } } void _validateColor() { - _paint.colorFilter = ColorFilter.mode(_tint, _blendMode); + _paint.colorFilter = ColorFilter.mode(_tint!, _blendMode); _invalidColor = false; } } /// proxy class to flutter_svg class SvgData { - Color color; - GRect viewBox; - GRect size; - Picture picture; - bool hasContent; + Color? color; + GRect? viewBox; + late GRect size; + Picture? picture; + bool? hasContent; SvgData([this.picture]); diff --git a/lib/src/textures/sub_texture.dart b/lib/src/textures/sub_texture.dart index 222671a..9ba852f 100644 --- a/lib/src/textures/sub_texture.dart +++ b/lib/src/textures/sub_texture.dart @@ -2,24 +2,24 @@ import 'dart:ui' as ui; import '../../graphx.dart'; class GSubTexture extends GTexture { - GTexture _parent; - bool _ownsParent; - GRect _region; - GRect _sourceRegion; - bool _rotated; - double _w; - double _h; - double _scale; + GTexture? _parent; + bool? _ownsParent; + GRect? _region; + late GRect _sourceRegion; + bool? _rotated; + double? _w; + double? _h; + double? _scale; /// cache rendering. - ui.Rect _sourceRegionRect; - ui.Rect _destRect; + late ui.Rect _sourceRegionRect; + late ui.Rect _destRect; GSubTexture(GTexture parent, - {GRect region, + {GRect? region, bool ownsParent = false, - GRect frame, - bool rotated, + GRect? frame, + required bool rotated, double scaleModifier = 1}) { $setTo( parent, @@ -32,21 +32,21 @@ class GSubTexture extends GTexture { } void $setTo(GTexture parent, - {GRect region, + {GRect? region, bool ownsParent = false, - GRect frame, - bool rotated, + GRect? frame, + required bool rotated, double scaleModifier = 1}) { _region ??= GRect(); if (region != null) { - _region.copyFrom(region); + _region!.copyFrom(region); } else { /// used (parent.width) - _region.setTo(0, 0, parent.nativeWidth, parent.nativeHeight); + _region!.setTo(0, 0, parent.nativeWidth, parent.nativeHeight); } if (frame != null) { if (this.frame != null) { - this.frame.copyFrom(frame); + this.frame!.copyFrom(frame); } else { this.frame = frame.clone(); } @@ -56,10 +56,10 @@ class GSubTexture extends GTexture { _parent = parent; _ownsParent = ownsParent; _rotated = rotated; - _w = (rotated ? _region.height : _region.width) / scaleModifier; - _h = (rotated ? _region.width : _region.height) / scaleModifier; - _scale = parent.scale * scaleModifier; - _sourceRegion = _region.clone() * scale; + _w = (rotated ? _region!.height : _region!.width)/ scaleModifier; + _h = (rotated ? _region!.width : _region!.height)/ scaleModifier; + _scale = parent.scale! * scaleModifier; + _sourceRegion = _region!.clone() * scale!; /// cache. _sourceRegionRect = _sourceRegion.toNative(); @@ -77,46 +77,46 @@ class GSubTexture extends GTexture { @override void dispose() { - if (_ownsParent) { - _parent.dispose(); + if (_ownsParent!) { + _parent!.dispose(); } super.dispose(); } - GRect get region => _region; + GRect? get region => _region; - bool get rotated => _rotated; + bool? get rotated => _rotated; - bool get ownsParent => _ownsParent; + bool? get ownsParent => _ownsParent; - GTexture get parent => _parent; + GTexture? get parent => _parent; @override - ui.Image get root => _parent.root; + ui.Image? get root => _parent!.root; @override - double get width => _w; + double? get width => _w; @override - double get height => _h; + double? get height => _h; @override - double get nativeWidth => _w * _scale; + double get nativeWidth => _w! * _scale!; @override - double get nativeHeight => _h * _scale; + double get nativeHeight => _h! * _scale!; @override - double get scale => _scale; + double? get scale => _scale; /// no support void updateMatrices() {} @override - void render(ui.Canvas canvas, [ui.Paint paint]) { + void render(ui.Canvas? canvas, [ui.Paint? paint]) { paint ??= GTexture.sDefaultPaint; paint.isAntiAlias = true; - canvas.drawImageRect(root, _sourceRegionRect, _destRect, paint); + canvas!.drawImageRect(root!, _sourceRegionRect, _destRect, paint); // final sub = texture as GSubTexture; // final dest = Rect.fromLTWH( // 0, diff --git a/lib/src/textures/texture.dart b/lib/src/textures/texture.dart index 53ce278..831533b 100644 --- a/lib/src/textures/texture.dart +++ b/lib/src/textures/texture.dart @@ -3,22 +3,22 @@ import 'dart:ui' as ui; import '../../graphx.dart'; class GTexture { - GRect frame; + GRect? frame; // set from the outside. - GRect scale9Grid; - GRect scale9GridDest; + GRect? scale9Grid; + GRect? scale9GridDest; - double get width => nativeWidth; + double? get width => nativeWidth; - double get height => nativeHeight; + double? get height => nativeHeight; - double get nativeWidth => root?.width?.toDouble() ?? 0; + double get nativeWidth => root?.width.toDouble() ?? 0; - double get nativeHeight => root?.height?.toDouble() ?? 0; + double get nativeHeight => root?.height.toDouble() ?? 0; /// when the texture is plain color. - ui.Color color; + ui.Color? color; /// used width. double get frameWidth => frame?.width ?? nativeWidth; @@ -26,13 +26,13 @@ class GTexture { double get frameHeight => frame?.height ?? nativeHeight; /// set this by hand. - double actualWidth, actualHeight; + double? actualWidth, actualHeight; - double pivotX = 0, pivotY = 0; - GRect sourceRect; + double? pivotX = 0, pivotY = 0; + GRect? sourceRect; - double scale = 1; - ui.Image root; + double? scale = 1; + ui.Image? root; /// copy Image data, and properties from other GTexture instance. void copyFrom(GTexture other) { @@ -46,7 +46,7 @@ class GTexture { scale = other.scale; } - GRect getBounds() { + GRect? getBounds() { return sourceRect; } @@ -89,11 +89,11 @@ class GTexture { static ui.Paint sDefaultPaint = ui.Paint(); - void render(ui.Canvas canvas, [ui.Paint paint]) { + void render(ui.Canvas? canvas, [ui.Paint? paint]) { paint ??= sDefaultPaint; if (scale != 1) { - canvas.save(); - canvas.scale(1 / scale); + canvas!.save(); + canvas.scale(1 / scale!); // canvas.drawImage(root, Offset.zero, paint); _drawImage(canvas, paint); canvas.restore(); @@ -102,18 +102,18 @@ class GTexture { } } - void _drawImage(ui.Canvas canvas, ui.Paint paint) { + void _drawImage(ui.Canvas? canvas, ui.Paint paint) { if (scale9Grid != null) { // print('src: $scale9Grid, dst: $scale9GridDest'); - canvas.drawImageNine( - root, - scale9Grid.toNative(), - scale9GridDest.toNative(), + canvas!.drawImageNine( + root!, + scale9Grid!.toNative(), + scale9GridDest!.toNative(), // sourceRect.toNative(), paint, ); } else { - canvas.drawImage(root, ui.Offset.zero, paint); + canvas!.drawImage(root!, ui.Offset.zero, paint); } } diff --git a/lib/src/textures/texture_atlas.dart b/lib/src/textures/texture_atlas.dart index dacd75c..cf95aaa 100644 --- a/lib/src/textures/texture_atlas.dart +++ b/lib/src/textures/texture_atlas.dart @@ -3,16 +3,17 @@ import 'package:xml/xml.dart' as xml; import '../../graphx.dart'; class GTextureAtlas { - GTexture _atlasTexture; - Map _subTextures; - List _subTexturesNames; + GTexture? _atlasTexture; + Map? _subTextures; + List? _subTexturesNames; static final List _names = []; - static bool attrBoolean(xml.XmlElement el, String name, {bool defaultValue}) { + static bool? attrBoolean(xml.XmlElement el, String name, + {bool? defaultValue}) { var val = el.getAttribute(name); if (val == null) return defaultValue; - return StringUtils.parseBoolean(val) ?? defaultValue; + return StringUtils.parseBoolean(val); } static double attrDouble(xml.XmlElement el, String name, @@ -22,11 +23,11 @@ class GTextureAtlas { return double.tryParse(val) ?? defaultValue; } - double _atlasXmlRatio; + late double _atlasXmlRatio; GTextureAtlas( - GTexture texture, [ - Object data, + GTexture? texture, [ + Object? data, double adjustXmlSizesRatio = 1, ]) { _subTextures = {}; @@ -40,7 +41,7 @@ class GTextureAtlas { void parseAtlasData(Object data) { if (data is String) { /// parse json or xml. - if ((data as String).contains('')) { + if (data.contains('')) { data = xml.XmlDocument.parse(data); } } @@ -54,14 +55,14 @@ class GTextureAtlas { /// Parse the XML tree and defines all SubTextures areas. void parseAtlasXml(xml.XmlDocument atlasXml) { - var scale = _atlasTexture.scale; + var scale = _atlasTexture!.scale; var region = GRect(); var frame = GRect(); - final pivots = {}; + final pivots = {}; final nodeList = atlasXml.findAllElements('SubTexture'); for (var subTexture in nodeList) { var name = subTexture.getAttribute('name'); - var x = attrDouble(subTexture, 'x') / scale * _atlasXmlRatio; + var x = attrDouble(subTexture, 'x') / scale! * _atlasXmlRatio; var y = attrDouble(subTexture, 'y') / scale * _atlasXmlRatio; var width = attrDouble(subTexture, 'width') / scale * _atlasXmlRatio; var height = attrDouble(subTexture, 'height') / scale * _atlasXmlRatio; @@ -81,9 +82,9 @@ class GTextureAtlas { region.setTo(x, y, width, height); frame.setTo(frameX, frameY, frameWidth, frameHeight); if (frameWidth > 0 && frameHeight > 0) { - addRegion(name, region, frame, rotated); + addRegion(name, region, frame, rotated!); } else { - addRegion(name, region, null, rotated); + addRegion(name, region, null, rotated!); } if (pivotX != 0 || pivotY != 0) { /// image bind pivot point to texture! @@ -94,12 +95,12 @@ class GTextureAtlas { /// adobe animate workaround. } - void addRegion(String name, GRect region, - [GRect frame, bool rotated = false]) { + void addRegion(String? name, GRect region, + [GRect? frame, bool rotated = false]) { addSubTexture( name, GSubTexture( - _atlasTexture, + _atlasTexture!, region: region, ownsParent: false, frame: frame, @@ -108,31 +109,31 @@ class GTextureAtlas { } void removeRegion(String name) { - var subTexture = _subTextures[name]; + var subTexture = _subTextures![name]; subTexture?.dispose(); - _subTextures.remove(name); + _subTextures!.remove(name); _subTexturesNames = null; } - GTexture get texture => _atlasTexture; + GTexture? get texture => _atlasTexture; bool getRotation(String name) { - return _subTextures[name]?.rotated ?? false; + return _subTextures![name]?.rotated ?? false; } - GRect getFrame(String name) { - return _subTextures[name]?.frame; + GRect? getFrame(String name) { + return _subTextures![name]?.frame; } - GSubTexture getTexture(String name) { - return _subTextures[name]; + GSubTexture? getTexture(String? name) { + return _subTextures![name]; } - GRect getRegion(String name) { - return _subTextures[name]?.region; + GRect? getRegion(String name) { + return _subTextures![name]?.region; } - List getTextures({String prefix, List out}) { + List getTextures({String? prefix, List? out}) { prefix ??= ''; out ??= []; final list = getNames(prefix: prefix, out: _names); @@ -142,29 +143,29 @@ class GTextureAtlas { return out; } - List getNames({String prefix, List out}) { + List getNames({String? prefix, List? out}) { prefix ??= ''; out ??= []; if (_subTexturesNames == null) { _subTexturesNames = []; - for (var name in _subTextures.keys) { - _subTexturesNames.add(name); + for (var name in _subTextures!.keys) { + _subTexturesNames!.add(name); } - _subTexturesNames.sort(); + _subTexturesNames!.sort(); } - for (var name in _subTexturesNames) { - if (name.indexOf(prefix) == 0) { + for (var name in _subTexturesNames!) { + if (name!.indexOf(prefix) == 0) { out.add(name); } } return out; } - void addSubTexture(String name, GSubTexture subTexture) { - if (subTexture.root != _atlasTexture.root) { + void addSubTexture(String? name, GSubTexture subTexture) { + if (subTexture.root != _atlasTexture!.root) { throw 'SubTexture\'s root must be an Atlas Texture.'; } - _subTextures[name] = subTexture; + _subTextures![name] = subTexture; _subTexturesNames = null; } diff --git a/lib/src/ticker/ticker.dart b/lib/src/ticker/ticker.dart index 3ce2bb1..55c030d 100644 --- a/lib/src/ticker/ticker.dart +++ b/lib/src/ticker/ticker.dart @@ -4,11 +4,11 @@ import '../events/events.dart'; class GTicker { GTicker(); - Ticker _ticker; - EventSignal _onFrame; + Ticker? _ticker; + EventSignal? _onFrame; EventSignal get onFrame => _onFrame ??= EventSignal(); - VoidCallback _nextFrameCallback; + VoidCallback? _nextFrameCallback; // ignore: use_setters_to_change_properties void callNextFrame(VoidCallback callback) { @@ -18,8 +18,8 @@ class GTicker { void _createTicker() { if (_ticker != null) return; _ticker = Ticker(_onTick); - _ticker.start(); - _ticker.muted = true; + _ticker!.start(); + _ticker!.muted = true; } bool get isTicking => _ticker?.isTicking ?? false; @@ -47,7 +47,7 @@ class GTicker { double _currentDeltaRatio = 0.0; double frameRate = 60.0; - double _expectedDelta; + late double _expectedDelta; /// enterframe ticker void _onTick(Duration elapsed) { @@ -79,17 +79,17 @@ class GTicker { } } -Stopwatch _stopwatch; +Stopwatch? _stopwatch; void _initTimer() { if (_stopwatch != null) return; _stopwatch = Stopwatch(); - _stopwatch.start(); + _stopwatch!.start(); } int getTimer() { if (_stopwatch == null) { _initTimer(); } - return _stopwatch.elapsedMilliseconds; + return _stopwatch!.elapsedMilliseconds; } diff --git a/lib/src/tween/src/core/prop_tween.dart b/lib/src/tween/src/core/prop_tween.dart index f1685a0..fbbda28 100644 --- a/lib/src/tween/src/core/prop_tween.dart +++ b/lib/src/tween/src/core/prop_tween.dart @@ -2,44 +2,44 @@ part of gtween; class PropTween { /// target or dynamic - GTweenable t; + GTweenable? t; /// property "name" (commonly a String), or value! - Object p; + Object? p; /// start value - double s; + double s = 0.0; /// amount to change, diff between end and start. - double c; + double? c; /// original target object. - Object cObj; + Object? cObj; /// is function - bool f; + bool? f; /// priority in render queue. - int pr; + int? pr; /// target is tween plugin? - bool pg; + bool? pg; // name of original target property. Typically same as `t` - String n; + String? n; /// rounded - bool r; + bool? r; /// linked list next. - PropTween _next, _prev; + PropTween? _next, _prev; PropTween({ - GTweenable target, - Object property, - double start, - double change, - String name, - PropTween next, + GTweenable? target, + Object? property, + double start = 0.0, + double? change, + String? name, + PropTween? next, int priority = 0, }) { t = target; diff --git a/lib/src/tween/src/extensions/common_types.dart b/lib/src/tween/src/extensions/common_types.dart index c68617b..be46317 100644 --- a/lib/src/tween/src/extensions/common_types.dart +++ b/lib/src/tween/src/extensions/common_types.dart @@ -1,9 +1,9 @@ part of gtween; extension GTweenNumExt on num { - GTweenableDouble get twn { - return this is double ? GTweenableDouble(this) : GTweenableInt(this); - } + GTweenableDouble get twn => this is double + ? GTweenableDouble(this as double) + : GTweenableInt(this as int) as GTweenableDouble; } extension GTweenDoubleExt on double { @@ -14,7 +14,7 @@ extension GTweenIntExt on int { GTweenableInt get twn => GTweenableInt(this); } -extension GTweenMapExt on Map { +extension GTweenMapExt on Map { GTweenableMap get twn => GTweenableMap(this); } diff --git a/lib/src/tween/src/extensions/display_object.dart b/lib/src/tween/src/extensions/display_object.dart index c8e3075..49d092a 100644 --- a/lib/src/tween/src/extensions/display_object.dart +++ b/lib/src/tween/src/extensions/display_object.dart @@ -4,36 +4,36 @@ extension GTweenDiplayObjectExt on GDisplayObject { GTweenableDisplayObject get twn => GTweenableDisplayObject(this); GTween tween({ - @required double duration, - Object x, - Object y, - Object scaleX, - Object scaleY, - Object scale, - Object rotation, - Object rotationX, - Object rotationY, - Object pivotX, - Object pivotY, - Object width, - Object height, - Object skewX, - Object skewY, - Color colorize, - Object alpha, - EaseFunction ease, - double delay, - bool useFrames, + required double duration, + Object? x, + Object? y, + Object? scaleX, + Object? scaleY, + Object? scale, + Object? rotation, + Object? rotationX, + Object? rotationY, + Object? pivotX, + Object? pivotY, + Object? width, + Object? height, + Object? skewX, + Object? skewY, + Color? colorize, + Object? alpha, + EaseFunction? ease, + double? delay, + bool? useFrames, int overwrite = 1, - Function onStart, - Object onStartParams, - Function onComplete, - Object onCompleteParams, - Function onUpdate, - Object onUpdateParams, - bool runBackwards, - bool immediateRender, - Map startAt, + Function? onStart, + Object? onStartParams, + Function? onComplete, + Object? onCompleteParams, + Function? onUpdate, + Object? onUpdateParams, + bool? runBackwards, + bool? immediateRender, + Map? startAt, }) { final targetValues = { if (x != null) 'x': x, @@ -79,24 +79,24 @@ extension GTweenDiplayObjectExt on GDisplayObject { /// Shortcut to assign multiple properties and render immeditatly. /// Doesn't wait for the next tick update. void setProps({ - Object x, - Object y, - Object scaleX, - Object scaleY, - Object scale, - Object rotation, - Object pivotX, - Object pivotY, - Object width, - Object height, - Object skewX, - Object skewY, - Object rotationX, - Object rotationY, - Object alpha, - Color colorize, + Object? x, + Object? y, + Object? scaleX, + Object? scaleY, + Object? scale, + Object? rotation, + Object? pivotX, + Object? pivotY, + Object? width, + Object? height, + Object? skewX, + Object? skewY, + Object? rotationX, + Object? rotationY, + Object? alpha, + Color? colorize, double delay = 0, - bool visible, + bool? visible, bool immediateRender = true, }) { if (visible != null) { @@ -105,7 +105,7 @@ extension GTweenDiplayObjectExt on GDisplayObject { tween( duration: 0, delay: delay, - immediateRender: immediateRender ?? true, + immediateRender: immediateRender, x: x, y: y, scaleX: scaleX, @@ -120,8 +120,8 @@ extension GTweenDiplayObjectExt on GDisplayObject { skewX: skewX, skewY: skewY, alpha: alpha, - rotationX:rotationX, - rotationY:rotationY, + rotationX: rotationX, + rotationY: rotationY, ); } } diff --git a/lib/src/tween/src/extensions/filter_types.dart b/lib/src/tween/src/extensions/filter_types.dart index 9f0b099..c5b9f85 100644 --- a/lib/src/tween/src/extensions/filter_types.dart +++ b/lib/src/tween/src/extensions/filter_types.dart @@ -3,22 +3,22 @@ part of gtween; extension GTweenBlurFilterExt on GBlurFilter { GTweenableBlur get twn => GTweenableBlur(this); GTween tween({ - @required double duration, - Object blurX, - Object blurY, - EaseFunction ease, - double delay, - bool useFrames, + required double duration, + Object? blurX, + Object? blurY, + EaseFunction? ease, + double? delay, + bool? useFrames, int overwrite = 1, - VoidCallback onStart, - Object onStartParams, - VoidCallback onComplete, - Object onCompleteParams, - VoidCallback onUpdate, - Object onUpdateParams, - bool runBackwards, - bool immediateRender, - Map startAt, + VoidCallback? onStart, + Object? onStartParams, + VoidCallback? onComplete, + Object? onCompleteParams, + VoidCallback? onUpdate, + Object? onUpdateParams, + bool? runBackwards, + bool? immediateRender, + Map? startAt, }) => twn.tween( duration: duration, @@ -43,25 +43,25 @@ extension GTweenBlurFilterExt on GBlurFilter { extension GTweenDropShadowFilterExt on GDropShadowFilter { GTweenableDropShadowFilter get twn => GTweenableDropShadowFilter(this); GTween tween({ - @required double duration, - Object blurX, - Object blurY, - Object angle, - Object distance, - Color color, - EaseFunction ease, - double delay, - bool useFrames, + required double duration, + Object? blurX, + Object? blurY, + Object? angle, + Object? distance, + Color? color, + EaseFunction? ease, + double? delay, + bool? useFrames, int overwrite = 1, - VoidCallback onStart, - Object onStartParams, - VoidCallback onComplete, - Object onCompleteParams, - VoidCallback onUpdate, - Object onUpdateParams, - bool runBackwards, - bool immediateRender, - Map startAt, + VoidCallback? onStart, + Object? onStartParams, + VoidCallback? onComplete, + Object? onCompleteParams, + VoidCallback? onUpdate, + Object? onUpdateParams, + bool? runBackwards, + bool? immediateRender, + Map? startAt, }) { return twn.tween( duration: duration, @@ -90,23 +90,23 @@ extension GTweenDropShadowFilterExt on GDropShadowFilter { extension GTweenGlowFilterExt on GlowFilter { GTweenableGlowFilter get twn => GTweenableGlowFilter(this); GTween tween({ - @required double duration, - Object blurX, - Object blurY, - Color color, - EaseFunction ease, - double delay, - bool useFrames, + required double duration, + Object? blurX, + Object? blurY, + Color? color, + EaseFunction? ease, + double? delay, + bool? useFrames, int overwrite = 1, - VoidCallback onStart, - Object onStartParams, - VoidCallback onComplete, - Object onCompleteParams, - VoidCallback onUpdate, - Object onUpdateParams, - bool runBackwards, - bool immediateRender, - Map startAt, + VoidCallback? onStart, + Object? onStartParams, + VoidCallback? onComplete, + Object? onCompleteParams, + VoidCallback? onUpdate, + Object? onUpdateParams, + bool? runBackwards, + bool? immediateRender, + Map? startAt, }) { return twn.tween( duration: duration, diff --git a/lib/src/tween/src/gtween.dart b/lib/src/tween/src/gtween.dart index 8cda672..c84dccc 100644 --- a/lib/src/tween/src/gtween.dart +++ b/lib/src/tween/src/gtween.dart @@ -1,20 +1,20 @@ part of gtween; class GVars { - EaseFunction ease; - double delay; - bool useFrames; - int overwrite; - Function onStart; - CallbackParams onStartParams; - Function onComplete; - CallbackParams onCompleteParams; - Function onUpdate; - CallbackParams onUpdateParams; - bool runBackwards; - bool immediateRender; - - Map startAt; + EaseFunction? ease; + double? delay; + bool? useFrames; + int? overwrite; + Function? onStart; + CallbackParams? onStartParams; + Function? onComplete; + CallbackParams? onCompleteParams; + Function? onUpdate; + CallbackParams? onUpdateParams; + bool? runBackwards; + bool? immediateRender; + + Map? startAt; /// TODO: maybe in future use vars from this object. // Map vars; @@ -27,9 +27,9 @@ class GVars { this.onStart, this.onComplete, this.onUpdate, - Object onStartParams, - Object onCompleteParams, - Object onUpdateParams, + Object? onStartParams, + Object? onCompleteParams, + Object? onUpdateParams, this.runBackwards, this.immediateRender, this.startAt, @@ -50,13 +50,13 @@ class GVars { void _setTween(GTween gTween) { if (onStartParams != null) { - _setCallbackParams(gTween, onStartParams); + _setCallbackParams(gTween, onStartParams!); } if (onCompleteParams != null) { - _setCallbackParams(gTween, onCompleteParams); + _setCallbackParams(gTween, onCompleteParams!); } if (onUpdateParams != null) { - _setCallbackParams(gTween, onUpdateParams); + _setCallbackParams(gTween, onUpdateParams!); } // onStartParams?._setTween(gTween); // onCompleteParams?._setTween(gTween); @@ -101,7 +101,7 @@ class GTween { /// [GTweenableDouble.wrap, GTweenableInt.wrap, GTweenableList] /// ); /// ``` - static void registerCommonWraps([List otherWraps]) { + static void registerCommonWraps([List? otherWraps]) { if (initialized) return; GTween.registerWrap(GTweenableDisplayObject.wrap); GTween.registerWrap(GTweenableMap.wrap); @@ -127,7 +127,7 @@ class GTween { /// or make GTicker global... being able to track unique refresh frames /// is a must. static void processTick(double elapsed) { - final ts = SchedulerBinding.instance.currentFrameTimeStamp; + final ts = SchedulerBinding.instance!.currentFrameTimeStamp; if (_lastFrameTimeStamp == ts) return; GTween.ticker.dispatch(elapsed); _lastFrameTimeStamp = ts; @@ -147,36 +147,36 @@ class GTween { static void registerWrap(GxAnimatableBuilder builder) => _tweenableBuilders.add(builder); - static Map _reservedProps; - static GTween _first; - static GTween _last; + static Map? _reservedProps; + static GTween? _first; + static GTween? _last; - double _duration; - Map vars; - GVars nanoVars; - double _startTime; + double? _duration; + Map? vars; + late GVars nanoVars; + late double _startTime; - Object target; + Object? target; /// the real target - Object _animatableTarget; + Object? _animatableTarget; - bool _useFrames; - double ratio = 0; + late bool _useFrames; + double? ratio = 0; - Function _ease; + Function? _ease; // Ease _rawEase; bool _inited = false; - PropTween _firstPT; - GTween _next; - GTween _prev; - List _targets; + PropTween? _firstPT; + GTween? _next; + GTween? _prev; + List? _targets; bool _gc = false; - GTween(this.target, double duration, this.vars, [GVars myVars]) { + GTween(this.target, double duration, this.vars, [GVars? myVars]) { if (_reservedProps == null) { _reservedProps = { 'delay': 1, @@ -206,7 +206,7 @@ class GTween { var targetList = target as List; if (targetList.first is Map || targetList.first is GTweenable) { - _targets = List.of(target); + _targets = List.of(target as Iterable); } /// TODO : add wrap support. @@ -217,7 +217,7 @@ class GTween { /// no process. } else { /// target can be a Function. - GTweenable result; + GTweenable? result; for (final builder in _tweenableBuilders) { result = builder(target); if (result != null) { @@ -243,13 +243,13 @@ class GTween { } _prev = _last; if (_last != null) { - _last._next = this; + _last!._next = this; } else { _first = this; } _last = this; - if (nanoVars.immediateRender || + if (nanoVars.immediateRender! || (duration == 0 && nanoVars.delay == 0 && nanoVars.immediateRender != false)) { @@ -264,18 +264,18 @@ class GTween { // GTween.to(target, 0, nanoVars.startAt.vars, nanoVars.startAt); } if (_targets != null) { - var i = _targets.length; + var i = _targets!.length; while (--i > -1) { - _initProps(_targets[i]); + _initProps(_targets![i]); } } else { _initProps(target); } - if (nanoVars.runBackwards) { + if (nanoVars.runBackwards!) { var pt = _firstPT; while (pt != null) { - pt.s += pt.c; - pt.c = -pt.c; + pt.s += pt.c!; + pt.c = -pt.c!; pt = pt._next; } } @@ -283,20 +283,21 @@ class GTween { } /// initialiazes the PropTween to be used in the target Object. - void _initProps(Object target) { + void _initProps(Object? target) { if (target == null) return; - for (final key in vars.keys) { + for (final key in vars!.keys) { final prop = '$key'; - if (!_reservedProps.containsKey(prop)) { - _firstPT = PropTween(target: target, property: key, next: _firstPT); + if (!_reservedProps!.containsKey(prop)) { + _firstPT = PropTween( + target: target as GTweenable?, property: key, next: _firstPT); var startVal = _getStartValue(target, key); - _firstPT.s = startVal; - var endValue = _getEndValue(vars, key, _firstPT.s); - _firstPT.cObj = vars[key]; - _firstPT.c = endValue; - _firstPT.t.setTweenProp(_firstPT); - if (_firstPT._next != null) { - _firstPT._next._prev = _firstPT; + _firstPT!.s = startVal; + var endValue = _getEndValue(vars!, key, _firstPT!.s); + _firstPT!.cObj = vars![key]; + _firstPT!.c = endValue; + _firstPT!.t!.setTweenProp(_firstPT!); + if (_firstPT!._next != null) { + _firstPT!._next!._prev = _firstPT; } } } @@ -304,15 +305,15 @@ class GTween { /// Can be tweening a List asMap(), so `prop` is better to be /// dynamic. - double _getEndValue(Map pvars, dynamic prop, double start) { + double? _getEndValue(Map pvars, dynamic prop, double? start) { dynamic val = pvars[prop]; if (val is num) { - double v = val + 0.0; - return v - start; + var v = val + 0.0; + return v - start!; } else if (val is String) { if (val.length > 2 && val[1] == '=') { var multiplier = double.tryParse('${val[0]}1') ?? 1; - var factor = double.tryParse(val.substring(2)); + var factor = double.tryParse(val.substring(2))!; return multiplier * factor; } else { return double.tryParse(val); @@ -322,11 +323,11 @@ class GTween { } void _setCurrentValue(PropTween pt, double ratio) { - var value = pt.c * ratio + pt.s; + var value = pt.c! * ratio + pt.s; if (pt.t is GTweenable) { - pt.t.setProperty(pt.p, value); + pt.t!.setProperty(pt.p, value); } else { - pt.t[pt.p] = value; + pt.t![pt.p as String] = value; } } @@ -339,13 +340,13 @@ class GTween { throw 'error'; } - void _render(double time) { + void _render(double? time) { if (!_inited) { _init(); time = 0; } var prevTime = time; - if (time >= _duration) { + if (time! >= _duration!) { time = _duration; ratio = 1; } else if (time <= 0) { @@ -355,12 +356,12 @@ class GTween { ratio = 0; } else { // ratio = _ease.getRatio(time / _duration); - ratio = _ease(time / _duration); + ratio = _ease!(time / _duration!); } var pt = _firstPT; while (pt != null) { - _setCurrentValue(pt, ratio); + _setCurrentValue(pt, ratio!); pt = pt._next; } _signal(nanoVars.onUpdate, nanoVars.onUpdateParams); @@ -374,17 +375,17 @@ class GTween { } } - void _signal(Function callback, CallbackParams params) { + void _signal(Function? callback, CallbackParams? params) { if (callback != null) { /// It's a very slow approach. Function.apply(callback, params?.positional, params?.named); } } - Object _getAnimatable(Object searchTarget) { + Object? _getAnimatable(Object searchTarget) { if (_animatableTarget == searchTarget) return target; if (_targets != null) { - for (var t in _targets) { + for (var t in _targets!) { if (t is GTweenable) { if (t.target == searchTarget) return t; } @@ -393,7 +394,7 @@ class GTween { return null; } - void kill([Object tg]) { + void kill([Object? tg]) { tg ??= _targets ?? target; var pt = _firstPT; if (tg is List) { @@ -407,22 +408,22 @@ class GTween { return; } } else if (_targets != null) { - var i = _targets.length; + var i = _targets!.length; if (tg is! GTweenable) { - tg = _getAnimatable(tg); + tg = _getAnimatable(tg!); } while (--i > -1) { - if (tg == _targets[i]) { - _targets.removeAt(i); + if (tg == _targets![i]) { + _targets!.removeAt(i); } } while (pt != null) { if (pt.t == tg) { if (pt._next != null) { - pt._next._prev = pt._prev; + pt._next!._prev = pt._prev; } if (pt._prev != null) { - pt._prev._next = pt._next; + pt._prev!._next = pt._next; } else { _firstPT = pt._next; } @@ -430,15 +431,15 @@ class GTween { pt = pt._next; } } - if (_targets == null || _targets.isEmpty) { + if (_targets == null || _targets!.isEmpty) { _gc = true; if (_prev != null) { - _prev._next = _next; + _prev!._next = _next; } else if (this == _first) { _first = _next; } if (_next != null) { - _next._prev = _prev; + _next!._prev = _prev; } else if (this == _last) { _last = _prev; } @@ -462,7 +463,8 @@ class GTween { } /// Shortcut to start a tween on an `target`. - static GTween to(Object target, double duration, Map vars, [GVars nanoVars]) { + static GTween to(Object? target, double duration, Map? vars, + [GVars? nanoVars]) { nanoVars ??= GVars(); return GTween(target, duration, vars, nanoVars); } @@ -470,7 +472,7 @@ class GTween { /// Shortcut to start a tween on an `target`, start from the end values /// to the start values, this option flips the tweens. static GTween from(Object target, double duration, Map vars, - [GVars nanoVars]) { + [GVars? nanoVars]) { nanoVars ??= GVars(); nanoVars.runBackwards = true; nanoVars.immediateRender ??= true; @@ -483,7 +485,7 @@ class GTween { static GTween delayedCall( double delay, Function callback, { - Object params, + Object? params, bool useFrames = false, }) { var props = GVars() @@ -518,20 +520,20 @@ class GTween { } } - static bool isTweening(Object target){ + static bool isTweening(Object target) { var t = _first; while (t != null) { var next = t._next; if (t.target == target || t._animatableTarget == target) { - return true ; + return true; } t = next; } - return false ; + return false; } /// Removes a Tween based on the the target object. - static void killTweensOf(Object target) { + static void killTweensOf(Object? target) { var t = _first; while (t != null) { var next = t._next; @@ -545,4 +547,4 @@ class GTween { } } -typedef GxAnimatableBuilder = GTweenable Function(Object target); +typedef GxAnimatableBuilder = GTweenable? Function(Object? target); diff --git a/lib/src/tween/src/lerps/common_lerps.dart b/lib/src/tween/src/lerps/common_lerps.dart index 1a905b1..283cfed 100644 --- a/lib/src/tween/src/lerps/common_lerps.dart +++ b/lib/src/tween/src/lerps/common_lerps.dart @@ -1,16 +1,16 @@ part of gtween; -class GTweenLerpColor extends GTweenLerpProp { +class GTweenLerpColor extends GTweenLerpProp { GTweenLerpColor({ - GTweenSetProp setProp, - GTweenGetProp getProp, + GTweenSetProp? setProp, + GTweenGetProp? getProp, }) : super( setProp: setProp, getProp: getProp, ); @override - Color resolve(double ratio) { + Color? resolve(double ratio) { final value = Color.lerp(from, to, ratio); setProp?.call(value); return value; diff --git a/lib/src/tween/src/mixins/tweenable.dart b/lib/src/tween/src/mixins/tweenable.dart index 68f8430..1fe63c6 100644 --- a/lib/src/tween/src/mixins/tweenable.dart +++ b/lib/src/tween/src/mixins/tweenable.dart @@ -4,16 +4,16 @@ typedef GTweenSetProp = void Function(T targetValue); typedef GTweenGetProp = T Function(); class GTweenLerpProp { - T from; - T to; - String name; + T? from; + T? to; + String? name; - GTweenSetProp setProp; - GTweenGetProp getProp; + GTweenSetProp? setProp; + GTweenGetProp? getProp; GTweenLerpProp({this.setProp, this.getProp}); - T resolve(double ratio) => null; + T? resolve(double ratio) => null; } /// Base interface used by [GTween] to animate properties. @@ -26,11 +26,11 @@ mixin GTweenable { /// Also used by [GTween] to reference internally the "_nativeTarget" instead /// of the [GTweenable] instance. So you can "kill" the tween by [GTweenable] /// or using the actual object that you plan to Tween. - Object target; + Object? target; /// override to know which properties will change. void setTweenProp(PropTween tweenProp) { - final lerpObj = _lerps[tweenProp.p]; + final lerpObj = _lerps[tweenProp.p as String]; if (lerpObj == null) return; lerpObj.to = tweenProp.cObj; tweenProp.c = 1.0; @@ -42,7 +42,7 @@ mixin GTweenable { @override String toString() => '[GTweenable] $target'; - Map> _accessors; + Map>? _accessors; /// Lerps are special objects that are not `double` like /// Color, Rect, etc. @@ -53,35 +53,35 @@ mixin GTweenable { void initProps() => _accessors = getTweenableAccessors(); /// implement in class. - Map> getTweenableAccessors() => null; + Map>? getTweenableAccessors() => null; - void setProperty(Object prop, double value) { - if (_lerps[prop] != null) { - _lerps[prop].resolve(value); + void setProperty(Object? prop, double value) { + if (_lerps[prop as String] != null) { + _lerps[prop]!.resolve(value); // TODO: add setLerp(prop, value) function to be override? } else { if (_accessors == null) initProps(); - _accessors[prop][1](value); + _accessors![prop]![1](value); } } double getProperty(Object prop) { if (_lerps.containsKey(prop)) { - _lerps[prop]?.from = _lerps[prop]?.getProp(); + _lerps[prop as String]?.from = _lerps[prop]?.getProp!(); // TODO: add initLerp(prop) to read the initial value from `target` ? return 0.0; } if (_accessors == null) initProps(); - return _accessors[prop][0](); + return _accessors![prop]![0](); } /// when tween is disposed. void dispose() { - _lerps?.clear(); + _lerps.clear(); // _lerps = null; } - double operator [](String key) => getProperty(key); + double? operator [](String key) => getProperty(key); - void operator []=(String key, double value) => setProperty(key, value); + void operator []=(String? key, double value) => setProperty(key, value); } diff --git a/lib/src/tween/src/wraps/common_wraps.dart b/lib/src/tween/src/wraps/common_wraps.dart index dbc6abb..cd993b6 100644 --- a/lib/src/tween/src/wraps/common_wraps.dart +++ b/lib/src/tween/src/wraps/common_wraps.dart @@ -4,40 +4,39 @@ part of gtween; abstract class CommonTweenWraps { /// TODO: check performance to use a Custom mapping type. /// Lerps (like Color) are managed separately. - static Map> displayObject(GDisplayObject o) { + static Map> displayObject(GDisplayObject? o) { return { - 'x': [() => o.x, (v) => o.x = v], - 'y': [() => o.y, (v) => o.y = v], - 'scaleX': [() => o.scaleX, (v) => o.scaleX = v], - 'scaleY': [() => o.scaleY, (v) => o.scaleY = v], - 'scale': [() => o.scale, (v) => o.scale = v], - 'rotation': [() => o.rotation, (v) => o.rotation = v], - 'rotationX': [() => o.rotationX, (v) => o.rotationX = v], - 'rotationY': [() => o.rotationY, (v) => o.rotationY = v], - 'pivotX': [() => o.pivotX, (v) => o.pivotX = v], - 'pivotY': [() => o.pivotY, (v) => o.pivotY = v], - 'width': [() => o.width, (v) => o.width = v], - 'height': [() => o.height, (v) => o.height = v], - 'skewX': [() => o.skewX, (v) => o.skewX = v], - 'skewY': [() => o.skewY, (v) => o.skewY = v], - 'alpha': [() => o.alpha, (v) => o.alpha = v], + 'x': [() => o!.x, (v) => o!.x = v], + 'y': [() => o!.y, (v) => o!.y = v], + 'scaleX': [() => o!.scaleX, (v) => o!.scaleX = v], + 'scaleY': [() => o!.scaleY, (v) => o!.scaleY = v], + 'scale': [() => o!.scale, (v) => o!.scale = v], + 'rotation': [() => o!.rotation, (v) => o!.rotation = v], + 'rotationX': [() => o!.rotationX, (v) => o!.rotationX = v], + 'rotationY': [() => o!.rotationY, (v) => o!.rotationY = v], + 'pivotX': [() => o!.pivotX, (v) => o!.pivotX = v], + 'pivotY': [() => o!.pivotY, (v) => o!.pivotY = v], + 'width': [() => o!.width, (v) => o!.width = v], + 'height': [() => o!.height, (v) => o!.height = v], + 'skewX': [() => o!.skewX, (v) => o!.skewX = v], + 'skewY': [() => o!.skewY, (v) => o!.skewY = v], + 'alpha': [() => o!.alpha, (v) => o!.alpha = v], }; } } class GTweenableDouble with GTweenable, SingleValueTweenMixin { - static GTweenable wrap(Object target) => + static GTweenable? wrap(Object? target) => target is double ? GTweenableDouble(target) : null; - double value; + double? value; GTweenableDouble(double target) { value = this.target = target; } @override - Map> getTweenableAccessors() => - { + Map> getTweenableAccessors() => { 'value': [() => value, (v) => value = v], }; @@ -46,21 +45,20 @@ class GTweenableDouble with GTweenable, SingleValueTweenMixin { } class GTweenableInt with GTweenable, SingleValueTweenMixin { - static GTweenable wrap(Object target) => + static GTweenable? wrap(Object? target) => target is int ? GTweenableInt(target) : null; - int value; + int? value; GTweenableInt(int target) { value = this.target = target; } @override - Map> getTweenableAccessors() => - { + Map> getTweenableAccessors() => { 'value': [ - () => value + .0, - (v) => value = v.round(), + () => value! + .0, + (v) => value = v.round(), ], }; @@ -69,17 +67,17 @@ class GTweenableInt with GTweenable, SingleValueTweenMixin { } class GTweenableMap with GTweenable { - static GTweenable wrap(Object target) => - target is Map ? GTweenableMap(target) : null; + static GTweenable? wrap(Object? target) => + target is Map ? GTweenableMap(target) : null; - Map value; + late Map value; GTweenableMap(Map target) { value = this.target = target; } @override - void setProperty(Object prop, double val) { + void setProperty(Object? prop, double val) { value[prop] = convertFromDouble(value[prop], val); } @@ -88,24 +86,23 @@ class GTweenableMap with GTweenable { return convertToDouble(value[prop]); } - GTween tween(Map targetMap, { - @required double duration, - EaseFunction ease, - double delay, - bool useFrames, - int overwrite, - VoidCallback onStart, - Object onStartParams, - VoidCallback onComplete, - Object onCompleteParams, - VoidCallback onUpdate, - Object onUpdateParams, - bool runBackwards, - bool immediateRender, - Map startAt, + GTween tween( + Map targetMap, { + required double duration, + EaseFunction? ease, + double? delay, + bool? useFrames, + int? overwrite, + VoidCallback? onStart, + Object? onStartParams, + VoidCallback? onComplete, + Object? onCompleteParams, + VoidCallback? onUpdate, + Object? onUpdateParams, + bool? runBackwards, + bool? immediateRender, + Map? startAt, }) { - assert(targetMap != null); - targetMap.removeWhere((k, v) => !value.containsKey(k)); if (targetMap.isEmpty) { throw ''' @@ -136,20 +133,20 @@ tween(targetMap) Map can't be empty. Or there are no matching keys with the twee } class GTweenableList with GTweenable { - static GTweenable wrap(Object target) { + static GTweenable? wrap(Object? target) { if (target is! List) return null; return GTweenableList(target); } - List value; + late List value; GTweenableList(List target) { value = this.target = target; } @override - void setProperty(Object prop, double val) { - final index = int.tryParse('$prop'); + void setProperty(Object? prop, double val) { + final index = int.tryParse('$prop')!; value[index] = convertFromDouble(value[index], val); } @@ -158,23 +155,23 @@ class GTweenableList with GTweenable { return convertToDouble(value[int.parse('$prop')]); } - GTween tween(List targetList, { - @required double duration, - EaseFunction ease, - double delay, - bool useFrames, - int overwrite, - VoidCallback onStart, - Object onStartParams, - VoidCallback onComplete, - Object onCompleteParams, - VoidCallback onUpdate, - Object onUpdateParams, - bool runBackwards, - bool immediateRender, - Map startAt, + GTween tween( + List targetList, { + required double duration, + EaseFunction? ease, + double? delay, + bool? useFrames, + int? overwrite, + VoidCallback? onStart, + Object? onStartParams, + VoidCallback? onComplete, + Object? onCompleteParams, + VoidCallback? onUpdate, + Object? onUpdateParams, + bool? runBackwards, + bool? immediateRender, + Map? startAt, }) { - assert(targetList != null); targetList.removeWhere((element) => element is! num); if (targetList.isEmpty) { throw ''' @@ -207,7 +204,7 @@ tween(targetList) List can't be empty. Or values inside of it where not a number } } -Object convertFromDouble(Object originalValue, double val) { +Object convertFromDouble(Object? originalValue, double val) { if (originalValue is int) { return val.toInt(); } else if (originalValue is String) { @@ -217,35 +214,35 @@ Object convertFromDouble(Object originalValue, double val) { } } -double convertToDouble(Object val) { +double convertToDouble(Object? val) { if (val is int) { return val + .0; } else if (val is String) { - return double.tryParse(val); + return double.tryParse(val) as double; } - return val; + return val as double; } mixin SingleValueTweenMixin { - Object getValue; + Object? getValue; - GTween tween(Object value, { - @required double duration, - EaseFunction ease, - double delay, - bool useFrames, - int overwrite, - Function onStart, - Object onStartParams, - Function onComplete, - Object onCompleteParams, - Function onUpdate, - Object onUpdateParams, - bool runBackwards, - bool immediateRender, - Map startAt, + GTween tween( + Object value, { + required double duration, + EaseFunction? ease, + double? delay, + bool? useFrames, + int? overwrite, + Function? onStart, + Object? onStartParams, + Function? onComplete, + Object? onCompleteParams, + Function? onUpdate, + Object? onUpdateParams, + bool? runBackwards, + bool? immediateRender, + Map? startAt, }) { - assert(value != null); return GTween.to( this, duration, diff --git a/lib/src/tween/src/wraps/display_object.dart b/lib/src/tween/src/wraps/display_object.dart index 428b8fe..8216359 100644 --- a/lib/src/tween/src/wraps/display_object.dart +++ b/lib/src/tween/src/wraps/display_object.dart @@ -1,7 +1,7 @@ part of gtween; class GTweenableDisplayObject with GTweenable { - static GTweenable wrap(Object target) { + static GTweenable? wrap(Object? target) { if (target is! GDisplayObject) return null; return GTweenableDisplayObject(target); } @@ -20,5 +20,5 @@ class GTweenableDisplayObject with GTweenable { @override Map> getTweenableAccessors() => - CommonTweenWraps.displayObject(target); + CommonTweenWraps.displayObject(target as GDisplayObject?); } diff --git a/lib/src/tween/src/wraps/filter_wraps.dart b/lib/src/tween/src/wraps/filter_wraps.dart index cd3031f..e600fc5 100644 --- a/lib/src/tween/src/wraps/filter_wraps.dart +++ b/lib/src/tween/src/wraps/filter_wraps.dart @@ -1,12 +1,12 @@ part of gtween; class GTweenableBlur with GTweenable { - static GTweenable wrap(Object target) { + static GTweenable? wrap(Object target) { if (target is! GBlurFilter) return null; return GTweenableBlur(target); } - GBlurFilter value; + late GBlurFilter value; GTweenableBlur(GBlurFilter target) { value = this.target = target; @@ -19,22 +19,22 @@ class GTweenableBlur with GTweenable { }; GTween tween({ - @required double duration, - Object blurX, - Object blurY, - EaseFunction ease, - double delay, - bool useFrames, + required double duration, + Object? blurX, + Object? blurY, + EaseFunction? ease, + double? delay, + bool? useFrames, int overwrite = 1, - VoidCallback onStart, - Object onStartParams, - VoidCallback onComplete, - Object onCompleteParams, - VoidCallback onUpdate, - Object onUpdateParams, - bool runBackwards, - bool immediateRender, - Map startAt, + VoidCallback? onStart, + Object? onStartParams, + VoidCallback? onComplete, + Object? onCompleteParams, + VoidCallback? onUpdate, + Object? onUpdateParams, + bool? runBackwards, + bool? immediateRender, + Map? startAt, }) { final targetMap = { if (blurX != null) 'blurX': blurX, @@ -63,12 +63,12 @@ class GTweenableBlur with GTweenable { } class GTweenableDropShadowFilter with GTweenable { - static GTweenable wrap(Object target) { + static GTweenable? wrap(Object target) { if (target is! GDropShadowFilter) return null; return GTweenableDropShadowFilter(target); } - GDropShadowFilter value; + late GDropShadowFilter value; GTweenableDropShadowFilter(GDropShadowFilter target) { value = this.target = target; @@ -91,25 +91,25 @@ class GTweenableDropShadowFilter with GTweenable { }; GTween tween({ - @required double duration, - Object blurX, - Object blurY, - Object angle, - Object distance, - Color color, - EaseFunction ease, - double delay, - bool useFrames, + required double duration, + Object? blurX, + Object? blurY, + Object? angle, + Object? distance, + Color? color, + EaseFunction? ease, + double? delay, + bool? useFrames, int overwrite = 1, - VoidCallback onStart, - Object onStartParams, - VoidCallback onComplete, - Object onCompleteParams, - VoidCallback onUpdate, - Object onUpdateParams, - bool runBackwards, - bool immediateRender, - Map startAt, + VoidCallback? onStart, + Object? onStartParams, + VoidCallback? onComplete, + Object? onCompleteParams, + VoidCallback? onUpdate, + Object? onUpdateParams, + bool? runBackwards, + bool? immediateRender, + Map? startAt, }) { final targetMap = { if (blurX != null) 'blurX': blurX, @@ -141,12 +141,12 @@ class GTweenableDropShadowFilter with GTweenable { } class GTweenableGlowFilter with GTweenable { - static GTweenable wrap(Object target) { + static GTweenable? wrap(Object target) { if (target is! GlowFilter) return null; return GTweenableGlowFilter(target); } - GlowFilter value; + late GlowFilter value; GTweenableGlowFilter(GlowFilter target) { value = this.target = target; @@ -167,23 +167,23 @@ class GTweenableGlowFilter with GTweenable { }; GTween tween({ - @required double duration, - Object blurX, - Object blurY, - Color color, - EaseFunction ease, - double delay, - bool useFrames, + required double duration, + Object? blurX, + Object? blurY, + Color? color, + EaseFunction? ease, + double? delay, + bool? useFrames, int overwrite = 1, - VoidCallback onStart, - Object onStartParams, - VoidCallback onComplete, - Object onCompleteParams, - VoidCallback onUpdate, - Object onUpdateParams, - bool runBackwards, - bool immediateRender, - Map startAt, + VoidCallback? onStart, + Object? onStartParams, + VoidCallback? onComplete, + Object? onCompleteParams, + VoidCallback? onUpdate, + Object? onUpdateParams, + bool? runBackwards, + bool? immediateRender, + Map? startAt, }) { final targetMap = { if (blurX != null) 'blurX': blurX, diff --git a/lib/src/tween/src/wraps/geom_wraps.dart b/lib/src/tween/src/wraps/geom_wraps.dart index 534d169..323ab7c 100644 --- a/lib/src/tween/src/wraps/geom_wraps.dart +++ b/lib/src/tween/src/wraps/geom_wraps.dart @@ -1,12 +1,12 @@ part of gtween; class GTweenablePoint with GTweenable { - static GTweenable wrap(Object target) { + static GTweenable? wrap(Object target) { if (target is! GPoint) return null; return GTweenablePoint(target); } - GPoint value; + late GPoint value; GTweenablePoint(GPoint target) { value = this.target = target; @@ -19,23 +19,23 @@ class GTweenablePoint with GTweenable { }; GTween tween({ - @required double duration, - Object x, - Object y, - GPoint to, - EaseFunction ease, - double delay, - bool useFrames, - int overwrite, - VoidCallback onStart, - Object onStartParams, - VoidCallback onComplete, - Object onCompleteParams, - VoidCallback onUpdate, - Object onUpdateParams, - bool runBackwards, - bool immediateRender, - Map startAt, + required double duration, + Object? x, + Object? y, + GPoint? to, + EaseFunction? ease, + double? delay, + bool? useFrames, + int? overwrite, + VoidCallback? onStart, + Object? onStartParams, + VoidCallback? onComplete, + Object? onCompleteParams, + VoidCallback? onUpdate, + Object? onUpdateParams, + bool? runBackwards, + bool? immediateRender, + Map? startAt, }) { if ((x != null || y != null) && to != null) { throw ''' @@ -71,12 +71,12 @@ GTween Can't use 'x, y' AND 'to' arguments for GxPoint tween. Choose one'''; } class GTweenableRect with GTweenable { - static GTweenable wrap(Object target) { + static GTweenable? wrap(Object target) { if (target is! GRect) return null; return GTweenableRect(target); } - GRect value; + late GRect value; GTweenableRect(GRect target) { value = this.target = target; @@ -91,25 +91,25 @@ class GTweenableRect with GTweenable { }; GTween tween( - {@required double duration, - Object x, - Object y, - Object width, - Object height, - GRect to, - EaseFunction ease, - double delay, - bool useFrames, - int overwrite, - VoidCallback onStart, - Object onStartParams, - VoidCallback onComplete, - Object onCompleteParams, - VoidCallback onUpdate, - Object onUpdateParams, - bool runBackwards, - bool immediateRender, - Map startAt}) { + {required double duration, + Object? x, + Object? y, + Object? width, + Object? height, + GRect? to, + EaseFunction? ease, + double? delay, + bool? useFrames, + int? overwrite, + VoidCallback? onStart, + Object? onStartParams, + VoidCallback? onComplete, + Object? onCompleteParams, + VoidCallback? onUpdate, + Object? onUpdateParams, + bool? runBackwards, + bool? immediateRender, + Map? startAt}) { if ((x != null || y != null || width != null || height != null) && to != null) { throw "GTween Can't use 'x, y, width, height' AND 'to' arguments to " @@ -151,14 +151,14 @@ class GTweenableRect with GTweenable { } class GTweenableColor with GTweenable { - static GTweenable wrap(Object target) { + static GTweenable? wrap(Object target) { if (target is! Color) return null; return GTweenableColor(target); } - Color value; - PropTween _propTween; - Color _targetColor; + Color? value; + late PropTween _propTween; + Color? _targetColor; @override void setTweenProp(PropTween tweenProp) { @@ -171,29 +171,28 @@ class GTweenableColor with GTweenable { } @override - void setProperty(Object prop, double val) { - value = Color.lerp(target, _targetColor, val); + void setProperty(Object? prop, double val) { + value = Color.lerp(target as Color?, _targetColor, val); } @override double getProperty(Object prop) => 0.0; // start value, from 0-1 GTween tween(Color color, - {@required double duration, - EaseFunction ease, - double delay, - bool useFrames, - int overwrite, - VoidCallback onStart, - Object onStartParams, - VoidCallback onComplete, - Object onCompleteParams, - VoidCallback onUpdate, - Object onUpdateParams, - bool runBackwards, - bool immediateRender, - Map startAt}) { - assert(color != null); + {required double duration, + EaseFunction? ease, + double? delay, + bool? useFrames, + int? overwrite, + VoidCallback? onStart, + Object? onStartParams, + VoidCallback? onComplete, + Object? onCompleteParams, + VoidCallback? onUpdate, + Object? onUpdateParams, + bool? runBackwards, + bool? immediateRender, + Map? startAt}) { _targetColor = color; return GTween.to( this, diff --git a/lib/src/utils/context_utils.dart b/lib/src/utils/context_utils.dart index 43919cc..ee83862 100644 --- a/lib/src/utils/context_utils.dart +++ b/lib/src/utils/context_utils.dart @@ -4,7 +4,7 @@ import '../../graphx.dart'; abstract class ContextUtils { /// todo: validate RenderObject Type. - static GRect getRenderObjectBounds(BuildContext context) { + static GRect? getRenderObjectBounds(BuildContext context) { final box = context.findRenderObject() as RenderBox; return GRect.fromNative(box.localToGlobal(Offset.zero) & box.size); } diff --git a/lib/src/utils/http/_http_io.dart b/lib/src/utils/http/_http_io.dart index a51c649..8b19dce 100644 --- a/lib/src/utils/http/_http_io.dart +++ b/lib/src/utils/http/_http_io.dart @@ -3,17 +3,18 @@ import 'dart:typed_data'; import 'package:flutter/foundation.dart'; -/// Fetches an HTTP resource from the specified [url] using the specified [headers]. -Future httpGet(String url, {Map headers}) async { - final HttpClient httpClient = HttpClient(); - final Uri uri = Uri.base.resolve(url); - final HttpClientRequest request = await httpClient.getUrl(uri); +/// Fetches an HTTP resource from the specified +/// [url] using the specified [headers]. +Future httpGet(String url, {Map? headers}) async { + final httpClient = HttpClient(); + final uri = Uri.base.resolve(url); + final request = await httpClient.getUrl(uri); if (headers != null) { - headers.forEach((String key, String value) { + headers.forEach((key, value) { request.headers.add(key, value); }); } - final HttpClientResponse response = await request.close(); + final response = await request.close(); if (response.statusCode != HttpStatus.ok) { throw HttpException('Could not get network asset', uri: uri); diff --git a/lib/src/utils/http/_http_web.dart b/lib/src/utils/http/_http_web.dart index 236b087..0347135 100644 --- a/lib/src/utils/http/_http_web.dart +++ b/lib/src/utils/http/_http_web.dart @@ -1,9 +1,10 @@ import 'dart:html' as html; import 'dart:typed_data'; -/// Fetches an HTTP resource from the specified [url] using the specified [headers]. -Future httpGet(String url, {Map headers}) async { - final html.HttpRequest request = await html.HttpRequest.request(url, +/// Fetches an HTTP resource from the specified +/// [url] using the specified [headers]. +Future httpGet(String url, {Map? headers}) async { + final request = await html.HttpRequest.request(url, requestHeaders: headers, responseType: 'arraybuffer'); if (request.status != html.HttpStatus.ok) { throw 'Could not get network asset: "$url"'; diff --git a/lib/src/utils/keyboard_util.dart b/lib/src/utils/keyboard_util.dart index 1f9b6ba..214a1c3 100644 --- a/lib/src/utils/keyboard_util.dart +++ b/lib/src/utils/keyboard_util.dart @@ -152,9 +152,11 @@ class GKeyboard { static const copy = GKeyboard._(LogicalKeyboardKey.copy); static const paste = GKeyboard._(LogicalKeyboardKey.paste); static const find = GKeyboard._(LogicalKeyboardKey.find); - static const audioVolumeMute = GKeyboard._(LogicalKeyboardKey.audioVolumeMute); + static const audioVolumeMute = + GKeyboard._(LogicalKeyboardKey.audioVolumeMute); static const audioVolumeUp = GKeyboard._(LogicalKeyboardKey.audioVolumeUp); - static const audioVolumeDown = GKeyboard._(LogicalKeyboardKey.audioVolumeDown); + static const audioVolumeDown = + GKeyboard._(LogicalKeyboardKey.audioVolumeDown); static const numpadComma = GKeyboard._(LogicalKeyboardKey.numpadComma); static const intlRo = GKeyboard._(LogicalKeyboardKey.intlRo); static const kanaMode = GKeyboard._(LogicalKeyboardKey.kanaMode); @@ -168,17 +170,20 @@ class GKeyboard { static const lang5 = GKeyboard._(LogicalKeyboardKey.lang5); static const abort = GKeyboard._(LogicalKeyboardKey.abort); static const props = GKeyboard._(LogicalKeyboardKey.props); - static const numpadParenLeft = GKeyboard._(LogicalKeyboardKey.numpadParenLeft); + static const numpadParenLeft = + GKeyboard._(LogicalKeyboardKey.numpadParenLeft); static const numpadParenRight = GKeyboard._(LogicalKeyboardKey.numpadParenRight); - static const numpadBackspace = GKeyboard._(LogicalKeyboardKey.numpadBackspace); + static const numpadBackspace = + GKeyboard._(LogicalKeyboardKey.numpadBackspace); static const numpadMemoryStore = GKeyboard._(LogicalKeyboardKey.numpadMemoryStore); static const numpadMemoryRecall = GKeyboard._(LogicalKeyboardKey.numpadMemoryRecall); static const numpadMemoryClear = GKeyboard._(LogicalKeyboardKey.numpadMemoryClear); - static const numpadMemoryAdd = GKeyboard._(LogicalKeyboardKey.numpadMemoryAdd); + static const numpadMemoryAdd = + GKeyboard._(LogicalKeyboardKey.numpadMemoryAdd); static const numpadMemorySubtract = GKeyboard._(LogicalKeyboardKey.numpadMemorySubtract); static const numpadSignChange = @@ -246,13 +251,15 @@ class GKeyboard { static const launchControlPanel = GKeyboard._(LogicalKeyboardKey.launchControlPanel); static const selectTask = GKeyboard._(LogicalKeyboardKey.selectTask); - static const launchDocuments = GKeyboard._(LogicalKeyboardKey.launchDocuments); + static const launchDocuments = + GKeyboard._(LogicalKeyboardKey.launchDocuments); static const spellCheck = GKeyboard._(LogicalKeyboardKey.spellCheck); static const launchKeyboardLayout = GKeyboard._(LogicalKeyboardKey.launchKeyboardLayout); static const launchScreenSaver = GKeyboard._(LogicalKeyboardKey.launchScreenSaver); - static const launchAssistant = GKeyboard._(LogicalKeyboardKey.launchAssistant); + static const launchAssistant = + GKeyboard._(LogicalKeyboardKey.launchAssistant); static const launchAudioBrowser = GKeyboard._(LogicalKeyboardKey.launchAudioBrowser); static const newKey = GKeyboard._(LogicalKeyboardKey.newKey); @@ -296,8 +303,10 @@ class GKeyboard { static const gameButtonA = GKeyboard._(LogicalKeyboardKey.gameButtonA); static const gameButtonB = GKeyboard._(LogicalKeyboardKey.gameButtonB); static const gameButtonC = GKeyboard._(LogicalKeyboardKey.gameButtonC); - static const gameButtonLeft1 = GKeyboard._(LogicalKeyboardKey.gameButtonLeft1); - static const gameButtonLeft2 = GKeyboard._(LogicalKeyboardKey.gameButtonLeft2); + static const gameButtonLeft1 = + GKeyboard._(LogicalKeyboardKey.gameButtonLeft1); + static const gameButtonLeft2 = + GKeyboard._(LogicalKeyboardKey.gameButtonLeft2); static const gameButtonMode = GKeyboard._(LogicalKeyboardKey.gameButtonMode); static const gameButtonRight1 = GKeyboard._(LogicalKeyboardKey.gameButtonRight1); @@ -305,7 +314,8 @@ class GKeyboard { GKeyboard._(LogicalKeyboardKey.gameButtonRight2); static const gameButtonSelect = GKeyboard._(LogicalKeyboardKey.gameButtonSelect); - static const gameButtonStart = GKeyboard._(LogicalKeyboardKey.gameButtonStart); + static const gameButtonStart = + GKeyboard._(LogicalKeyboardKey.gameButtonStart); static const gameButtonThumbLeft = GKeyboard._(LogicalKeyboardKey.gameButtonThumbLeft); static const gameButtonThumbRight = @@ -328,15 +338,15 @@ class GKeyboard { alt: () => isDown(altLeft) || isDown(altRight), }; - static Stage _stage; + static Stage? _stage; static bool justReleased(GKeyboard key) { - return _justReleased[key] != null; + return _justReleased[key as LogicalKeyboardKey] != null; } static bool isDown(GKeyboard key) { if (_metaKeys.containsKey(key)) { - return _metaKeys[key](); + return _metaKeys[key]!(); } return _pressed[key.value] ?? false; } @@ -344,17 +354,17 @@ class GKeyboard { /// Initializer of the Keyboard utility class. static void init(Stage stage) { _stage = stage; - _stage.keyboard.onDown.add(_onKey); - _stage.keyboard.onUp.add(_onKey); + _stage!.keyboard!.onDown.add(_onKey); + _stage!.keyboard!.onUp.add(_onKey); } static void dispose() { - _stage?.keyboard?.onDown?.remove(_onKey); - _stage?.keyboard?.onUp?.remove(_onKey); + _stage?.keyboard?.onDown.remove(_onKey); + _stage?.keyboard?.onUp.remove(_onKey); } static void _onKey(KeyboardEventData input) { - final k = input.rawEvent.logicalKey; + final k = input.rawEvent!.logicalKey; if (input.type == KeyEventType.down) { _pressed[k] = true; } else { diff --git a/lib/src/utils/layout_utils.dart b/lib/src/utils/layout_utils.dart index d2280d2..3b046e0 100644 --- a/lib/src/utils/layout_utils.dart +++ b/lib/src/utils/layout_utils.dart @@ -22,25 +22,24 @@ class LayoutUtils { static void objectFit( GDisplayObject object, { BoxFit fit = BoxFit.cover, - double objW, - double objH, - @required double canvasW, - @required double canvasH, + double? objW, + double? objH, + required double canvasW, + required double canvasH, bool reposition = false, }) { - assert(canvasW != null && canvasH != null); if (objW == null || objH == null) { /// calculate real objects bounds. if (object is GBitmap) { - objW ??= object.texture.width; - objH ??= object.texture.height; + objW ??= object.texture!.width; + objH ??= object.texture!.height; } else { - final bounds = object.bounds; + final bounds = object.bounds!; objW ??= bounds.width; objH ??= bounds.height; } } - var r1 = objW / objH; + var r1 = objW! / objH!; var r2 = canvasW / canvasH; if (fit == BoxFit.scaleDown) { @@ -143,7 +142,7 @@ class LayoutUtils { double gapX = 0, double gapY = 0, int rows = 0, - @required int cols, + required int cols, double width = 0, double height = 0, double startX = 0, @@ -203,7 +202,7 @@ class LayoutUtils { width = maxW; } - final parent = items?.first?.parent as GSprite; + final parent = items.first.parent as GSprite?; final hasSize = width > 0 && height > 0; if (debug && parent != null && hasSize) { final g = parent.graphics; @@ -303,7 +302,7 @@ class LayoutUtils { height = maxH; } - final parent = items?.first?.parent as GSprite; + final parent = items.first.parent as GSprite?; final hasSize = width > 0 && height > 0; if (debug && parent != null && hasSize) { final g = parent.graphics; diff --git a/lib/src/utils/list_utils.dart b/lib/src/utils/list_utils.dart index 74a68aa..bbf604f 100644 --- a/lib/src/utils/list_utils.dart +++ b/lib/src/utils/list_utils.dart @@ -1,10 +1,12 @@ - - import '../../graphx.dart'; abstract class ListUtils { - static void mergeSort(List input, SortChildrenCallback compare, - int startIndex, int len, List buffer) { + static void mergeSort( + List input, + SortChildrenCallback compare, + int startIndex, + int len, + List buffer) { if (len > 1) { int i, endIndex = startIndex + len, diff --git a/lib/src/utils/matrix_utils.dart b/lib/src/utils/matrix_utils.dart index 722cbe3..4f38be5 100644 --- a/lib/src/utils/matrix_utils.dart +++ b/lib/src/utils/matrix_utils.dart @@ -9,30 +9,30 @@ abstract class MatrixUtils { var sinY = Math.sin(skewY); var cosY = Math.cos(skewY); matrix.setTo( - matrix.a * cosY - matrix.b * sinX, - matrix.a * sinY + matrix.b * cosX, - matrix.c * cosY - matrix.d * sinX, - matrix.c * sinY + matrix.d * cosX, - matrix.tx * cosY - matrix.ty * sinX, - matrix.tx * sinY + matrix.ty * cosX, + matrix.a* cosY - matrix.b* sinX, + matrix.a* sinY + matrix.b* cosX, + matrix.c* cosY - matrix.d* sinX, + matrix.c* sinY + matrix.d* cosX, + matrix.tx* cosY - matrix.ty* sinX, + matrix.tx* sinY + matrix.ty* cosX, ); } static GRect getTransformedBoundsRect(GMatrix matrix, GRect rect, - [GRect out]) { + [GRect? out]) { out ??= GRect(); var minX = 10000000.0; var maxX = -10000000.0; var minY = 10000000.0; var maxY = -10000000.0; - var tx1 = matrix.a * rect.x + matrix.c * rect.y + matrix.tx; - var ty1 = matrix.d * rect.y + matrix.b * rect.x + matrix.ty; - var tx2 = matrix.a * rect.x + matrix.c * rect.bottom + matrix.tx; - var ty2 = matrix.d * rect.bottom + matrix.b * rect.x + matrix.ty; - var tx3 = matrix.a * rect.right + matrix.c * rect.y + matrix.tx; - var ty3 = matrix.d * rect.y + matrix.b * rect.right + matrix.ty; - var tx4 = matrix.a * rect.right + matrix.c * rect.bottom + matrix.tx; - var ty4 = matrix.d * rect.bottom + matrix.b * rect.right + matrix.ty; + var tx1 = matrix.a* rect.x+ matrix.c* rect.y+ matrix.tx; + var ty1 = matrix.d* rect.y+ matrix.b* rect.x+ matrix.ty; + var tx2 = matrix.a* rect.x+ matrix.c* rect.bottom + matrix.tx; + var ty2 = matrix.d* rect.bottom + matrix.b* rect.x+ matrix.ty; + var tx3 = matrix.a* rect.right + matrix.c* rect.y+ matrix.tx; + var ty3 = matrix.d* rect.y+ matrix.b* rect.right + matrix.ty; + var tx4 = matrix.a* rect.right + matrix.c* rect.bottom + matrix.tx; + var ty4 = matrix.d* rect.bottom + matrix.b* rect.right + matrix.ty; if (minX > tx1) minX = tx1; if (minX > tx2) minX = tx2; if (minX > tx3) minX = tx3; diff --git a/lib/src/utils/mixins.dart b/lib/src/utils/mixins.dart index 1dbfb1e..3f22f07 100644 --- a/lib/src/utils/mixins.dart +++ b/lib/src/utils/mixins.dart @@ -3,7 +3,7 @@ import 'dart:ui'; import '../../graphx.dart'; mixin RenderUtilMixin { - Picture createPicture([void Function(Canvas) prePaintCallback]) { + Picture createPicture([void Function(Canvas)? prePaintCallback]) { final r = PictureRecorder(); final c = Canvas(r); prePaintCallback?.call(c); @@ -53,14 +53,14 @@ mixin RenderUtilMixin { final width = adjustOffset ? rect.width.toInt() : rect.right.toInt(); final height = adjustOffset ? rect.height.toInt() : rect.bottom.toInt(); final output = await picture.toImage(width, height); - picture?.dispose(); + picture.dispose(); return output; } } mixin DisplayMasking { - GRect maskRect; - double maskRectCornerRadius; + GRect? maskRect; + double? maskRectCornerRadius; bool maskRectInverted = false; /// Direct scissor rect masking, more optimized than using @@ -78,15 +78,15 @@ mixin DisplayMasking { /// By default GxRect has no corners, so is only implemented to make use /// of `RRect` clipping. /// - void $applyMaskRect(Canvas c) { - if (maskRect.hasCorners) { - c.clipRRect( - maskRect.toRoundNative(), + void $applyMaskRect(Canvas? c) { + if (maskRect!.hasCorners) { + c!.clipRRect( + maskRect!.toRoundNative(), doAntiAlias: true, ); } else { - c.clipRect( - maskRect.toNative(), + c!.clipRect( + maskRect!.toNative(), clipOp: maskRectInverted ? ClipOp.difference : ClipOp.intersect, doAntiAlias: true, ); diff --git a/lib/src/utils/pools.dart b/lib/src/utils/pools.dart index 11b227f..940a896 100644 --- a/lib/src/utils/pools.dart +++ b/lib/src/utils/pools.dart @@ -17,7 +17,7 @@ mixin Pool { /// Remember to NOT KEEP any references to the object after moving it to /// the pool. static void putPoint(GPoint point) { - if (point != null) _points.add(point); + _points.add(point); } static GMatrix getMatrix([ @@ -33,7 +33,7 @@ mixin Pool { } static void putMatrix(GMatrix matrix) { - if (matrix != null) _matrices.add(matrix); + _matrices.add(matrix); } static GRect getRect([ @@ -47,6 +47,6 @@ mixin Pool { } static void putRect(GRect rect) { - if (rect != null) _rectangles.add(rect); + _rectangles.add(rect); } } diff --git a/lib/src/utils/string_utils.dart b/lib/src/utils/string_utils.dart index df31939..309f7de 100644 --- a/lib/src/utils/string_utils.dart +++ b/lib/src/utils/string_utils.dart @@ -1,8 +1,5 @@ class StringUtils { static bool parseBoolean(String value) { - if (value == null) { - return false; - } return value == 'true' || value == 'TRUE' || value == 'True' || diff --git a/lib/src/utils/texture_utils.dart b/lib/src/utils/texture_utils.dart index ba1d104..1e6533e 100644 --- a/lib/src/utils/texture_utils.dart +++ b/lib/src/utils/texture_utils.dart @@ -10,25 +10,25 @@ mixin GTextureUtils { static void scale9Rect( GTexture tx, double x, { - double y, - double w, - double h, + double? y, + double? w, + double? h, bool adjustScale = false, }) { y ??= x; w ??= -x; h ??= -y; if (adjustScale) { - x *= tx.scale; - y *= tx.scale; - w *= tx.scale; - h *= tx.scale; + x *= tx.scale!; + y *= tx.scale!; + w *= tx.scale!; + h *= tx.scale!; } if (w < 0) { - w = tx.width + w * 2; + w = tx.width! + w * 2; } if (h < 0) { - h = tx.height + h * 2; + h = tx.height! + h * 2; } var out = GRect(x, y, w, h); tx.scale9Grid = out; @@ -39,7 +39,7 @@ mixin GTextureUtils { double radius = 20, double x = 0, double y = 0, - String id, + String? id, }) async { _g.clear()..beginFill(color).drawCircle(x, y, radius); return await _drawShape(id); @@ -51,7 +51,7 @@ mixin GTextureUtils { double y = 0, double w = 20, double h = 20, - String id, + String? id, }) async { _g.clear()..beginFill(color).drawRect(x, y, w, h); return (await _drawShape(id)); @@ -64,7 +64,7 @@ mixin GTextureUtils { double w = 20, double h = 20, double r = 8, - String id, + String? id, }) async { _g.clear()..beginFill(color).drawRoundRect(x, y, w, h, r); return (await _drawShape(id)); @@ -75,7 +75,7 @@ mixin GTextureUtils { double w = 20, double h = 20, double rotation = 0, - String id, + String? id, }) async { _g.clear() .beginFill(color) @@ -88,7 +88,7 @@ mixin GTextureUtils { return tx; } - static Future _drawShape([String id]) async { + static Future _drawShape([String? id]) async { final tx = await _helperShape.createImageTexture( true, GTextureUtils.resolution, @@ -102,15 +102,15 @@ mixin GTextureUtils { static List getRectAtlasFromGTexture( GTexture base, int w, { - int h, + int? h, int padding = 0, double scale = 1, }) { h ??= w; /// create SubTextures from the main Texture. - var cols = base.sourceRect.width / w; - var rows = base.sourceRect.height / h; + var cols = base.sourceRect!.width/ w; + var rows = base.sourceRect!.height/ h; var total = cols * rows; var output = []; final _w = w.toDouble(); diff --git a/lib/src/widgets/graphics_clipper.dart b/lib/src/widgets/graphics_clipper.dart index 3b62592..a70438d 100644 --- a/lib/src/widgets/graphics_clipper.dart +++ b/lib/src/widgets/graphics_clipper.dart @@ -40,7 +40,7 @@ abstract class GraphicsClipper extends CustomClipper { final m = Pool.getMatrix(); m.setTransform( x, y, pivotX, pivotY, scaleX, scaleY, skewX, skewY, rotation); - final result = p.transform(m.toNative().storage); + final result = p.transform(m.toNative()!.storage); Pool.putMatrix(m); return result; } diff --git a/lib/src/widgets/graphx_widget.dart b/lib/src/widgets/graphx_widget.dart index e2797eb..0d77d6d 100644 --- a/lib/src/widgets/graphx_widget.dart +++ b/lib/src/widgets/graphx_widget.dart @@ -5,7 +5,7 @@ import '../../graphx.dart'; import '../core/core.dart'; class SceneBuilderWidget extends StatefulWidget { - final Widget child; + final Widget? child; final SceneController Function() builder; @@ -22,8 +22,8 @@ class SceneBuilderWidget extends StatefulWidget { final HitTestBehavior pointerBehaviour; const SceneBuilderWidget({ - Key key, - this.builder, + Key? key, + required this.builder, this.child, this.painterIsComplex = true, this.mouseOpaque = true, @@ -35,24 +35,26 @@ class SceneBuilderWidget extends StatefulWidget { } class _SceneBuilderWidgetState extends State { - SceneController _controller; + late SceneController _controller; @override void initState() { super.initState(); _controller = widget.builder(); + _controller.resolveWindowBounds = _getRenderObjectWindowBounds; _controller.$init(); } - GRect _getRenderObjectWindowBounds() { + GRect? _getRenderObjectWindowBounds() { if (!mounted) return null; + trace(context); return ContextUtils.getRenderObjectBounds(context); } @override void dispose() { - _controller?.dispose(); + _controller.dispose(); super.dispose(); } @@ -79,30 +81,30 @@ class _SceneBuilderWidgetState extends State { ); var converter = _controller.$inputConverter; - if (_controller.config.usePointer) { + if (_controller.config.usePointer ?? false) { child = MouseRegion( - onEnter: converter.pointerEnter, - onExit: converter.pointerExit, - onHover: converter.pointerHover, + onEnter: converter?.pointerEnter, + onExit: converter?.pointerExit, + onHover: converter?.pointerHover, cursor: MouseCursor.defer, opaque: widget.mouseOpaque, child: Listener( child: child, behavior: widget.pointerBehaviour, - onPointerDown: converter.pointerDown, - onPointerUp: converter.pointerUp, - onPointerCancel: converter.pointerCancel, - onPointerMove: converter.pointerMove, - onPointerSignal: converter.pointerSignal, + onPointerDown: converter?.pointerDown, + onPointerUp: converter?.pointerUp, + onPointerCancel: converter?.pointerCancel, + onPointerMove: converter?.pointerMove, + onPointerSignal: converter?.pointerSignal, ), ); } - if (_controller.config.useKeyboard) { + if (_controller.config.useKeyboard ?? false) { child = RawKeyboardListener( - onKey: converter.handleKey, + onKey: converter!.handleKey, autofocus: true, includeSemantics: false, - focusNode: converter.keyboard.focusNode, + focusNode: converter.keyboard?.focusNode ?? FocusNode(), child: child, ); } diff --git a/lib/src/widgets/mps_widget.dart b/lib/src/widgets/mps_widget.dart index a7ff7bf..7c6abee 100644 --- a/lib/src/widgets/mps_widget.dart +++ b/lib/src/widgets/mps_widget.dart @@ -5,7 +5,7 @@ import '../../graphx.dart'; typedef MPSFunctionBuilder = Widget Function( BuildContext context, MPSEvent event, - Widget child, + Widget? child, ); /// [MPSBuilder] allows you to subscribe to multiple MinPubSub topics. @@ -18,16 +18,16 @@ typedef MPSFunctionBuilder = Widget Function( /// or 1 parameter[T] `ems.emit1(topic, value)`. Data is captured and sent as /// 2nd parameter ([MPSEvent] event object) in the [build] function. class MPSBuilder extends StatefulWidget { - final Widget child; + final Widget? child; final MPS mps; final MPSFunctionBuilder builder; final List topics; const MPSBuilder({ - Key key, - @required this.builder, - @required this.topics, - @required this.mps, + Key? key, + required this.builder, + required this.topics, + required this.mps, this.child, }) : super(key: key); @@ -79,7 +79,7 @@ class _MPSBuilderState extends State> { /// Model object passed as 2nd argument in [MPSBuilder.builder]. class MPSEvent { final String type; - final T data; + final T? data; factory MPSEvent.empty() => const MPSEvent(''); diff --git a/pubspec.lock b/pubspec.lock index 20d2c0b..9d3f47d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,63 +7,49 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0-nullsafety.3" + version: "2.5.0" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.3" + version: "2.1.0" characters: dependency: transitive description: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety.5" + version: "1.1.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety.3" + version: "1.2.0" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety.3" + version: "1.1.0" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0-nullsafety.5" - convert: - dependency: transitive - description: - name: convert - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.1" - effective_dart: - dependency: "direct dev" - description: - name: effective_dart - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" + version: "1.15.0" fake_async: dependency: transitive description: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety.3" + version: "1.2.0" flutter: dependency: "direct main" description: flutter @@ -80,49 +66,49 @@ packages: name: http url: "https://pub.dartlang.org" source: hosted - version: "0.12.2" + version: "0.13.0" http_parser: dependency: transitive description: name: http_parser url: "https://pub.dartlang.org" source: hosted - version: "3.1.4" + version: "4.0.0" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10-nullsafety.3" + version: "0.12.10" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0-nullsafety.6" + version: "1.3.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0-nullsafety.3" + version: "1.8.0" pedantic: - dependency: "direct dev" + dependency: transitive description: name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "1.9.2" + version: "1.11.0" petitparser: dependency: transitive description: name: petitparser url: "https://pub.dartlang.org" source: hosted - version: "3.1.0" + version: "4.0.2" sky_engine: dependency: transitive description: flutter @@ -134,62 +120,62 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0-nullsafety.4" + version: "1.8.0" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.10.0-nullsafety.6" + version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.3" + version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety.3" + version: "1.1.0" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety.3" + version: "1.2.0" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19-nullsafety.6" + version: "0.2.19" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.3.0-nullsafety.5" + version: "1.3.0" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.5" + version: "2.1.0" xml: dependency: "direct main" description: name: xml url: "https://pub.dartlang.org" source: hosted - version: "4.5.1" + version: "5.0.2" sdks: - dart: ">=2.12.0-0.0 <3.0.0" + dart: ">=2.12.0 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 59151e0..f0c8587 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,17 +4,15 @@ version: 0.9.9 homepage: https://github.com/roipeker/graphx environment: - sdk: ">=2.9.1 <3.0.0" + sdk: '>=2.12.0 <3.0.0' dependencies: flutter: sdk: flutter - xml: ^4.5.1 - http: ^0.12.2 + xml: ^5.0.0-nullsafety.1 + http: ^0.13.0-nullsafety.0 # flutter_svg: 0.19.0 dev_dependencies: - pedantic: ^1.9.2 flutter_test: sdk: flutter - effective_dart: ^1.3.0