Compare commits

...

485 Commits

Author SHA1 Message Date
Nick Fisher 071a6c8bd3 chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.16
 - thermion_flutter@0.2.1-dev.16
 - thermion_flutter_web@0.2.0+7
 - thermion_flutter_platform_interface@0.2.1-dev.16
 - thermion_flutter_ffi@0.2.1-dev.16
2024-10-31 22:41:06 +08:00
Nick Fisher bfdda4a7cc feat: Rename Gizmo material to UnlitFixedSize, and expose methods for using this material on other entities. Also exposes new methods for setting single float parameters. 2024-10-31 22:39:39 +08:00
Nick Fisher 91d653b288 doc: fix links in README 2024-10-31 17:07:51 +08:00
Nick Fisher 54d7c4087e doc: README 2024-10-31 17:06:43 +08:00
Nick Fisher b88ed80ecd doc: update README 2024-10-31 16:19:44 +08:00
Nick Fisher bbba889080 chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.15
 - thermion_flutter@0.2.1-dev.15
 - thermion_flutter_web@0.2.0+6
 - thermion_flutter_platform_interface@0.2.1-dev.15
 - thermion_flutter_ffi@0.2.1-dev.15
2024-10-31 15:32:22 +08:00
Nick Fisher 2f1c2fdd9f chore: add logging to ThermionTextureWidget 2024-10-31 15:31:41 +08:00
Nick Fisher cee5631064 fix: multiply coordinates by pixelRatio for scale events 2024-10-31 15:31:18 +08:00
Nick Fisher e22a0aec4d fix: remove superfluous ceil() calls for picking coordinates 2024-10-31 15:30:49 +08:00
Nick Fisher c40faeb888 feat: expose zoomSensitivity argument for flight input handler 2024-10-31 15:27:49 +08:00
Nick Fisher f666b36e43 fix: replace assets symlink for quickstart project 2024-10-30 12:12:09 +08:00
Nick Fisher 965be02891 fix: replace symlinks for camera_manipulation project 2024-10-30 12:12:09 +08:00
Nick Fisher a760e0e594 chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.14
 - thermion_flutter@0.2.1-dev.14
 - thermion_flutter_platform_interface@0.2.1-dev.14
 - thermion_flutter_ffi@0.2.1-dev.14
 - thermion_flutter_web@0.2.0+5
2024-10-30 11:43:21 +08:00
Nick Fisher 82bbb572a5 feat: sanitize file paths in build.dart for Windows compatibility 2024-10-30 11:43:15 +08:00
Nick Fisher 2a9158d0e0 chore: use dependency_overrides for camera_manipulation project 2024-10-30 11:43:14 +08:00
Nick Fisher 3e29749eb4 fix: reduce size of pick functor for compatibility with armeabi-v7a 2024-10-30 11:43:14 +08:00
Nick Fisher 1ac72b7c7b chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.13
 - thermion_flutter_web@0.2.0+4
 - thermion_flutter@0.2.1-dev.13
 - thermion_flutter_ffi@0.2.1-dev.13
 - thermion_flutter_platform_interface@0.2.1-dev.13
2024-10-30 11:43:14 +08:00
Nick Fisher fb1ed9f34b chore: test cleanup 2024-10-30 11:43:14 +08:00
Nick Fisher 07bdc028df feat: pass through fragment coordinates for picking 2024-10-30 11:43:14 +08:00
Nick Fisher 4ed0e69321 chore: remove sandbox from macos quickstart project 2024-10-30 11:43:14 +08:00
Nick Fisher 61f8be2d62 test: add perspective projection test 2024-10-30 11:43:14 +08:00
Nick Fisher 25505c7648 Update dart.yml 2024-10-30 11:43:14 +08:00
Nick Fisher 7282e713ef Update dart.yml 2024-10-30 11:43:14 +08:00
Nick Fisher d76882f194 Update dart.yml 2024-10-30 11:43:14 +08:00
Nick Fisher d24c55033b Update dart.yml 2024-10-30 11:43:14 +08:00
Nick Fisher 64a163a6d6 chore: dummy tests 2024-10-30 11:43:14 +08:00
Nick Fisher f4e2a4bdc6 chore: dummy tests 2024-10-30 11:43:14 +08:00
Nick Fisher 420193a7e2 chore: dummy tests 2024-10-30 11:43:14 +08:00
Nick Fisher 99b79b4f16 chore: dummy test for GitHub actions 2024-10-30 11:43:14 +08:00
Nick Fisher d6b2e8f8d3 chore: rename test 2024-10-30 11:43:14 +08:00
Nick Fisher 014e1bfbcd Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher 343f3cfd61 chore: update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher db3ec6b194 chore: update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher 063a0b7ca7 chore: cleanup tests 2024-10-30 11:43:13 +08:00
Nick Fisher 5fe91f95db Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher 46cfc6e72f Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher f71874cbf7 chore: remove combined integration_test 2024-10-30 11:43:13 +08:00
Nick Fisher c793de7aba Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher ac3550a27c Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher b61e7df4ec Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher 1665a9698f chore: clean up thermion_dart test directory for GitHub actions 2024-10-30 11:43:13 +08:00
Nick Fisher 53bfd894b1 chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.12
 - thermion_flutter@0.2.1-dev.12
 - thermion_flutter_web@0.2.0+3
 - thermion_flutter_platform_interface@0.2.1-dev.12
 - thermion_flutter_ffi@0.2.1-dev.12
2024-10-30 11:43:13 +08:00
Nick Fisher f2cd165ee0 Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher 8947f7c819 Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher 8402619b97 Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher 5c955d15db Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher e01072ff00 Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher e3fe7aaa88 chore: (flutter) (example) use dependency overrides for local thermion packages. We want to build this application for CI before releasing, so we need to be testing the packages that will be built 2024-10-30 11:43:13 +08:00
Nick Fisher ff5ac01a1d chore: (windows) remove unused libs 2024-10-30 11:43:12 +08:00
Nick Fisher 5dac06d335 chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.12
 - thermion_flutter_web@0.2.0+2
 - thermion_flutter_platform_interface@0.2.1-dev.11
 - thermion_flutter_ffi@0.2.1-dev.11
 - thermion_flutter@0.2.1-dev.11
2024-10-25 11:24:32 +08:00
Nick Fisher a8d21fe316 Merge pull request #72 from nmfisher/develop
Gesture handling improvements & build fixes
2024-10-25 14:24:20 +11:00
Nick Fisher d784efa44a Update dart.yml 2024-10-25 11:22:49 +08:00
Nick Fisher b2a4955d54 Update dart.yml 2024-10-25 11:19:50 +08:00
Nick Fisher 02d7a0acfd Update dart.yml 2024-10-25 14:16:29 +11:00
Nick Fisher ee5c08f795 fix: (flutter) (windows) remove deleted source file from Windows CMakeLists 2024-10-25 14:16:22 +11:00
Nick Fisher d7debf981c Merge branch 'master' into develop 2024-10-25 14:15:51 +11:00
Nick Fisher 2b4a73f355 feat: add SCALE2_MOVE InputType 2024-10-25 10:37:57 +08:00
Nick Fisher 06b20ec6fc fix: properly pass through loadResourcesAsync flag for loadGlbFromBuffer 2024-10-25 10:37:34 +08:00
Nick Fisher a3b6d60e16 chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.11
 - thermion_flutter@0.2.1-dev.10
 - thermion_flutter_web@0.2.0+1
 - thermion_flutter_platform_interface@0.2.1-dev.10
 - thermion_flutter_ffi@0.2.1-dev.10
2024-10-24 12:59:43 +08:00
Nick Fisher 37608a8fbe fix: LFS materials 2024-10-24 12:58:13 +08:00
Nick Fisher 2713286ca5 Merge pull request #71 from nmfisher/develop
Allow finer control over input handling
2024-10-24 15:56:11 +11:00
Nick Fisher 6f648702e9 feat: add SCALE2_ROTATE to InputHandler 2024-10-24 12:52:14 +08:00
Nick Fisher 5e17e0c6d1 feat!: expose velocity, rotation and timestamp for scale events in listener. accept rotationSensitivity/zoomSensitivity for FixedOrbitRotateInputHandlerDelegate 2024-10-24 10:07:32 +08:00
Nick Fisher 0fcc44bff8 doc: update docstrings for setLayerVisibilty and setVisibilityLayer 2024-10-23 15:48:34 +08:00
Nick Fisher f65324e555 chore: cleanup LFS 2024-10-23 15:17:25 +08:00
Nick Fisher 1ba4b2a5be chore: merge master 2024-10-23 15:16:06 +08:00
Nick Fisher de4733edf1 chore: remove superseded LFS files 2024-10-23 15:12:46 +08:00
Nick Fisher 75936c75d0 doc: fix doc index 2024-10-23 15:04:26 +08:00
Nick Fisher 6f6ee807cf chore: update published dependency for sample project 2024-10-23 14:59:31 +08:00
Nick Fisher 7a1ce5c281 docs: update doc index 2024-10-23 14:59:09 +08:00
Nick Fisher 74b7c938a8 feat: set SCALE2:InputAction.ZOOM by default 2024-10-23 14:36:47 +08:00
Nick Fisher 3dcacfe631 doc: update camera_manipulation example project and docs 2024-10-23 14:36:26 +08:00
Nick Fisher bf02406bf4 doc: add camera_manipulation example project 2024-10-23 14:11:48 +08:00
Nick Fisher 4371dbda3c feat: track zoom delta for DelegateInputHandler 2024-10-23 14:10:41 +08:00
Nick Fisher c6640cef96 feat: set InputType.SCALE1 to ROTATE by default for DelegateInputHandler.fixedOrbit 2024-10-23 14:03:47 +08:00
Nick Fisher 11ca6972c6 chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.9
 - thermion_flutter@0.2.1-dev.8
 - thermion_flutter_ffi@0.2.1-dev.8
 - thermion_flutter_web@0.1.1
 - thermion_flutter_platform_interface@0.2.1-dev.8
2024-10-23 13:46:45 +08:00
Nick Fisher e235d22c7c chore: add quickstart .metadata 2024-10-23 13:46:00 +08:00
Nick Fisher 512d74568a chore: test cleanup 2024-10-23 16:43:17 +11:00
Nick Fisher 617c2ba578 chore: test cleanup 2024-10-23 16:43:02 +11:00
Nick Fisher 5476c6248c chore: test cleanup 2024-10-23 16:42:33 +11:00
Nick Fisher 916366bd10 doc: add BUILDING.md with Windows instructions 2024-10-23 16:42:09 +11:00
Nick Fisher 5e66893719 chore!: View.getCamera returns Future<Camera> 2024-10-23 16:41:51 +11:00
Nick Fisher 16964b4987 fix:move createUnlitMaterialInstance and createGeometry to render thread 2024-10-23 16:40:55 +11:00
Nick Fisher 73846ffa9b feat: produce debug symbols on Windows 2024-10-23 16:40:30 +11:00
Nick Fisher d5824239f5 fix:move createUnlitMaterialInstance and createGeometry to render thread 2024-10-23 16:39:42 +11:00
Nick Fisher c4270fc918 fix:move createUnlitMaterialInstance and createGeometry to render thread 2024-10-23 16:38:23 +11:00
Nick Fisher a29a1605a7 chore: rename SceneManager* methods 2024-10-23 16:28:42 +11:00
Nick Fisher 22868a594f fix: dont calculate surface orientation for non-triangle geometry 2024-10-23 16:28:00 +11:00
Nick Fisher aed64a27e8 chore: test cleanup 2024-10-23 15:11:33 +11:00
Nick Fisher 2b338a63ba cleanup tests 2024-10-23 15:08:14 +11:00
Nick Fisher cda4027f83 fix!: (windows) add flushAndWait call to capture() to prevent stalling on Windows; use provided buffer as pixelBuffer rather than duplicate allocation 2024-10-23 15:02:28 +11:00
Nick Fisher e2175db7cb fix!: add meshoptimizer lib on Windows 2024-10-23 14:16:03 +11:00
Nick Fisher f1828b0c92 fix!: Dart-only release mode builds on Window 2024-10-23 14:15:41 +11:00
Nick Fisher 5cf9fab4f2 fix: fix all Windows warnings so apps will compile with /WX 2024-10-23 02:41:16 +11:00
Nick Fisher c3764df4e2 feat: (flutter) (windows) add DestroyRenderingSurface method 2024-10-23 02:25:06 +11:00
Nick Fisher a2a1033701 feat: (flutter) (windows) add DestroyRenderingSurface method 2024-10-23 02:24:49 +11:00
Nick Fisher 2536f7fc6f feat: (flutter) (windows) add DestroyRenderingSurface method 2024-10-23 02:24:34 +11:00
Nick Fisher b6fe78b82c feat: (flutter) (windows) add Destroy() to BackingWindow 2024-10-23 02:23:54 +11:00
Nick Fisher f8cddf0bce chore: cleanup thermion_flutter pubspec.yaml 2024-10-23 02:23:15 +11:00
Nick Fisher 2c7a32b47e chore: cleanup quickstart pubspec.yaml 2024-10-23 02:22:45 +11:00
Nick Fisher e6dd4c6cfe chore: cleanup thermion_flutter_ffi pubspec 2024-10-23 02:22:23 +11:00
Nick Fisher fb756fe9ba chore: rearrange thermion_flutter_ffi src dir 2024-10-23 02:22:04 +11:00
Nick Fisher c21e890b48 chore: update quickstart for Windows 2024-10-23 02:21:00 +11:00
Nick Fisher 3720aa98df Merge branch 'develop' of https://github.com/nmfisher/thermion into develop 2024-10-23 01:24:44 +11:00
Nick Fisher 640aa7854a doc: add camera_manipulation 2024-10-22 22:23:51 +08:00
Nick Fisher 9689690730 feat: simplify FixedOrbitCameraRotationDelegate 2024-10-22 22:23:35 +08:00
Nick Fisher a08620d7c9 rename gestureHandler to inputHandler 2024-10-22 22:23:13 +08:00
Nick Fisher fdbdc8e3f3 chore: update quickstart 2024-10-22 22:22:30 +08:00
Nick Fisher 071d3b3023 doc: update README 2024-10-22 22:22:16 +08:00
Nick Fisher f6b12d946a merge 2024-10-23 01:20:22 +11:00
Nick Fisher 11572b4939 fix: on resize, destroy swapchain if destroySwapChainOnResize is true 2024-10-22 14:11:02 +08:00
Nick Fisher 0c75b9a994 chore: update quickstart android project files 2024-10-22 14:10:22 +08:00
Nick Fisher ed44aad076 chore: add flutter quickstart example, assets and update README 2024-10-22 13:11:48 +08:00
Nick Fisher 6dc00bff74 fix: add listener in ThermionFlutterTextureBackedPlatform to unset viewer on dispose 2024-10-22 12:48:26 +08:00
Nick Fisher 5f2407baeb fix: add listener in ThermionFlutterMethodChannelInterface to unset viewer on dispose 2024-10-22 12:48:05 +08:00
Nick Fisher 45f41f3cf7 fix: clean up destruction logic for FlutterPlatformTexture 2024-10-22 12:47:35 +08:00
Nick Fisher 0c29d61a35 fix: use internal Set for determining first ThermionTextureWidget to call requestFrame and cleanup destruction logic 2024-10-22 12:47:13 +08:00
Nick Fisher 58e549e3b3 chore: await future in ThermionFlutterPlugin 2024-10-22 12:46:36 +08:00
Nick Fisher 2ae4f6b338 chore: remove destroy() methods from FFIRenderTarget/FFISwapChain, implement destroyRenderTarget/destroySwapChain and clean up ThermionViewerFFI disposal 2024-10-22 12:46:18 +08:00
Nick Fisher e28e41c1d9 chore: update stubbed methods 2024-10-22 12:45:30 +08:00
Nick Fisher 05dfe51260 chore: add destroySwapChain/destroyRenderTarget methods to Dart vieer and allow setting null renderTarget 2024-10-22 12:45:16 +08:00
Nick Fisher ec6e94f4ca chore: remove destroy() methods from RenderTarget and SwapChain (these need to be managed by Viewer to handle instances where the viewer itself has been disposed 2024-10-22 12:44:46 +08:00
Nick Fisher bdb332bd79 fix: set View render target to nullptr if Dart renderTarget is null 2024-10-22 12:44:00 +08:00
Nick Fisher 9295dfc7c1 docs: add quickstart to README 2024-10-22 12:43:31 +08:00
Nick Fisher fb4bee4801 docs: remove Windows native_toolchain_c fixes from docs 2024-10-22 12:43:15 +08:00
Nick Fisher 8b7c2aa48d fix: set render target to null for each view and then destroy render targets when viewer disposed 2024-10-22 12:42:50 +08:00
Nick Fisher 9bec96f160 chore: rename Viewer_destroyOnRenderThread method and cleanup unused SwapChain parameter in render threa 2024-10-22 12:42:19 +08:00
Nick Fisher cb517c907d chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.8
 - thermion_flutter_web@0.1.0+9
 - thermion_flutter@0.2.1-dev.7
 - thermion_flutter_platform_interface@0.2.1-dev.7
 - thermion_flutter_ffi@0.2.1-dev.7
2024-10-14 09:36:55 +08:00
Nick Fisher a6f5e59cbb fix: move ThermionWin32.h to include 2024-10-14 09:36:28 +08:00
Nick Fisher 9420143a36 chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.7
 - thermion_flutter_web@0.1.0+8
 - thermion_flutter@0.2.1-dev.6
 - thermion_flutter_platform_interface@0.2.1-dev.6
 - thermion_flutter_ffi@0.2.1-dev.6
2024-10-14 09:25:59 +08:00
Nick Fisher eb8835b63a Merge pull request #69 from nmfisher/feature/multiple_swapchains
Support multiple views/widgets/swapchains
2024-10-14 12:05:21 +11:00
Nick Fisher f9468db266 Windows embedder fixes 2024-10-14 11:23:56 +11:00
Nick Fisher 1135ba054c cleanup 2024-10-12 15:07:14 +11:00
Nick Fisher 8f7509a23f cleanup 2024-10-12 15:06:57 +11:00
Nick Fisher cba9ee98ad (flutter) set view renderable on Windows 2024-10-12 14:56:04 +11:00
Nick Fisher 0ec0fef8f3 move standalone Windows file to extras 2024-10-12 14:55:41 +11:00
Nick Fisher a348562f56 cleanup 2024-10-12 14:36:51 +11:00
Nick Fisher 392a606bbc don't call endFrame() if no views were rendered 2024-10-12 14:36:05 +11:00
Nick Fisher 440bed4485 add files to run standalone Windows 2024-10-12 14:34:42 +11:00
Nick Fisher a321966e5b fix Windows build.dart to avoid native_assets fork; add implementations for ThermionFlutterWindows 2024-10-12 02:14:37 +11:00
Nick Fisher f180c1018f mobile gesture handler 2024-10-11 15:37:03 +08:00
Nick Fisher f267aa6dc6 chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.6
 - thermion_flutter_web@0.1.0+7
 - thermion_flutter_platform_interface@0.2.1-dev.5
 - thermion_flutter@0.2.1-dev.5
 - thermion_flutter_ffi@0.2.1-dev.5
2024-10-10 20:58:19 +08:00
Nick Fisher 1c74e83c2c add native_assets_cli to dependencies 2024-10-10 20:57:50 +08:00
Nick Fisher 099a895eb6 chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.5
 - thermion_flutter_platform_interface@0.2.1-dev.4
 - thermion_flutter_web@0.1.0+6
 - thermion_flutter@0.2.1-dev.4
 - thermion_flutter_ffi@0.2.1-dev.4
2024-10-10 20:49:40 +08:00
Nick Fisher 3b810f84da add animation tests 2024-10-10 20:49:08 +08:00
Nick Fisher 10f2c7d36b update cube test asset with morph targets 2024-10-10 20:49:01 +08:00
Nick Fisher 5b849638de update cube test asset with morph targets 2024-10-10 20:48:54 +08:00
Nick Fisher 857fd6f782 update tests 2024-10-10 20:48:41 +08:00
Nick Fisher 29edec63ab bump animation_tools_dart dependency 2024-10-10 20:47:45 +08:00
Nick Fisher c6afc4756a bump animation_tools_dart dependency 2024-10-10 20:47:33 +08:00
Nick Fisher 365657cf88 add pick to view tests 2024-10-10 20:47:17 +08:00
Nick Fisher 5441dedcf4 add fall-through for InputAction.ZOOM for Third Person camera delegate 2024-10-10 20:47:00 +08:00
Nick Fisher 254b6d8af2 move zoom delta to InputAction.ZOOM for FreeFlight rotation delegate 2024-10-10 20:46:34 +08:00
Nick Fisher 1459aea5cf move zoom delta to InputAction.ZOOM for FixedOrbit rotation delegate 2024-10-10 20:46:16 +08:00
Nick Fisher 80d8525671 pass through sensitivity options in DelegateGestureHandler and implement cameraUpdated 2024-10-10 20:45:33 +08:00
Nick Fisher 389a165ed3 rearrange package folders 2024-10-10 20:44:55 +08:00
Nick Fisher d8f309d21b add stubbed methods 2024-10-10 20:44:39 +08:00
Nick Fisher ee983ddfaa add InputAction.ZOOM 2024-10-10 20:43:58 +08:00
Nick Fisher c1cdd37e9d add DefaultPickDelegate 2024-10-10 20:43:31 +08:00
Nick Fisher 646f05933d use condition_variable for render thread requestFrame as well as tasks 2024-10-10 20:43:04 +08:00
Nick Fisher 3f854a7f27 rearrange utils dir 2024-10-10 14:59:11 +08:00
Nick Fisher 740dbea8bd add Axis class and rearrange utils dir 2024-10-10 14:58:50 +08:00
Nick Fisher 95a44936ac add option for async loading glTF resources 2024-10-10 14:58:09 +08:00
Nick Fisher 9deafc7371 return View when picking, use uint32_t for morphIndices 2024-10-10 08:42:16 +08:00
Nick Fisher c1af7e374d set bloom enabled by default, but 0 strength 2024-10-10 08:39:48 +08:00
Nick Fisher cd71db72be chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.4
 - thermion_flutter_web@0.1.0+5
 - thermion_flutter@0.2.1-dev.3
 - thermion_flutter_platform_interface@0.2.1-dev.3
 - thermion_flutter_ffi@0.2.1-dev.3
2024-10-02 17:59:56 +08:00
Nick Fisher a9d90f966b chore: make pub.dev happy 2024-10-02 17:59:34 +08:00
Nick Fisher 1a323ca551 chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.3
 - thermion_flutter_web@0.1.0+4
 - thermion_flutter@0.2.1-dev.2
 - thermion_flutter_platform_interface@0.2.1-dev.2
 - thermion_flutter_ffi@0.2.1-dev.2
2024-10-02 17:58:24 +08:00
Nick Fisher 2d85e191bc chore: make pub.dev happy 2024-10-02 17:58:08 +08:00
Nick Fisher 1b971a859c chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.2
 - thermion_flutter_web@0.1.0+3
 - thermion_flutter_ffi@0.2.1-dev.1
 - thermion_flutter@0.2.1-dev.1
 - thermion_flutter_platform_interface@0.2.1-dev.1
2024-10-02 17:56:55 +08:00
Nick Fisher 78b697d1c2 chore: make pub.dev happy 2024-10-02 17:56:37 +08:00
Nick Fisher 9da2ce6672 chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.1
 - thermion_flutter_web@0.1.0+2
 - thermion_flutter@0.2.1-dev.0
 - thermion_flutter_platform_interface@0.2.1-dev.0
 - thermion_flutter_ffi@0.2.1-dev.0
2024-10-02 17:55:23 +08:00
Nick Fisher 39fabd501d chore: move swift bindings to test folder to make pub.dev happy 2024-10-02 17:53:31 +08:00
Nick Fisher 3f1867dd6f chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.0
 - thermion_flutter@0.2.1-dev.0.0.0
 - thermion_flutter_ffi@0.2.1-dev.0.0.0
 - thermion_flutter_platform_interface@0.2.1-dev.0.0.0
 - thermion_flutter_web@0.1.0+1
2024-10-02 17:46:54 +08:00
Nick Fisher 68d29041b0 chore(release): publish packages
- thermion_dart@0.2.0
 - thermion_flutter@0.2.0
 - thermion_flutter_ffi@0.2.0
 - thermion_flutter_platform_interface@0.2.0
 - thermion_flutter_web@0.1.0
2024-10-02 17:41:13 +08:00
Nick Fisher b300e86962 chore(release): publish packages
- thermion_dart@0.2.0-dev.8.0.0
 - thermion_flutter@0.2.0-dev.8.0.0
 - thermion_flutter_ffi@0.2.0-dev.8.0.0
 - thermion_flutter_platform_interface@0.2.0-dev.8.0.0
 - thermion_flutter_web@0.1.0-dev.8.0.0
2024-10-02 16:50:41 +08:00
Nick Fisher 562ecf2ee5 feat: camera and resizing improvements 2024-10-02 16:47:55 +08:00
Nick Fisher d294938a2c chore: remove EMSCRIPTEN ifdefs in *RenderThread methods (no longer used) 2024-09-30 18:24:05 +08:00
Nick Fisher 027cf23069 chore: cleanup 2024-09-30 18:20:30 +08:00
Nick Fisher c4598637bb feat: support multiple ThermionWidget on Android 2024-09-30 18:20:05 +08:00
Nick Fisher 8a94b6a334 feat: use imported texture on iOS 2024-09-30 14:51:11 +08:00
Nick Fisher c80c163212 feat: working implementation of multiple widgets on macos 2024-09-30 13:45:57 +08:00
Nick Fisher 921a994eb6 refactor: continual refactor to support multiple render targets 2024-09-28 18:28:05 +08:00
Nick Fisher 65e60da288 chore: upgrade Swift interop gen 2024-09-28 17:59:05 +08:00
Nick Fisher 661185083e chore: refactoring and cleanup for Gizmo 2024-09-28 13:24:28 +08:00
Nick Fisher a2a26555e2 feat: more work on multiple views/swapchains 2024-09-28 11:19:06 +08:00
Nick Fisher 7f11250b79 refactor!: refactor to support multiple Views/Render Targets 2024-09-27 23:16:01 +08:00
Nick Fisher a6d2f2ecf9 feat!: big refactor to support multiple swapchains 2024-09-27 18:39:20 +08:00
Nick Fisher 399d447eec chore: don't keep superfluous handle to rtDepth and rtColor 2024-09-27 16:40:30 +08:00
Nick Fisher fb6204e47c chore: cleanup 2024-09-27 15:19:53 +08:00
Nick Fisher 566856c8fb chore: update bindings 2024-09-27 15:13:45 +08:00
Nick Fisher d29dd207b6 feat: add rendering check to ThermionWidget ticker 2024-09-27 15:13:33 +08:00
Nick Fisher e20489900d fix!: replace queuePosition/Rotation with queueTransforms 2024-09-27 15:12:43 +08:00
Nick Fisher 567a268ded fix!: replace queuePosition/Rotation with queueTransforms 2024-09-27 15:12:33 +08:00
Nick Fisher 6a57d242f9 feat: add setParameterFloat2 method 2024-09-27 15:12:14 +08:00
Nick Fisher 41e0851d70 feat: add setParameterFloat2 method 2024-09-27 15:12:05 +08:00
Nick Fisher 95b378348c refactor!: remove RenderThread methods no longer needed 2024-09-27 15:11:47 +08:00
Nick Fisher 1309bf7c6e fix!: replace queuePosition/Rotation with queueTransforms 2024-09-27 15:10:13 +08:00
Nick Fisher 2531b507b0 fix!: replace queuePosition/Rotation with queueTransforms 2024-09-27 15:09:49 +08:00
Nick Fisher 16dc0419e2 feat: add uvScale to unlit material 2024-09-27 15:08:30 +08:00
Nick Fisher 4e7ec6bfb4 feat: add ThirdPersonCameraDelegate 2024-09-27 15:06:51 +08:00
Nick Fisher 035ad48fe4 feat!: set baseColorIndex to -1 by default in unlit materialss 2024-09-27 15:06:32 +08:00
Nick Fisher ff7c582157 chore: update tests 2024-09-27 15:06:02 +08:00
Nick Fisher 0876a91e17 add ThirdPersonCameraDelegate 2024-09-27 15:05:41 +08:00
Nick Fisher a2d3c1d73e chore: getter for native camera view matrix 2024-09-26 18:49:32 +08:00
Nick Fisher 1a721deee6 more camera work 2024-09-26 18:41:34 +08:00
Nick Fisher 4355d9c83f more camera work 2024-09-26 16:51:14 +08:00
Nick Fisher 239891c400 chore: rearrange library/export structure 2024-09-26 16:35:33 +08:00
Nick Fisher ac10aa0a1e chore: camera transform tests 2024-09-26 15:56:54 +08:00
Nick Fisher 7ecf414a47 feat: set camera model matrix directly 2024-09-26 15:52:50 +08:00
Nick Fisher 87c96d06a4 chore: rearrange library dirs, gesture handler improvements 2024-09-26 15:52:23 +08:00
Nick Fisher 26a8d9c6b5 chore: import cleanup 2024-09-26 10:48:40 +08:00
Nick Fisher 947a77f619 chore: rearrange flutter gesture/widget directory structure 2024-09-26 10:46:52 +08:00
Nick Fisher c850513b7f chore: rearrange flutter gesture/widget directory structure 2024-09-26 10:46:10 +08:00
Nick Fisher c47d827139 chore: rename thermion_flutter src dir 2024-09-26 10:44:47 +08:00
Nick Fisher a2684ae47d renaming/refactoring and allow creating new cameras 2024-09-25 23:56:25 +08:00
Nick Fisher 2b1339b560 feat: expose more camera methods 2024-09-25 23:09:27 +08:00
Nick Fisher 59aec2bcc9 chore(release): publish packages
- thermion_dart@0.2.0-dev.7.0
 - thermion_flutter_web@0.1.0-dev.7.0
 - thermion_flutter@0.2.0-dev.7.0
 - thermion_flutter_platform_interface@0.2.0-dev.7.0
 - thermion_flutter_ffi@0.2.0-dev.7.0
2024-09-25 22:35:46 +08:00
Nick Fisher 61d1581b96 fix!: fix min SDK for thermion_dart 2024-09-25 22:35:30 +08:00
Nick Fisher 8e47332ce8 chore(release): publish packages
- thermion_dart@0.2.0-dev.6.0
 - thermion_flutter_web@0.1.0-dev.6.0
 - thermion_flutter@0.2.0-dev.6.0
 - thermion_flutter_platform_interface@0.2.0-dev.6.0
 - thermion_flutter_ffi@0.2.0-dev.6.0
2024-09-25 21:58:28 +08:00
Nick Fisher ffe8bee98b chore!: cleanup deleted export 2024-09-25 21:58:19 +08:00
Nick Fisher 1e07486017 chore(release): publish packages
- thermion_flutter@0.2.0-dev.6.0
2024-09-25 21:57:38 +08:00
Nick Fisher 58da196876 chore!: remove superseded HardwareKeyboard* classes 2024-09-25 21:56:16 +08:00
Nick Fisher 78af155a6d chore(release): publish packages
- thermion_dart@0.2.0-dev.5.0
 - thermion_flutter_web@0.1.0-dev.5.0
 - thermion_flutter@0.2.0-dev.5.0
 - thermion_flutter_platform_interface@0.2.0-dev.5.0
 - thermion_flutter_ffi@0.2.0-dev.5.0
2024-09-25 21:52:58 +08:00
Nick Fisher d7e1b3d7ba chore!: remove EntityTransformController (requires replacement) 2024-09-25 21:52:42 +08:00
Nick Fisher 877eae35cd chore(release): publish packages
- thermion_dart@0.2.0-dev.4.0
 - thermion_flutter_web@0.1.0-dev.4.0
 - thermion_flutter@0.2.0-dev.4.0
 - thermion_flutter_platform_interface@0.2.0-dev.4.0
 - thermion_flutter_ffi@0.2.0-dev.4.0
2024-09-25 21:51:19 +08:00
Nick Fisher 87846b68de fix!: (web/wasm) free pick callbacks on dispose 2024-09-25 21:50:31 +08:00
Nick Fisher 6581ee8a2a chore!: restructure viewer folders as libraries to only export the public interface 2024-09-25 21:49:15 +08:00
Nick Fisher 951064e657 chore(release): publish packages
- thermion_flutter@0.2.0-dev.3.0
2024-09-25 21:20:54 +08:00
Nick Fisher 68ebf945a5 chore: add path to dev deps 2024-09-25 21:20:34 +08:00
Nick Fisher 153817e859 chore!: (flutter) cleanup for pub.dev publishing 2024-09-25 21:20:04 +08:00
Nick Fisher ba0bc54fa7 fix!: remove EntityControllerMouseWidget (replace with GestureHandler) 2024-09-25 21:19:41 +08:00
Nick Fisher 9b99975017 chore(release): publish packages
- thermion_flutter@0.2.0-dev.2.0
2024-09-25 21:18:00 +08:00
Nick Fisher e6a6862ba4 chore: (flutter) web packaging fixes (use logger) 2024-09-25 21:17:38 +08:00
Nick Fisher b7d3e9191a chore: (flutter) web packaging fixes 2024-09-25 21:17:20 +08:00
Nick Fisher b461b2c5db chore: (flutter) web packaging fixes 2024-09-25 21:17:09 +08:00
Nick Fisher 8f7f48bcaa chore: (flutter) add package:web to flutter deps 2024-09-25 21:16:48 +08:00
Nick Fisher 7dc8e394f7 chore!: remove EntityListWidget - will replace with new Scene 2024-09-25 21:16:24 +08:00
Nick Fisher f5c8faa5c3 chore(release): publish packages
- thermion_dart@0.2.0-dev.1.0
 - thermion_flutter@0.2.0-dev.1.0
 - thermion_flutter_ffi@0.2.0-dev.1.0
 - thermion_flutter_platform_interface@0.2.0-dev.1.0
 - thermion_flutter_web@0.1.0-dev.1.0
2024-09-25 21:06:28 +08:00
Nick Fisher c84b4010d1 Merge pull request #68 from nmfisher/improvements
Improvements
2024-09-25 21:02:53 +08:00
Nick Fisher b720c1294f rename Android plugin class in pubspec.yaml 2024-09-25 19:27:38 +08:00
Nick Fisher d442ab5ce6 add namespace for build.gradle 2024-09-25 19:27:19 +08:00
Nick Fisher 61fdf300f4 add namespace for AndroidManifest.xml 2024-09-25 19:27:04 +08:00
Nick Fisher 4dabca9160 rename Android package/paths 2024-09-25 19:26:51 +08:00
Nick Fisher 85d6946645 (flutter) provide nicer implementation of FixedOrbitCameraRotationDelegate 2024-09-25 19:26:19 +08:00
Nick Fisher 4b1d8ce729 (flutter) update FreeFlight camera delegate 2024-09-24 14:24:29 +08:00
Nick Fisher c52b0084ce add PickDelegate to DelegateGestureHandler 2024-09-24 14:21:13 +08:00
Nick Fisher 8db725d8bd add PICK_ENTITY to GestureAction 2024-09-24 14:20:49 +08:00
Nick Fisher c67d1cbbc4 add background color tests 2024-09-24 14:20:33 +08:00
Nick Fisher 3ea4062e33 normalize direction in addLight 2024-09-24 14:20:14 +08:00
Nick Fisher 65e99b9212 set clearOptions to true 2024-09-23 13:51:18 +08:00
Nick Fisher e83193ba0d introduce stronger native typing, camera projection/culling methods, update tests 2024-09-21 11:36:41 +08:00
Nick Fisher 835338ef63 (flutter) use scheduleFrameCallback to invoke requestFrame to match Flutter/vsync 2024-09-21 10:22:49 +08:00
Nick Fisher 57872d2e40 rename from *FFI to *RenderThread, return bool from render() to check frame timings, update render loop to wait on condition variable, add requestFrame() method 2024-09-21 10:21:46 +08:00
Nick Fisher b5a7996769 add Dart Camera type 2024-09-21 10:18:36 +08:00
Nick Fisher ddbb4ec5c6 rename CameraPtr to TCamera and use named arguments for setCameraLensProjection 2024-09-20 18:31:20 +08:00
Nick Fisher 7cb3080596 move MaterialInstance methods to own class 2024-09-20 18:18:08 +08:00
Nick Fisher f6c91294aa rename setLayerEnabled to setLayerVisibility, add setVisibilityLayer method 2024-09-20 17:34:17 +08:00
Nick Fisher 412d333525 add PickDelegate 2024-09-20 14:54:18 +08:00
Nick Fisher 378dede02d add ThermionPickResult typedef 2024-09-20 14:53:48 +08:00
Nick Fisher 0e3db2635f update bindings 2024-09-20 14:53:34 +08:00
Nick Fisher 77147cbafd add setMaterialDepthWrite method 2024-09-20 14:53:16 +08:00
Nick Fisher 43e5fd7766 add setMaterialDepthWrite method 2024-09-20 14:53:06 +08:00
Nick Fisher fc3ca3d6b3 update tests 2024-09-20 14:08:47 +08:00
Nick Fisher 51f52bb71b update stub 2024-09-20 14:08:26 +08:00
Nick Fisher 033c3f632d add createUnlitMaterialInstance, setMaterialPropertyInt methods to viewer interface 2024-09-20 14:08:16 +08:00
Nick Fisher 6d862ef36a update bindings 2024-09-20 14:07:37 +08:00
Nick Fisher f816274fb9 replace some async methods with futures, fix setMaterialProperty4, update unproject, setMaterialPropertyInt, createUnlitMaterialInstance 2024-09-20 14:07:09 +08:00
Nick Fisher 0816286696 export geometry from thermion_dart 2024-09-20 14:05:14 +08:00
Nick Fisher b421df5e2f remove image.mat from LFS 2024-09-20 14:04:59 +08:00
Nick Fisher f6a136643d remove image.mat from LFS 2024-09-20 14:04:43 +08:00
Nick Fisher b5e278183a update built unlit material 2024-09-20 14:04:27 +08:00
Nick Fisher 8e85042e37 remove old default paramsf rom UnlitMaterialProvider 2024-09-20 14:04:11 +08:00
Nick Fisher f943756624 add setMaterialProperty for int, add create_unlit_material_instance, use double4 instead of float4 2024-09-20 14:03:50 +08:00
Nick Fisher 92814aed56 add setMaterialProperty for int, add create_unlit_material_instance 2024-09-20 14:03:29 +08:00
Nick Fisher e8a1b976e1 set default layer for loadGlb to 0,. add setMaterialProperty for int, add SceneManager::createUnlitMaterialInstance 2024-09-20 14:02:30 +08:00
Nick Fisher ef48dbce30 add base color/texture to unlit 2024-09-20 14:01:59 +08:00
Nick Fisher 196cc6b980 set default layer for loadGlb to 0,. add setMaterialProperty for int 2024-09-20 14:01:41 +08:00
Nick Fisher 1788c74d4c change float4 to double4 2024-09-20 14:01:02 +08:00
Nick Fisher 74e808d1dc update tests 2024-09-19 21:10:42 +08:00
Nick Fisher 72dacc5b21 update unproject texture to accept input texture 2024-09-19 21:10:28 +08:00
Nick Fisher ebdaf65b89 update unproject texture to accept input texture 2024-09-19 21:10:22 +08:00
Nick Fisher fa43149c98 update unproject texture to accept input texture 2024-09-19 21:10:10 +08:00
Nick Fisher e8ae7193ee update unproject texture to accept input texture 2024-09-19 21:09:23 +08:00
Nick Fisher aa21c0fb76 don't call clearBackgroundImage when setBackgroundImage is called (would deadlock) 2024-09-19 21:08:55 +08:00
Nick Fisher 10826466a4 set default material for geometry to baseColorIndex 0 2024-09-19 17:08:06 +08:00
Nick Fisher 3b2d7d8c47 depth pre-pass when projecting texture 2024-09-19 16:59:01 +08:00
Nick Fisher 212443cb8e add spot constructor 2024-09-19 13:44:17 +08:00
Nick Fisher 523141d54b add test cube texture image 2024-09-19 13:02:51 +08:00
Nick Fisher d8a0859f16 update test 2024-09-19 13:00:40 +08:00
Nick Fisher c70cc9abb5 add image methods to test helper 2024-09-19 12:53:44 +08:00
Nick Fisher 66b626e605 update showcase 2024-09-19 12:53:30 +08:00
Nick Fisher 4b28119318 test updates 2024-09-19 12:52:27 +08:00
Nick Fisher 666506aed0 widget updates 2024-09-19 12:52:16 +08:00
Nick Fisher a55f63a428 increase min Dart SDK to 3.5 for .address FFI accessors 2024-09-19 12:51:30 +08:00
Nick Fisher fb441e151c update ffigen with new headers 2024-09-19 12:51:09 +08:00
Nick Fisher 82d85386c0 fixes for createMaterialInstance 2024-09-19 12:50:57 +08:00
Nick Fisher 242b2f6faa gesture detector fixes 2024-09-19 09:19:23 +08:00
Nick Fisher 31d31dd583 ThermionViewer: add create/destroy materialinstance, add MaterialInstance property to createGeometry, priority/layer to loadGlbFromBuffer 2024-09-19 09:17:45 +08:00
Nick Fisher f6077012b1 widget cleanup 2024-09-19 09:16:45 +08:00
Nick Fisher 18bb45dcd8 use TMaterialInstance for FFI API, add priority/layer params to load_glb_from_buffer 2024-09-19 09:16:06 +08:00
Nick Fisher 10b919e4f4 add priority/layer to FFI viewer, use struct for model matrix, add createUbershaderMaterialInstance and destroyMaterialInstance 2024-09-19 09:15:31 +08:00
Nick Fisher 98cedf821c update bindings 2024-09-19 09:14:10 +08:00
Nick Fisher 729f72e768 use SceneManager::LAYERS enum for Overlay, set priority/layer in loadGlbFromBuffer, add create/destroy material instance 2024-09-19 09:12:57 +08:00
Nick Fisher d01861e949 use SceneManager::LAYERS enum for Overlay 2024-09-19 09:12:16 +08:00
Nick Fisher adec48f253 use SceneManager::LAYERS enum for gizmo 2024-09-19 09:12:02 +08:00
Nick Fisher 27a8ce18d5 add priority/layer to load_glb_from_buffer 2024-09-19 09:11:40 +08:00
Nick Fisher 4b740a9f5a native types, add create/destroy material instance, add SceneManager::LAYERS enum 2024-09-19 09:11:20 +08:00
Nick Fisher 0b34b4546e refactor: native types 2024-09-19 09:10:24 +08:00
Nick Fisher c17919cd97 refactor: native types 2024-09-19 09:09:42 +08:00
Nick Fisher 462f1f02bf refactor: move native types to own header, add methods for create/destroy material instance, add priority/layer to load_glb_from_buffer 2024-09-19 09:09:16 +08:00
Nick Fisher ddc433a126 refactor: Dart types 2024-09-19 09:07:35 +08:00
Nick Fisher ab649e860d update gitattr 2024-09-16 20:51:27 +08:00
Nick Fisher 676ddc3773 add texture methods (including unproject) 2024-09-16 20:51:14 +08:00
Nick Fisher 7d2cf3f91b don't store gizmo material in LFS 2024-09-16 11:25:21 +08:00
Nick Fisher 492d41d756 test update 2024-09-16 11:24:24 +08:00
Nick Fisher 191c2fd709 restructure viewer/types/helper folders, remove old WASM/web FFI interop, add SceneUpdated stream 2024-09-16 11:08:27 +08:00
Nick Fisher 027fc9ae04 update tests 2024-09-16 11:08:19 +08:00
Nick Fisher b73d0e1e96 restructure viewer/types/helper folders, remove old WASM/web FFI interop, add SceneUpdated stream 2024-09-16 11:07:54 +08:00
Nick Fisher 315f2b63b9 gesture handler & delegate improvements 2024-09-13 18:32:02 +08:00
Nick Fisher ad205679cb allow setting material property by name 2024-09-13 15:27:46 +08:00
Nick Fisher 6ef8d19e94 (flutter) export delegate gesture handler 2024-09-13 15:27:20 +08:00
Nick Fisher 6b0f25ca59 remove using namespace filament* 2024-09-13 15:27:01 +08:00
Nick Fisher 820d341f67 update bindings 2024-09-13 15:26:44 +08:00
Nick Fisher 70f904d54c allow setting material property by name 2024-09-13 15:20:45 +08:00
Nick Fisher aee607908d remove using namespace filament* 2024-09-13 15:18:01 +08:00
Nick Fisher c99c57e24d geometry receives/casts shadows by default 2024-09-13 14:52:20 +08:00
Nick Fisher 00d75be479 gesture handler improvements 2024-09-13 14:25:10 +08:00
Nick Fisher 3a9bd31919 remove superseded desktop/mobile gesture detector widget 2024-09-13 13:47:26 +08:00
Nick Fisher 51be1bce39 add pan camera implementation and fix velocity timer 2024-09-13 13:46:41 +08:00
Nick Fisher 822b8e14c1 add delegate-based implementations for gesture handlers 2024-09-13 13:30:00 +08:00
Nick Fisher 2ab30a7933 remove double sided from HighlightOverlay material 2024-09-13 11:09:09 +08:00
Nick Fisher 1be8a5e862 adjust gizmo size 2024-09-13 11:08:49 +08:00
Nick Fisher 98d61fa1b3 fix setCameraModelMatrix4 2024-09-13 10:36:24 +08:00
Nick Fisher 5b3d16a316 update bindings 2024-09-13 10:36:07 +08:00
Nick Fisher b6863828b4 initialize viewportDimensions to (0,0) in ThermionViewer 2024-09-13 10:35:57 +08:00
Nick Fisher 98fefd0e52 fix winding order in GeometryHelper 2024-09-13 10:35:33 +08:00
Nick Fisher d476d78e2b reduce size of gizmo 2024-09-13 10:35:13 +08:00
Nick Fisher 98113fb79f remove logging 2024-09-13 10:34:59 +08:00
Nick Fisher 90827ff012 culling fixes for HighlightOverlay 2024-09-13 10:34:47 +08:00
Nick Fisher 44078ba2e0 add v2 gesture handlers 2024-09-13 10:34:23 +08:00
Nick Fisher 866219ee2e add v2 gesture handlers 2024-09-13 10:34:12 +08:00
Nick Fisher d785bd6b7e chore!: rename controller to viewer in gesture detector widgets 2024-09-12 08:54:07 +08:00
Nick Fisher 3e4e6653a8 update material building in Makefile 2024-09-11 23:09:56 +08:00
Nick Fisher 8d250e2664 update test 2024-09-11 23:09:41 +08:00
Nick Fisher d455cea29e use opaque CameraPtr to set camera matrices/properties/etc 2024-09-11 23:09:27 +08:00
Nick Fisher 374e8eb910 rename getBoundingBox to getViewportBoundingBox and add camera methods 2024-09-11 23:08:07 +08:00
Nick Fisher 833fc74b4c rename getBoundingBox to getViewportBoundingBox 2024-09-11 23:07:47 +08:00
Nick Fisher 62417bfebd explicitly mark type of Camera for Gizmo 2024-09-11 23:07:29 +08:00
Nick Fisher abc9ecbeee use opaque CameraPtr to set camera matrices/properties/etc 2024-09-11 23:07:03 +08:00
Nick Fisher a1f71ab459 remove camera methods from FilamentViewer 2024-09-11 23:06:32 +08:00
Nick Fisher d123929fb4 remove camera methods from FilamentViewer 2024-09-11 23:06:06 +08:00
Nick Fisher 141827c59c use opaque CameraPtr to set camera matrices/properties/etc 2024-09-11 23:05:40 +08:00
Nick Fisher 9fbcc9edaf mark all ffigen functions as leaf 2024-09-11 23:04:57 +08:00
Nick Fisher 83d9c5be30 remove update_viewport_and_camera_projection_ffi 2024-09-11 23:04:36 +08:00
Nick Fisher 6aadbbc3d0 remove update_viewport_and_camera_projection_ffi 2024-09-11 23:04:27 +08:00
Nick Fisher d5bc865cf4 add matrix helper 2024-09-11 23:04:02 +08:00
Nick Fisher d766733489 update stubbed ThermionViewer methods 2024-09-11 23:03:53 +08:00
Nick Fisher f51c640d17 remove unused get_camera_position method 2024-09-11 20:01:21 +08:00
Nick Fisher 66f10b598a update stub ThermionViewer 2024-09-11 19:59:43 +08:00
Nick Fisher 59957650aa update bindings 2024-09-11 19:59:33 +08:00
Nick Fisher d43fbd8964 add loadGlbFromBuffer implementation to ThermionViewerFFI 2024-09-11 19:59:25 +08:00
Nick Fisher f5de4349bf add createGeometryWithNormals to SceneManager 2024-09-11 18:09:42 +08:00
Nick Fisher f67e1a021d add createGeometryWithNormals to SceneManager 2024-09-11 18:09:14 +08:00
Nick Fisher 33f2c5fbf7 add normals to CustomGeometry implementation 2024-09-11 18:08:48 +08:00
Nick Fisher 6a7bde930d add normals to CustomGeometry interface 2024-09-11 18:08:35 +08:00
Nick Fisher b827a2142b HighlightOverlay fixes 2024-09-11 18:08:13 +08:00
Nick Fisher 8bd2416bad don't set stencil highlight in Gizmo 2024-09-11 18:07:38 +08:00
Nick Fisher 3684eb248c add create_geometry_with_normals method 2024-09-11 18:07:17 +08:00
Nick Fisher 9077632d1b add create_geometry_with_normals method 2024-09-11 18:07:07 +08:00
Nick Fisher d40261ae29 add create_geometry_with_normals_ffi method, switch load_glb_from_buffer type to uint8_t for Dart leaf compat and add keepData param 2024-09-11 18:06:50 +08:00
Nick Fisher 77dbb574c7 add create_geometry_with_normals_ffi method, switch load_glb_from_buffer type to uint8_t for Dart leaf compat and add keepData param 2024-09-11 18:06:31 +08:00
Nick Fisher 89a660144e update test helpers 2024-09-11 18:05:36 +08:00
Nick Fisher 7554af5d41 (flutter) add experimental GestureHandler widget and decouple from ThermionGestureDetectorDesktop 2024-09-11 18:05:24 +08:00
Nick Fisher 4b742fea2d (flutter) add experimental GestureHandler widget and decouple from ThermionGestureDetectorDesktop 2024-09-11 18:05:18 +08:00
Nick Fisher a6c6cff8b6 add loadGlbFromBuffer method and normals param to ThermionViewer 2024-09-11 18:04:36 +08:00
Nick Fisher 5813753ef9 (flutter) set enablePicking to false by default in ThermionGestureDetector 2024-09-11 18:03:52 +08:00
Nick Fisher cf0dad2631 (flutter) add const FlutterWebOptions 2024-09-11 18:03:29 +08:00
Nick Fisher cfddb99a8b (flutter) add CameraOrientationWidget 2024-09-11 18:01:45 +08:00
Nick Fisher 845d5bf223 (flutter) add const constructor for flutter options 2024-09-11 18:01:33 +08:00
Nick Fisher dbbd972909 add GeometryHelper 2024-09-11 17:54:21 +08:00
Nick Fisher aba3ba24af (flutter) add CameraOrientationWidget 2024-09-11 17:54:08 +08:00
Nick Fisher 81c27dde9f feat: parent the cloned entity instance when setting stencil highlight 2024-09-08 13:55:25 +08:00
Nick Fisher 476b552fd0 feat: add getAncestor method 2024-09-08 13:52:33 +08:00
Nick Fisher 5c4d5d4b9d feat: add getAncestor method 2024-09-08 13:52:04 +08:00
Nick Fisher ae5ef2c286 update bindings 2024-09-07 18:01:39 +08:00
Nick Fisher b0f3c8a087 feat: set stencil highlight on gizmo attach 2024-09-07 18:01:30 +08:00
Nick Fisher 43fc7ffc65 update tests 2024-09-07 18:01:03 +08:00
Nick Fisher ee24fca20e feat: move createGeometry to SceneManager, add queueRelativePositionUpdateFromViewportVector and removeStencilHighlight 2024-09-07 18:00:50 +08:00
Nick Fisher a00fdbe042 chore: remove createGeometry method from FilamentViewer, set default view blend mode 2024-09-07 17:59:55 +08:00
Nick Fisher c2eb28a8f5 fix: properly destroy entities/material/etc in Gizmo on destruction, remove custom scene creation logic 2024-09-07 17:59:03 +08:00
Nick Fisher 4c6c20f3de feat: move HighlightOverlay to nested class, move createGeometry to SceneManager, add queueRelativePositionUpdateFromViewportVector 2024-09-07 17:57:38 +08:00
Nick Fisher b2ae8135c6 feat: add removeStencilHighlight, accept color param for setStencilHighlight, queuePositionUpdateFromViewportCoords to ThermionDartApi 2024-09-07 17:55:40 +08:00
Nick Fisher aecde97200 feat: add removeStencilHighlight, queuePositionUpdateFromViewportCoords to ThermionViewer 2024-09-07 17:54:42 +08:00
Nick Fisher 331caccc22 chore: delete old unlit_opaque material 2024-09-07 17:54:12 +08:00
Nick Fisher 63e2b74bb1 chore: rebuild unlit material 2024-09-07 17:53:55 +08:00
Nick Fisher 433f03161c feat: add scale parameter to unlit material 2024-09-07 17:53:41 +08:00
Nick Fisher 6ec84b6249 fix: add Fence to capture() and set stencil buffer by default 2024-09-06 13:03:51 +08:00
Nick Fisher 29b6a48816 test: add test cube.glb 2024-09-06 12:44:54 +08:00
Nick Fisher 00755fd417 chore: remove old materials Makefile 2024-09-06 12:44:40 +08:00
Nick Fisher 9c5156e41a feat: add flag for keepData for gltf instancing, add highlightScene, add stencilHighlight method 2024-09-06 12:36:16 +08:00
Nick Fisher 226c45ee2e chore: minor widget fixes 2024-09-05 22:22:25 +08:00
Nick Fisher e04390b2fe feat: add grid material 2024-09-05 22:21:19 +08:00
Nick Fisher 9a87eb4d9b feat: allow passing null options to ThermionWidget 2024-09-05 22:21:09 +08:00
Nick Fisher 2284d9d081 feat: grid uses own material 2024-09-05 22:20:27 +08:00
Nick Fisher cf61369a8d chore: clean up old commented code 2024-09-05 22:20:11 +08:00
Nick Fisher 4e14bd2396 fix: ignore pick results directly on axis 2024-09-05 22:19:54 +08:00
Nick Fisher 0798d5c071 feat: add grid material 2024-09-05 22:19:27 +08:00
Nick Fisher 80d5b1d23f feat: expose setLightDirection and setLightPosition 2024-09-05 22:18:54 +08:00
Nick Fisher 0bd87288d1 chore: update binding 2024-09-05 17:53:24 +08:00
Nick Fisher 51e06c2eb9 chore: (js) stub missing methods 2024-09-05 17:52:53 +08:00
Nick Fisher b29663923d chore: (wasm) add missing interop methods 2024-09-05 17:52:40 +08:00
Nick Fisher f57a323cda feat: (flutter) (web) if importCanvasAsWidget is false, render transparency 2024-09-05 17:52:19 +08:00
Nick Fisher 03ffe85113 chore: stub ThermionWidget methods 2024-09-05 17:51:36 +08:00
Nick Fisher 4edc8aa85b feat: (flutter) move DPR calculation to resizeTexture and add createViewerWithOptions method to ThermionFlutterFFI 2024-09-05 17:51:22 +08:00
Nick Fisher 04ecb4d56f fix: (flutter) pass ThermionFlutterOptions to ThermionWidget, use dpr for resizeTexture, delete unnecessary TransparencyPainter class 2024-09-05 17:49:02 +08:00
Nick Fisher 0ac0a92024 feat: add createViewerWithOptions to ThermionFlutterPlugin and mark createViewer as deprecated 2024-09-05 17:47:54 +08:00
Nick Fisher ae1e14ddb7 feat: add createViewerWithOptions to ThermionFlutterPlugin and mark createViewer as deprecated 2024-09-05 17:47:41 +08:00
Nick Fisher aa246ab63a feat: (flutter) (web) use options to determine whether to create canvas, and set fixed position + offset 2024-09-05 17:45:49 +08:00
Nick Fisher d4350d7d99 test: update viewport gizmo test 2024-09-05 17:44:18 +08:00
Nick Fisher f07fe6084a chore: (flutter) export platform interface from thermion_flutter package 2024-09-05 17:43:58 +08:00
Nick Fisher 4e29055a20 chore: stub new methods 2024-09-05 17:43:35 +08:00
Nick Fisher 6d0c06a853 doc: pixelRatio 2024-09-05 17:43:19 +08:00
Nick Fisher abe6e1fcb8 feat: add ThermionFlutterOptions classes, rename interface parameter for offsetTop and ensure pixelRatio is passed to resizeTexture 2024-09-05 17:43:04 +08:00
Nick Fisher 683105c4f7 fix: emscripten export visibility for add_light 2024-09-05 17:42:17 +08:00
Nick Fisher 6f2331582c chore: use float instead of float32_t in FilamentViewer 2024-09-05 17:41:55 +08:00
Nick Fisher f0f97e310c chore: add nested PickCallbackHandler to Gizmo 2024-09-05 17:41:24 +08:00
Nick Fisher 2331f2c31a chore: update Makefile to add missing headers to resgen files 2024-08-27 21:51:29 +08:00
Nick Fisher 704b7f6734 fix: (flutter/web) use window.devicePixelRatio for viewport 2024-08-27 21:51:09 +08:00
Nick Fisher 7ac7ae43ab fix: (wasm) use correct coords for pick, free memory correctly, keep pixelratio copy 2024-08-27 21:50:07 +08:00
Nick Fisher d52b23d6b5 fix: (flutter) desktop gesture detector changes for new Gizmo methods 2024-08-27 21:49:28 +08:00
Nick Fisher 8b17916cd9 chore: Dart Gizmo class cleanup 2024-08-27 21:49:04 +08:00
Nick Fisher 4a0f4e3ac8 feat: add setGizmoVisibility/pickGizmo methods to ThermionViewer 2024-08-27 21:48:27 +08:00
Nick Fisher 85116f43a2 feat: remove gizmo view references, exclude gizmo entities from picking, add createIbl 2024-08-27 21:47:56 +08:00
Nick Fisher 3ecb8920ea feat: createIbl 2024-08-27 21:47:02 +08:00
Nick Fisher 8923d97129 chore: init SceneManager pointers to nullptr 2024-08-27 21:46:47 +08:00
Nick Fisher 375e1cc887 fix: add more nan checks for gizmo manipulation 2024-08-27 21:46:21 +08:00
Nick Fisher 78dcbc8bb9 feat: expose API methods for create_ibl, pick/set gizmo visibility 2024-08-27 21:45:49 +08:00
Nick Fisher a3f7b98bf7 feat: create transparent overlay for gizmo for easier picking 2024-08-27 21:45:19 +08:00
Nick Fisher 12b61e8767 feat: rescale gizmo based on distance from camera 2024-08-27 16:54:40 +08:00
Nick Fisher 0e3b014c2c feat: rescale gizmo based on distance from camera 2024-08-27 16:50:54 +08:00
Nick Fisher 10db8c39f3 fix: add check for nan NDC coordinates for viewport translation 2024-08-25 21:54:08 +08:00
Nick Fisher 371bcb3706 fix stub methods 2024-08-24 16:28:12 +08:00
Nick Fisher 714c575409 add implementations to JS bridge/shim classes 2024-08-24 16:26:05 +08:00
Nick Fisher c0941e3b7f add missing methods to wasm viewer 2024-08-24 16:25:37 +08:00
Nick Fisher 026acb7467 feat: highlight gizmo on hover 2024-08-24 16:25:17 +08:00
Nick Fisher 3c05cc6a43 add implementations to FFI viewer 2024-08-24 16:24:59 +08:00
Nick Fisher f1a2926bdf fix!: (flutter) pass pixelRatio to createTexture 2024-08-24 16:24:06 +08:00
Nick Fisher 88e8a138ac (flutter) (web) initialize viewer to 1x1 then resize on createTexture 2024-08-24 16:23:54 +08:00
Nick Fisher 53d0301828 feat!: (flutter) (web) upgrade package:web dep to 1.0.0 2024-08-24 16:23:00 +08:00
Nick Fisher b10fec1963 fix!: (flutter) pass pixelRatio to createTexture 2024-08-24 16:22:31 +08:00
Nick Fisher 08e1eb7778 feat: expose setLayerEnabled, viewportDimensions and getCameraFov on ThermionView 2024-08-24 16:22:12 +08:00
Nick Fisher d6713c090c stub out new methods 2024-08-24 16:21:35 +08:00
Nick Fisher 497ecbf881 fix!: (flutter) pass pixelRatio to createTexture 2024-08-24 16:20:06 +08:00
Nick Fisher 6f7d03737e fix!: (flutter) pass pixelRatio to createTexture 2024-08-24 16:19:50 +08:00
Nick Fisher ad60c6bbe1 chore: update bindings 2024-08-24 16:19:07 +08:00
Nick Fisher 92fdda722b chore: add viewport test 2024-08-24 16:18:53 +08:00
Nick Fisher 3cc876f972 feat: layers, grid 2024-08-24 16:18:23 +08:00
Nick Fisher 7d1e706045 feat: layers, grid 2024-08-24 16:18:12 +08:00
Nick Fisher 11756fcedd feat: ignore grid overlay and gizmo center when picking, implement highlighting 2024-08-24 16:17:34 +08:00
Nick Fisher 2e1f2cd56d feat: SceneManager updates (setLayer, add grid, queueRelativePositionUpdateWorld 2024-08-24 16:02:54 +08:00
Nick Fisher c08611b2c3 feat: expose set_layer_enabled, get_camera_fov and queue_relative_position_updateg_world_axis to ThermionDartApi.h 2024-08-24 16:02:06 +08:00
Nick Fisher f87f89427d feat: add getCameraFov to FilamentViewer 2024-08-24 16:01:03 +08:00
Nick Fisher c3319ebbf3 feat: add new grid overlay files to web CmakeLists 2024-08-24 16:00:15 +08:00
Nick Fisher f7b765c5d0 chore: rebuild materials 2024-08-24 15:59:55 +08:00
Nick Fisher 9512b74008 fix: update material output path in Makefile 2024-08-24 15:59:36 +08:00
Nick Fisher 5a3517f953 add grid overlay 2024-08-24 15:59:04 +08:00
Nick Fisher 731c4981c9 use inactive/active color gizmo 2024-08-24 15:58:49 +08:00
Nick Fisher 8f20a8a859 chore: don't use shader to overlay gizmo 2024-08-24 15:21:36 +08:00
Nick Fisher 7693a0fe14 feat: re-implement (native) Gizmo class, expose preserveScaling parameter for setParent, add methods for getting viewport bounding box from renderable entity 2024-08-22 18:04:06 +08:00
Nick Fisher 98c3676fdf fix: (web) add emscripten guards for flushAndWait call when swapchain destroyed 2024-08-21 17:18:37 +08:00
Nick Fisher d7664a9746 feat!: (web) (flutter) create canvas when createViewer is called (no longer need to manually add canvas element to web HTML) 2024-08-21 17:17:58 +08:00
Nick Fisher d868fd6970 feat: add capture() function and expose viewportDimensions on ThermionViewer (allows easier saving of captured images to PNG) 2024-08-21 14:33:48 +08:00
Nick Fisher 300396b97e feat: (web) allow table growth in emscripten module for passing C-style callback function pointers 2024-08-21 14:30:17 +08:00
Nick Fisher 1d8faa70a1 feat: (web) add capture() method and missing camera navigation controls 2024-08-21 14:29:40 +08:00
Nick Fisher 1051b1bb0e feat!: resize canvas on web 2024-08-17 11:43:43 +08:00
Nick Fisher c367824041 feat!: update web/http dependencies 2024-08-17 11:43:03 +08:00
Nick Fisher 81cedf0d43 feat: download WASM module directly on web (no need to embed in index.html any more) and expose updateViewportAndCameraProjection 2024-08-17 11:42:25 +08:00
Nick Fisher 16c6203b97 feat: add startOffset parameter to gltf playAnimation 2024-07-29 16:13:45 +08:00
Nick Fisher b7c0eeb7b4 chore(release): publish packages
- thermion_dart@0.1.3
 - thermion_flutter_ffi@0.1.0+12
 - thermion_flutter_web@0.0.3
 - thermion_flutter_platform_interface@0.1.0+11
 - thermion_flutter@0.1.1+13
2024-07-23 09:40:05 +08:00
Nick Fisher 7a362411b1 Merge pull request #56 from payl-ampa/patch-2
docs: correct link to windows page in quickstart page
2024-07-05 10:26:21 +10:00
Paul Ampadu e95dfe4671 Update quickstart.mdx 2024-07-04 10:59:27 -07:00
Nick Fisher e7b79bb6b9 fix: web/JS bool checks need to compare to int 2024-07-04 21:49:13 +08:00
Nick Fisher 59bc309f5b feat: allow passing assetPathPrefix to ThermionViewerWasm to account for Flutter build asset paths 2024-07-04 16:29:56 +08:00
Nick Fisher d2fb40f317 fix: shadow JS<->WASM bridge methods 2024-07-04 16:29:08 +08:00
91 changed files with 2936 additions and 3551 deletions
+82 -18
View File
@@ -2,7 +2,6 @@
# They are provided by a third-party and are governed by # They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support # separate terms of service, privacy policy, and support
# documentation. # documentation.
name: Dart name: Dart
on: on:
@@ -12,31 +11,96 @@ on:
branches: [ "develop" ] branches: [ "develop" ]
jobs: jobs:
build: thermion_dart:
runs-on: macos-13 name: thermion_dart
runs-on: windows-2019
defaults:
run:
working-directory: thermion_dart # Adjust this path
shell: bash # This helps ensure consistent behavior across platforms
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
# Enable debug logging for Actions
- name: Enable debug logging
run: echo "ACTIONS_STEP_DEBUG=true" >> $GITHUB_ENV
# Note: This workflow uses the latest stable version of the Dart SDK. # Setup Visual Studio environment
# You can specify other versions if desired, see documentation here: - name: Setup MSVC
# https://github.com/dart-lang/setup-dart/blob/main/README.md uses: ilammy/msvc-dev-cmd@v1
# - uses: dart-lang/setup-dart@v1 with:
- uses: dart-lang/setup-dart@9a04e6d73cca37bd455e0608d7e5092f881fd603 arch: x64
- uses: subosito/flutter-action@v2
with:
flutter-version: '3.26.0-0.1.pre' # Specify Flutter version
channel: 'master' # or 'beta', 'dev', 'master'
cache: true # Caches dependencies between runs
architecture: x64 # Explicitly specify x64 architecture
- name: Install dependencies - name: Install dependencies
run: dart pub get run: flutter pub get # even though this is a Dart package, it has as dev_dependency on objective_c for testing which for some reason has a Flutter dependency
# Ensure Visual C++ runtime is available
- name: Install Visual C++ redistributable
run: |
choco install visualstudio2019-workload-vctools -y
choco install vcredist140 -y
# Uncomment this step to verify the use of 'dart format' on each commit. # Uncomment this step to verify the use of 'dart format' on each commit.
# - name: Verify formatting # - name: Verify formatting
# run: dart format --output=none --set-exit-if-changed . # run: dart format --output=none --set-exit-if-changed .
# Consider passing '--fatal-infos' for slightly stricter analysis. #- name: Analyze project source
- name: Analyze project source # run: dart analyze
run: dart analyze
# Your project will need to have tests in test/ and a dependency on - name: Build and Test
# package:test for this step to succeed. Note that Flutter projects will shell: cmd
# want to change this to 'flutter test'. run: |
- name: Run tests call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
run: dart --enable-experiment=native-assets test dart --enable-experiment=native-assets test test/dummy_tests.dart
# Upload logs on failure
- name: Upload logs
if: failure() || steps.build.outcome == 'failure'
uses: actions/upload-artifact@v4
with:
name: build-logs
path: |
D:\a\thermion\thermion\thermion_dart\.dart_tool\thermion_dart\log\build.log
# /Users/runner/work/thermion/thermion/thermion_dart//.dart_tool/thermion_dart/log/build.log
retention-days: 5
# Capture crash dumps if they exist
- name: Collect crash dumps
if: failure()
uses: actions/upload-artifact@v3
with:
name: crash-dumps
path: |
${{ runner.temp }}/*.dmp
${{ env.LOCALAPPDATA }}/Temp/*.dmp
${{ env.LOCALAPPDATA }}/CrashDumps/*.dmp
# thermion_flutter:
# name: thermion_flutter
# runs-on: macos-13
# defaults:
# run:
# working-directory: thermion_flutter/thermion_flutter # Adjust this path
# steps:
# - uses: actions/checkout@v4
# - uses: dart-lang/setup-dart@9a04e6d73cca37bd455e0608d7e5092f881fd603
# - name: Install dependencies
# run: dart pub get
# # Uncomment this step to verify the use of 'dart format' on each commit.
# # - name: Verify formatting
# # run: dart format --output=none --set-exit-if-changed .
# - name: Analyze project source
# run: dart analyze
# - name: Run tests
# run: dart --enable-experiment=native-assets test
+288
View File
@@ -3,6 +3,294 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## 2024-10-31
### Changes
---
Packages with breaking changes:
- There are no breaking changes in this release.
Packages with other changes:
- [`thermion_dart` - `v0.2.1-dev.0.0.16`](#thermion_dart---v021-dev0016)
- [`thermion_flutter` - `v0.2.1-dev.16`](#thermion_flutter---v021-dev16)
- [`thermion_flutter_web` - `v0.2.0+7`](#thermion_flutter_web---v0207)
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.16`](#thermion_flutter_platform_interface---v021-dev16)
- [`thermion_flutter_ffi` - `v0.2.1-dev.16`](#thermion_flutter_ffi---v021-dev16)
Packages with dependency updates only:
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
- `thermion_flutter` - `v0.2.1-dev.16`
- `thermion_flutter_web` - `v0.2.0+7`
- `thermion_flutter_platform_interface` - `v0.2.1-dev.16`
- `thermion_flutter_ffi` - `v0.2.1-dev.16`
---
#### `thermion_dart` - `v0.2.1-dev.0.0.16`
- **FEAT**: Rename Gizmo material to UnlitFixedSize, and expose methods for using this material on other entities. Also exposes new methods for setting single float parameters.
## 2024-10-31
### Changes
---
Packages with breaking changes:
- There are no breaking changes in this release.
Packages with other changes:
- [`thermion_dart` - `v0.2.1-dev.0.0.15`](#thermion_dart---v021-dev0015)
- [`thermion_flutter` - `v0.2.1-dev.15`](#thermion_flutter---v021-dev15)
- [`thermion_flutter_web` - `v0.2.0+6`](#thermion_flutter_web---v0206)
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.15`](#thermion_flutter_platform_interface---v021-dev15)
- [`thermion_flutter_ffi` - `v0.2.1-dev.15`](#thermion_flutter_ffi---v021-dev15)
Packages with dependency updates only:
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
- `thermion_flutter_web` - `v0.2.0+6`
- `thermion_flutter_platform_interface` - `v0.2.1-dev.15`
- `thermion_flutter_ffi` - `v0.2.1-dev.15`
---
#### `thermion_dart` - `v0.2.1-dev.0.0.15`
- **FIX**: remove superfluous ceil() calls for picking coordinates.
- **FEAT**: expose zoomSensitivity argument for flight input handler.
#### `thermion_flutter` - `v0.2.1-dev.15`
- **FIX**: multiply coordinates by pixelRatio for scale events.
## 2024-10-30
### Changes
---
Packages with breaking changes:
- There are no breaking changes in this release.
Packages with other changes:
- [`thermion_dart` - `v0.2.1-dev.0.0.14`](#thermion_dart---v021-dev0014)
- [`thermion_flutter` - `v0.2.1-dev.14`](#thermion_flutter---v021-dev14)
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.14`](#thermion_flutter_platform_interface---v021-dev14)
- [`thermion_flutter_ffi` - `v0.2.1-dev.14`](#thermion_flutter_ffi---v021-dev14)
- [`thermion_flutter_web` - `v0.2.0+5`](#thermion_flutter_web---v0205)
Packages with dependency updates only:
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
- `thermion_flutter` - `v0.2.1-dev.14`
- `thermion_flutter_platform_interface` - `v0.2.1-dev.14`
- `thermion_flutter_ffi` - `v0.2.1-dev.14`
- `thermion_flutter_web` - `v0.2.0+5`
---
#### `thermion_dart` - `v0.2.1-dev.0.0.14`
- **FIX**: reduce size of pick functor for compatibility with armeabi-v7a.
- **FEAT**: sanitize file paths in build.dart for Windows compatibility.
- **FEAT**: pass through fragment coordinates for picking.
- **FEAT**: pass through fragment coordinates for picking.
## 2024-10-29
### Changes
---
Packages with breaking changes:
- There are no breaking changes in this release.
Packages with other changes:
- [`thermion_dart` - `v0.2.1-dev.0.0.13`](#thermion_dart---v021-dev0013)
- [`thermion_flutter_web` - `v0.2.0+4`](#thermion_flutter_web---v0204)
- [`thermion_flutter` - `v0.2.1-dev.13`](#thermion_flutter---v021-dev13)
- [`thermion_flutter_ffi` - `v0.2.1-dev.13`](#thermion_flutter_ffi---v021-dev13)
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.13`](#thermion_flutter_platform_interface---v021-dev13)
Packages with dependency updates only:
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
- `thermion_flutter_web` - `v0.2.0+4`
- `thermion_flutter` - `v0.2.1-dev.13`
- `thermion_flutter_ffi` - `v0.2.1-dev.13`
- `thermion_flutter_platform_interface` - `v0.2.1-dev.13`
---
#### `thermion_dart` - `v0.2.1-dev.0.0.13`
- **FIX**: properly pass through loadResourcesAsync flag for loadGlbFromBuffer.
- **FIX**: properly pass through loadResourcesAsync flag for loadGlbFromBuffer.
- **FEAT**: pass through fragment coordinates for picking.
- **FEAT**: add SCALE2_MOVE InputType.
- **FEAT**: add SCALE2_MOVE InputType.
## 2024-10-25
### Changes
---
Packages with breaking changes:
- There are no breaking changes in this release.
Packages with other changes:
- [`thermion_dart` - `v0.2.1-dev.0.0.12`](#thermion_dart---v021-dev0012)
- [`thermion_flutter` - `v0.2.1-dev.12`](#thermion_flutter---v021-dev12)
- [`thermion_flutter_web` - `v0.2.0+3`](#thermion_flutter_web---v0203)
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.12`](#thermion_flutter_platform_interface---v021-dev12)
- [`thermion_flutter_ffi` - `v0.2.1-dev.12`](#thermion_flutter_ffi---v021-dev12)
Packages with dependency updates only:
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
- `thermion_flutter_web` - `v0.2.0+3`
- `thermion_flutter_platform_interface` - `v0.2.1-dev.12`
- `thermion_flutter_ffi` - `v0.2.1-dev.12`
---
#### `thermion_dart` - `v0.2.1-dev.0.0.12`
- **FIX**: properly pass through loadResourcesAsync flag for loadGlbFromBuffer.
- **FIX**: properly pass through loadResourcesAsync flag for loadGlbFromBuffer.
- **FEAT**: add SCALE2_MOVE InputType.
- **FEAT**: add SCALE2_MOVE InputType.
#### `thermion_flutter` - `v0.2.1-dev.12`
- **FIX**: (flutter) (windows) remove deleted source file from Windows CMakeLists.
## 2024-10-25
### Changes
---
Packages with breaking changes:
- There are no breaking changes in this release.
Packages with other changes:
- [`thermion_dart` - `v0.2.1-dev.0.0.12`](#thermion_dart---v021-dev0012)
- [`thermion_flutter_web` - `v0.2.0+2`](#thermion_flutter_web---v0202)
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.11`](#thermion_flutter_platform_interface---v021-dev11)
- [`thermion_flutter_ffi` - `v0.2.1-dev.11`](#thermion_flutter_ffi---v021-dev11)
- [`thermion_flutter` - `v0.2.1-dev.11`](#thermion_flutter---v021-dev11)
Packages with dependency updates only:
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
- `thermion_flutter_web` - `v0.2.0+2`
- `thermion_flutter_platform_interface` - `v0.2.1-dev.11`
- `thermion_flutter_ffi` - `v0.2.1-dev.11`
- `thermion_flutter` - `v0.2.1-dev.11`
---
#### `thermion_dart` - `v0.2.1-dev.0.0.12`
- **FIX**: properly pass through loadResourcesAsync flag for loadGlbFromBuffer.
- **FEAT**: add SCALE2_MOVE InputType.
## 2024-10-24
### Changes
---
Packages with breaking changes:
- [`thermion_dart` - `v0.2.1-dev.0.0.11`](#thermion_dart---v021-dev0011)
- [`thermion_flutter` - `v0.2.1-dev.10`](#thermion_flutter---v021-dev10)
Packages with other changes:
- [`thermion_flutter_web` - `v0.2.0+1`](#thermion_flutter_web---v0201)
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.10`](#thermion_flutter_platform_interface---v021-dev10)
- [`thermion_flutter_ffi` - `v0.2.1-dev.10`](#thermion_flutter_ffi---v021-dev10)
Packages with dependency updates only:
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
- `thermion_flutter_web` - `v0.2.0+1`
- `thermion_flutter_platform_interface` - `v0.2.1-dev.10`
- `thermion_flutter_ffi` - `v0.2.1-dev.10`
---
#### `thermion_dart` - `v0.2.1-dev.0.0.11`
- **FEAT**: add SCALE2_ROTATE to InputHandler.
- **BREAKING** **FEAT**: expose velocity, rotation and timestamp for scale events in listener. accept rotationSensitivity/zoomSensitivity for FixedOrbitRotateInputHandlerDelegate.
#### `thermion_flutter` - `v0.2.1-dev.10`
- **REFACTOR**: continual refactor to support multiple render targets.
- **FIX**: fix all Windows warnings so apps will compile with /WX.
- **FIX**: use internal Set for determining first ThermionTextureWidget to call requestFrame and cleanup destruction logic.
- **FIX**: (flutter) pass ThermionFlutterOptions to ThermionWidget, use dpr for resizeTexture, delete unnecessary TransparencyPainter class.
- **FIX**: (flutter/web) use window.devicePixelRatio for viewport.
- **FIX**: (flutter) desktop gesture detector changes for new Gizmo methods.
- **FEAT**: (flutter) (windows) add DestroyRenderingSurface method.
- **FEAT**: (flutter) (windows) add DestroyRenderingSurface method.
- **FEAT**: (flutter) (windows) add DestroyRenderingSurface method.
- **FEAT**: (flutter) (windows) add Destroy() to BackingWindow.
- **FEAT**: camera and resizing improvements.
- **FEAT**: support multiple ThermionWidget on Android.
- **FEAT**: use imported texture on iOS.
- **FEAT**: working implementation of multiple widgets on macos.
- **FEAT**: add rendering check to ThermionWidget ticker.
- **FEAT**: allow passing null options to ThermionWidget.
- **FEAT**: (flutter) (web) if importCanvasAsWidget is false, render transparency.
- **FEAT**: add createViewerWithOptions to ThermionFlutterPlugin and mark createViewer as deprecated.
- **FEAT**: add createViewerWithOptions to ThermionFlutterPlugin and mark createViewer as deprecated.
- **FEAT**: highlight gizmo on hover.
- **BREAKING** **FIX**: remove EntityControllerMouseWidget (replace with GestureHandler).
- **BREAKING** **FIX**: (flutter) pass pixelRatio to createTexture.
- **BREAKING** **FIX**: (flutter) pass pixelRatio to createTexture.
- **BREAKING** **FEAT**: expose velocity, rotation and timestamp for scale events in listener. accept rotationSensitivity/zoomSensitivity for FixedOrbitRotateInputHandlerDelegate.
- **BREAKING** **FEAT**: (web) (flutter) create canvas when createViewer is called (no longer need to manually add canvas element to web HTML).
- **BREAKING** **FEAT**: resize canvas on web.
- **BREAKING** **CHORE**: remove superseded HardwareKeyboard* classes.
- **BREAKING** **CHORE**: (flutter) cleanup for pub.dev publishing.
- **BREAKING** **CHORE**: remove EntityListWidget - will replace with new Scene.
- **BREAKING** **CHORE**: rename controller to viewer in gesture detector widgets.
## 2024-10-23 ## 2024-10-23
### Changes ### Changes
+1 -1
View File
@@ -23,7 +23,7 @@ bindings:
# #
materials: FORCE materials: FORCE
@echo "Using Filament build from ${FILAMENT_PATH}" @echo "Using Filament build from ${FILAMENT_PATH}"
@for material in unlit image gizmo grid; do \ @for material in unlit image unlit_fixed_size grid; do \
${FILAMENT_PATH}/matc -a opengl -a metal -o materials/$$material.filamat materials/$$material.mat; \ ${FILAMENT_PATH}/matc -a opengl -a metal -o materials/$$material.filamat materials/$$material.mat; \
$(FILAMENT_PATH)/resgen -c -p $$material -x thermion_dart/native/include/material/ materials/$$material.filamat; \ $(FILAMENT_PATH)/resgen -c -p $$material -x thermion_dart/native/include/material/ materials/$$material.filamat; \
echo '#include "'$$material'.h"' | cat - thermion_dart/native/include/material/$$material.c > thermion_dart/native/include/material/$$material.c.new; \ echo '#include "'$$material'.h"' | cat - thermion_dart/native/include/material/$$material.c > thermion_dart/native/include/material/$$material.c.new; \
+9 -5
View File
@@ -3,7 +3,7 @@
<p align="center"> <p align="center">
<a href="https://thermion.dev/quickstart">Quickstart (Flutter)</a> • <a href="https://thermion.dev/quickstart">Quickstart (Flutter)</a> •
<a href="https://thermion.dev/">Documentation</a> • <a href="https://thermion.dev/">Documentation</a> •
<a href="https://thermion.dev/examples">Showcase</a> • <a href="https://thermion.dev/showcase">Showcase</a> •
<a href="https://dartpad.thermion.dev/">Playground</a> • <a href="https://dartpad.thermion.dev/">Playground</a> •
<a href="https://discord.gg/h2VdDK3EAQ">Discord</a> <a href="https://discord.gg/h2VdDK3EAQ">Discord</a>
</p> </p>
@@ -24,13 +24,17 @@
### Quickstart (Flutter) ### Quickstart (Flutter)
``` From the command line:
```bash
flutter channel master flutter channel master
flutter upgrade flutter upgrade
flutter config --enable-native-assets flutter config --enable-native-assets
``` ```
``` In your Flutter app:
```dart
_thermionViewer = await ThermionFlutterPlugin.createViewer(); _thermionViewer = await ThermionFlutterPlugin.createViewer();
// Geometry and models are represented as "entities". Here, we load a glTF // Geometry and models are represented as "entities". Here, we load a glTF
@@ -61,8 +65,8 @@ await _thermionViewer!.loadIbl("assets/default_env_ibl.ktx");
await _thermionViewer!.setRendering(true); await _thermionViewer!.setRendering(true);
``` ```
and then in your Flutter application: and then in your widget tree:
``` ```dart
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Stack(children: [ return Stack(children: [
+2 -1
View File
@@ -7,7 +7,8 @@
"Getting Started", "Getting Started",
[ [
["Overview", "/"], ["Overview", "/"],
["Quick Start", "/quickstart"] ["Quick Start", "/quickstart"],
["Camera Manipulation", "/camera_manipulation"]
] ]
], ],
["Misc.", [ ["Misc.", [
+1
View File
@@ -0,0 +1 @@
../../assets
@@ -1 +0,0 @@
../../../assets/cube.glb
@@ -1 +0,0 @@
../../../assets/default_env_ibl.ktx
@@ -1 +0,0 @@
../../../assets/default_env_skybox.ktx
@@ -15,13 +15,23 @@ dependencies:
win32: 5.5.1 win32: 5.5.1
web: 1.0.0 web: 1.0.0
thermion_flutter: ^0.2.1-dev.8 thermion_flutter: ^0.2.1-dev.9
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
flutter_lints: ^4.0.0 flutter_lints: ^4.0.0
dependency_overrides:
thermion_dart:
path: ../../../thermion_dart
thermion_flutter:
path: ../../../thermion_flutter/thermion_flutter
thermion_flutter_ffi:
path: ../../../thermion_flutter/thermion_flutter_ffi
thermion_flutter_platform_interface:
path: ../../../thermion_flutter/thermion_flutter_platform_interface
flutter: flutter:
uses-material-design: true uses-material-design: true
assets: assets:
+1
View File
@@ -0,0 +1 @@
../../assets
@@ -1 +0,0 @@
../../../assets/cube.glb
@@ -1 +0,0 @@
../../../assets/default_env_ibl.ktx
@@ -1 +0,0 @@
../../../assets/default_env_skybox.ktx
@@ -87,6 +87,7 @@
93162ABED09E78126BD3CDE5 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 93162ABED09E78126BD3CDE5 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9491FF37DFB0425E4EA0B397 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9491FF37DFB0425E4EA0B397 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
DB0270912CD09BDD00E05CE4 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = "<group>"; };
E5EDF04F05E94A7EC21CBB16 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; }; E5EDF04F05E94A7EC21CBB16 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@@ -188,6 +189,7 @@
33FAB671232836740065AC1E /* Runner */ = { 33FAB671232836740065AC1E /* Runner */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
DB0270912CD09BDD00E05CE4 /* RunnerDebug.entitlements */,
33CC10F02044A3C60003C045 /* AppDelegate.swift */, 33CC10F02044A3C60003C045 /* AppDelegate.swift */,
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
33E51913231747F40026EE4D /* DebugProfile.entitlements */, 33E51913231747F40026EE4D /* DebugProfile.entitlements */,
@@ -703,7 +705,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/RunnerDebug.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
</dict>
</plist>
+10
View File
@@ -16,6 +16,16 @@ dependencies:
web: 1.0.0 web: 1.0.0
thermion_flutter: ^0.2.1-dev.7 thermion_flutter: ^0.2.1-dev.7
dependency_overrides:
thermion_dart:
path: ../../../thermion_dart
thermion_flutter:
path: ../../../thermion_flutter/thermion_flutter
thermion_flutter_ffi:
path: ../../../thermion_flutter/thermion_flutter_ffi
thermion_flutter_platform_interface:
path: ../../../thermion_flutter/thermion_flutter_platform_interface
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
+178 -3
View File
@@ -1,3 +1,178 @@
version https://git-lfs.github.com/spec/v1 material {
oid sha256:bca5e20d7fa68fbc2bb7fa3cd65b07e0ac35c8cf961686cfaa267a941ab96d8f name : unlit_fade,
size 7393 requires : [ uv0, uv1, color ],
shadingModel : ${SHADINGMODEL},
blending : ${BLENDING},
doubleSided : ${DOUBLESIDED},
transparency : ${TRANSPARENCY},
flipUV : false,
specularAmbientOcclusion : simple,
specularAntiAliasing : true,
clearCoatIorChange : false,
reflections : screenspace,
parameters : [
{ type : float3, name : specularFactor },
{ type : float, name : glossinessFactor },
// Base Color
{ type : int, name : baseColorIndex },
{ type : float4, name : baseColorFactor },
{ type : sampler2d, name : baseColorMap },
{ type : mat3, name : baseColorUvMatrix, precision: high },
// Metallic-Roughness Map
{ type : int, name : metallicRoughnessIndex },
{ type : float, name : metallicFactor },
{ type : float, name : roughnessFactor },
{ type : sampler2d, name : metallicRoughnessMap },
{ type : mat3, name : metallicRoughnessUvMatrix, precision: high },
// Normal Map
{ type : int, name : normalIndex },
{ type : float, name : normalScale },
{ type : sampler2d, name : normalMap },
{ type : mat3, name : normalUvMatrix, precision: high },
// Ambient Occlusion
{ type : int, name : aoIndex },
{ type : float, name : aoStrength },
{ type : sampler2d, name : occlusionMap },
{ type : mat3, name : occlusionUvMatrix, precision: high },
// Emissive Map
{ type : int, name : emissiveIndex },
{ type : float3, name : emissiveFactor },
{ type : float, name : emissiveStrength },
{ type : sampler2d, name : emissiveMap },
{ type : mat3, name : emissiveUvMatrix, precision: high },
// Clear coat
{ type : float, name : clearCoatFactor },
{ type : float, name : clearCoatRoughnessFactor },
{ type : int, name : clearCoatIndex },
{ type : sampler2d, name : clearCoatMap },
{ type : mat3, name : clearCoatUvMatrix, precision: high },
{ type : int, name : clearCoatRoughnessIndex },
{ type : sampler2d, name : clearCoatRoughnessMap },
{ type : mat3, name : clearCoatRoughnessUvMatrix, precision: high },
{ type : int, name : clearCoatNormalIndex },
{ type : sampler2d, name : clearCoatNormalMap },
{ type : mat3, name : clearCoatNormalUvMatrix, precision: high },
{ type : float, name : clearCoatNormalScale },
// Reflectance
{ type : float, name : reflectance }
${CUSTOM_PARAMS}
],
}
vertex {
void materialVertex(inout MaterialVertexInputs material) {
${CUSTOM_VERTEX}
}
}
fragment {
void material(inout MaterialInputs material) {
highp float2 uvs[2];
uvs[0] = getUV0();
uvs[1] = getUV1();
#if !defined(SHADING_MODEL_UNLIT)
if (materialParams.normalIndex > -1) {
highp float2 uv = uvs[materialParams.normalIndex];
uv = (vec3(uv, 1.0) * materialParams.normalUvMatrix).xy;
material.normal = texture(materialParams_normalMap, uv).xyz * 2.0 - 1.0;
material.normal.xy *= materialParams.normalScale;
}
#if defined(SHADING_MODEL_LIT)
if (materialParams.clearCoatNormalIndex > -1) {
highp float2 uv = uvs[materialParams.clearCoatNormalIndex];
uv = (vec3(uv, 1.0) * materialParams.clearCoatNormalUvMatrix).xy;
material.clearCoatNormal = texture(materialParams_clearCoatNormalMap, uv).xyz * 2.0 - 1.0;
material.clearCoatNormal.xy *= materialParams.clearCoatNormalScale;
}
#endif
#endif
prepareMaterial(material);
material.baseColor = materialParams.baseColorFactor;
if (materialParams.baseColorIndex > -1) {
highp float2 uv = uvs[materialParams.baseColorIndex];
uv = (vec3(uv, 1.0) * materialParams.baseColorUvMatrix).xy;
material.baseColor *= texture(materialParams_baseColorMap, uv);
}
#if defined(BLEND_MODE_TRANSPARENT)
material.baseColor.rgb *= material.baseColor.a;
#endif
material.baseColor *= getColor();
#if !defined(SHADING_MODEL_UNLIT)
#if defined(SHADING_MODEL_LIT)
material.roughness = materialParams.roughnessFactor;
material.metallic = materialParams.metallicFactor;
// KHR_materials_clearcoat forbids clear coat from
// being applied in the specular/glossiness model
material.clearCoat = materialParams.clearCoatFactor;
material.clearCoatRoughness = materialParams.clearCoatRoughnessFactor;
if (materialParams.clearCoatIndex > -1) {
highp float2 uv = uvs[materialParams.clearCoatIndex];
uv = (vec3(uv, 1.0) * materialParams.clearCoatUvMatrix).xy;
material.clearCoat *= texture(materialParams_clearCoatMap, uv).r;
}
if (materialParams.clearCoatRoughnessIndex > -1) {
highp float2 uv = uvs[materialParams.clearCoatRoughnessIndex];
uv = (vec3(uv, 1.0) * materialParams.clearCoatRoughnessUvMatrix).xy;
material.clearCoatRoughness *= texture(materialParams_clearCoatRoughnessMap, uv).g;
}
#endif
material.emissive = vec4(materialParams.emissiveStrength *
materialParams.emissiveFactor.rgb, 0.0);
#if defined(SHADING_MODEL_SPECULAR_GLOSSINESS)
material.glossiness = materialParams.glossinessFactor;
material.specularColor = materialParams.specularFactor;
#else
material.reflectance = materialParams.reflectance;
#endif
if (materialParams.metallicRoughnessIndex > -1) {
highp float2 uv = uvs[materialParams.metallicRoughnessIndex];
uv = (vec3(uv, 1.0) * materialParams.metallicRoughnessUvMatrix).xy;
#if defined(SHADING_MODEL_SPECULAR_GLOSSINESS)
vec4 sg = texture(materialParams_metallicRoughnessMap, uv);
material.specularColor *= sg.rgb;
material.glossiness *= sg.a;
#else
vec4 mr = texture(materialParams_metallicRoughnessMap, uv);
material.roughness *= mr.g;
material.metallic *= mr.b;
#endif
}
if (materialParams.aoIndex > -1) {
highp float2 uv = uvs[materialParams.aoIndex];
uv = (vec3(uv, 1.0) * materialParams.occlusionUvMatrix).xy;
float occlusion = texture(materialParams_occlusionMap, uv).r;
material.ambientOcclusion = 1.0 + materialParams.aoStrength * (occlusion - 1.0);
}
if (materialParams.emissiveIndex > -1) {
highp float2 uv = uvs[materialParams.emissiveIndex];
uv = (vec3(uv, 1.0) * materialParams.emissiveUvMatrix).xy;
material.emissive.rgb *= texture(materialParams_emissiveMap, uv).rgb;
}
#endif
${CUSTOM_FRAGMENT}
}
}
@@ -1,5 +1,5 @@
material { material {
name : Gizmo, name : UnlitFixedSize,
parameters : [ parameters : [
{ {
type : mat4, type : mat4,
@@ -8,8 +8,13 @@
}, },
{ {
type : float4, type : float4,
name : color, name : baseColorFactor,
precision : low precision : low
},
{
type: float, // the number of world-space units between the camera and the (unscaled) gizmo
name: scale,
precision: low
} }
], ],
depthWrite : true, depthWrite : true,
@@ -24,14 +29,13 @@
vertex { vertex {
void materialVertex(inout MaterialVertexInputs material) { void materialVertex(inout MaterialVertexInputs material) {
// the object should have the same size (in screen-space), no matter the distance from the camera
// we want to ensure the gizmo has the same size (in screen-space), no matter the distance from the camera // scale the model-space vertex positions by the distance from the camera
// we do this by scaling the model-space vertex positions by the distance from the camera
vec4 modelSpace = getPosition(); vec4 modelSpace = getPosition();
vec4 worldSpace = getWorldFromModelMatrix() * modelSpace; vec4 worldSpace = getWorldFromModelMatrix() * modelSpace;
vec4 viewSpace = getViewFromWorldMatrix() * worldSpace; vec4 viewSpace = getViewFromWorldMatrix() * worldSpace;
float distanceFromCamera = length(viewSpace.xyz); float distanceFromCamera = length(viewSpace.xyz);
modelSpace.xyz *= (distanceFromCamera / 4.0f); // divide by 4 so that the size is equivalent to the camera being 4 world-space units away from the (unscaled) gizmo modelSpace.xyz *= (distanceFromCamera / materialParams.scale);
worldSpace = getWorldFromModelMatrix() * modelSpace; worldSpace = getWorldFromModelMatrix() * modelSpace;
material.worldPosition = worldSpace; material.worldPosition = worldSpace;
@@ -44,7 +48,7 @@
fragment { fragment {
void material(inout MaterialInputs material) { void material(inout MaterialInputs material) {
prepareMaterial(material); prepareMaterial(material);
material.baseColor = materialParams.color; material.baseColor = materialParams.baseColorFactor;
} }
} }
+43
View File
@@ -1,3 +1,46 @@
## 0.2.1-dev.0.0.16
- **FEAT**: Rename Gizmo material to UnlitFixedSize, and expose methods for using this material on other entities. Also exposes new methods for setting single float parameters.
## 0.2.1-dev.0.0.15
- **FIX**: remove superfluous ceil() calls for picking coordinates.
- **FEAT**: expose zoomSensitivity argument for flight input handler.
## 0.2.1-dev.0.0.14
- **FIX**: reduce size of pick functor for compatibility with armeabi-v7a.
- **FEAT**: sanitize file paths in build.dart for Windows compatibility.
- **FEAT**: pass through fragment coordinates for picking.
- **FEAT**: pass through fragment coordinates for picking.
## 0.2.1-dev.0.0.13
- **FIX**: properly pass through loadResourcesAsync flag for loadGlbFromBuffer.
- **FIX**: properly pass through loadResourcesAsync flag for loadGlbFromBuffer.
- **FEAT**: pass through fragment coordinates for picking.
- **FEAT**: add SCALE2_MOVE InputType.
- **FEAT**: add SCALE2_MOVE InputType.
## 0.2.1-dev.0.0.12
- **FIX**: properly pass through loadResourcesAsync flag for loadGlbFromBuffer.
- **FIX**: properly pass through loadResourcesAsync flag for loadGlbFromBuffer.
- **FEAT**: add SCALE2_MOVE InputType.
- **FEAT**: add SCALE2_MOVE InputType.
## 0.2.1-dev.0.0.12
- **FIX**: properly pass through loadResourcesAsync flag for loadGlbFromBuffer.
- **FEAT**: add SCALE2_MOVE InputType.
## 0.2.1-dev.0.0.11
> Note: This release has breaking changes.
- **FEAT**: add SCALE2_ROTATE to InputHandler.
- **BREAKING** **FEAT**: expose velocity, rotation and timestamp for scale events in listener. accept rotationSensitivity/zoomSensitivity for FixedOrbitRotateInputHandlerDelegate.
## 0.2.1-dev.0.0.10 ## 0.2.1-dev.0.0.10
> Note: This release has breaking changes. > Note: This release has breaking changes.
+1 -1
View File
@@ -3,7 +3,7 @@
<p align="center"> <p align="center">
<a href="https://thermion.dev/quickstart">Quickstart (Flutter)</a> • <a href="https://thermion.dev/quickstart">Quickstart (Flutter)</a> •
<a href="https://thermion.dev/quickstart">Documentation</a> • <a href="https://thermion.dev/quickstart">Documentation</a> •
<a href="https://thermion.dev/examples">Showcase</a> • <a href="https://thermion.dev/showcase">Showcase</a> •
<a href="https://dartpad.thermion.dev/">Playground</a> • <a href="https://dartpad.thermion.dev/">Playground</a> •
<a href="https://discord.gg/h2VdDK3EAQ">Discord</a> <a href="https://discord.gg/h2VdDK3EAQ">Discord</a>
</p> </p>
+22 -19
View File
@@ -3,11 +3,15 @@ import 'package:archive/archive.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:native_assets_cli/native_assets_cli.dart'; import 'package:native_assets_cli/native_assets_cli.dart';
import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart';
import 'package:path/path.dart' as path;
void main(List<String> args) async { void main(List<String> args) async {
await build(args, (config, output) async { await build(args, (config, output) async {
var logFile = File(
"${config.packageRoot.toFilePath()}.dart_tool/thermion_dart/log/build.log"); var pkgRootFilePath = config.packageRoot.toFilePath(windows: Platform.isWindows);
var logPath = path.join(pkgRootFilePath, ".dart_tool", "thermion_dart", "log", "build.log");
var logFile = File(logPath);
if (!logFile.parent.existsSync()) { if (!logFile.parent.existsSync()) {
logFile.parent.createSync(recursive: true); logFile.parent.createSync(recursive: true);
} }
@@ -50,16 +54,16 @@ void main(List<String> args) async {
final packageName = config.packageName; final packageName = config.packageName;
final sources = Directory("${config.packageRoot.toFilePath()}/native/src") final sources = Directory(path.join(pkgRootFilePath, "native", "src"))
.listSync(recursive: true) .listSync(recursive: true)
.whereType<File>() .whereType<File>()
.map((f) => f.path) .map((f) => f.path)
.toList(); .toList();
sources.addAll([ sources.addAll([
"${config.packageRoot.toFilePath()}/native/include/material/gizmo_material.c", path.join(pkgRootFilePath, "native", "include", "material", "unlit_fixed_size.c"),
"${config.packageRoot.toFilePath()}/native/include/material/image.c", path.join(pkgRootFilePath, "native", "include", "material", "image.c"),
"${config.packageRoot.toFilePath()}/native/include/material/grid.c", path.join(pkgRootFilePath, "native", "include", "material", "grid.c"),
"${config.packageRoot.toFilePath()}/native/include/material/unlit.c", path.join(pkgRootFilePath, "native", "include", "material", "unlit.c"),
]); ]);
var libs = [ var libs = [
@@ -91,9 +95,9 @@ void main(List<String> args) async {
]; ];
if (platform == "windows") { if (platform == "windows") {
libDir = Directory(libDir).uri.toFilePath(); libDir = Directory(libDir).uri.toFilePath(windows: config.targetOS == OS.windows);
libs = libs.map((lib) => "${libDir}${lib}.lib").toList(); libs = libs.map((lib) => path.join(libDir, "${lib}.lib")).toList();
libs.addAll(["${libDir}bluevk.lib", "${libDir}bluegl.lib"]); libs.addAll([path.join(libDir,"bluevk.lib"), path.join(libDir,"bluegl.lib")]);
libs.addAll([ libs.addAll([
"gdi32.lib", "gdi32.lib",
"user32.lib", "user32.lib",
@@ -172,8 +176,8 @@ void main(List<String> args) async {
if (platform != "windows") ...libs.map((lib) => "-l$lib"), if (platform != "windows") ...libs.map((lib) => "-l$lib"),
if (platform != "windows") "-L$libDir", if (platform != "windows") "-L$libDir",
if (platform == "windows") ...[ if (platform == "windows") ...[
"/I${config.packageRoot.toFilePath()}\\native\\include", "/I${path.join(pkgRootFilePath, "native", "include")}",
"/I${config.packageRoot.toFilePath()}native\\include\\filament", "/I${path.join(pkgRootFilePath, "native", "include", "filament")}",
...sources, ...sources,
'/link', '/link',
"/LIBPATH:$libDir", "/LIBPATH:$libDir",
@@ -232,8 +236,7 @@ void main(List<String> args) async {
name: "thermion_dart.dll", name: "thermion_dart.dll",
linkMode: DynamicLoadingBundled(), linkMode: DynamicLoadingBundled(),
os: config.targetOS, os: config.targetOS,
file: Uri.file( file: Uri.file(path.join(pkgRootFilePath, "thermion_dart.dll")),
config.outputDirectory.toFilePath() + "/thermion_dart.dll"),
architecture: config.targetArchitecture), architecture: config.targetArchitecture),
linkInPackage: config.packageName); linkInPackage: config.packageName);
} }
@@ -263,9 +266,9 @@ Future<Directory> getLibDir(BuildConfig config, Logger logger) async {
if (platform == "windows") { if (platform == "windows") {
mode = config.buildMode == BuildMode.debug ? "debug" : "release"; mode = config.buildMode == BuildMode.debug ? "debug" : "release";
} }
var libDir = Directory( var libDir = Directory(
"${config.packageRoot.toFilePath()}/.dart_tool/thermion_dart/lib/${_FILAMENT_VERSION}/$platform/$mode/"); path.join(config.packageRoot.toFilePath(windows:Platform.isWindows), ".dart_tool", "thermion_dart", "lib", _FILAMENT_VERSION, platform, mode));
if (platform == "android") { if (platform == "android") {
final archExtension = switch (config.targetArchitecture) { final archExtension = switch (config.targetArchitecture) {
@@ -275,7 +278,7 @@ Future<Directory> getLibDir(BuildConfig config, Logger logger) async {
Architecture.ia32 => "x86", Architecture.ia32 => "x86",
_ => throw FormatException('Invalid') _ => throw FormatException('Invalid')
}; };
libDir = Directory("${libDir.path}/$archExtension/"); libDir = Directory(path.join(libDir.path, archExtension));
} else if (platform == "windows") { } else if (platform == "windows") {
if (config.targetArchitecture != Architecture.x64) { if (config.targetArchitecture != Architecture.x64) {
throw Exception( throw Exception(
@@ -292,8 +295,8 @@ Future<Directory> getLibDir(BuildConfig config, Logger logger) async {
// We will write an empty file called success to the unzip directory after successfully downloading/extracting the prebuilt libraries. // We will write an empty file called success to the unzip directory after successfully downloading/extracting the prebuilt libraries.
// If this file already exists, we assume everything has been successfully extracted and skip // If this file already exists, we assume everything has been successfully extracted and skip
final unzipDir = platform == "android" ? libDir.parent.path : libDir.path; final unzipDir = platform == "android" ? libDir.parent.path : libDir.path;
final successToken = File("$unzipDir/success"); final successToken = File(path.join(unzipDir, "success"));
final libraryZip = File("$unzipDir/$filename"); final libraryZip = File(path.join(unzipDir, filename));
if (!successToken.existsSync()) { if (!successToken.existsSync()) {
if (libraryZip.existsSync()) { if (libraryZip.existsSync()) {
@@ -82,6 +82,7 @@ class DelegateInputHandler implements InputHandler {
{PickDelegate? pickDelegate, {PickDelegate? pickDelegate,
bool freeLook = false, bool freeLook = false,
double panSensitivity = 0.1, double panSensitivity = 0.1,
double zoomSensitivity = 0.1,
double movementSensitivity = 0.1, double movementSensitivity = 0.1,
double rotateSensitivity = 0.01, double rotateSensitivity = 0.01,
double? clampY, double? clampY,
@@ -93,6 +94,7 @@ class DelegateInputHandler implements InputHandler {
clampY: clampY, clampY: clampY,
entity: entity, entity: entity,
rotationSensitivity: rotateSensitivity, rotationSensitivity: rotateSensitivity,
zoomSensitivity:zoomSensitivity,
panSensitivity: panSensitivity, panSensitivity: panSensitivity,
movementSensitivity: movementSensitivity), movementSensitivity: movementSensitivity),
actions: { actions: {
@@ -260,10 +262,10 @@ class DelegateInputHandler implements InputHandler {
} }
@override @override
Future<void> onScaleEnd(int pointerCount) async {} Future<void> onScaleEnd(int pointerCount, double velocity) async {}
@override @override
Future<void> onScaleStart(Vector2 localPosition, int pointerCount) async { Future<void> onScaleStart(Vector2 localPosition, int pointerCount, Duration? sourceTimestamp ) async {
// noop // noop
} }
@@ -276,7 +278,9 @@ class DelegateInputHandler implements InputHandler {
double horizontalScale, double horizontalScale,
double verticalScale, double verticalScale,
double scale, double scale,
int pointerCount) async { int pointerCount,
double rotation,
Duration? sourceTimestamp) async {
if (pointerCount == 1) { if (pointerCount == 1) {
_inputDeltas[InputType.SCALE1] = _inputDeltas[InputType.SCALE1] =
Vector3(focalPointDelta.x, focalPointDelta.y, 0); Vector3(focalPointDelta.x, focalPointDelta.y, 0);
@@ -14,6 +14,9 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
late Future<Camera> _camera; late Future<Camera> _camera;
final double minimumDistance; final double minimumDistance;
late final Vector3 target; late final Vector3 target;
final double rotationSensitivity;
final double zoomSensitivity;
Vector2 _queuedRotationDelta = Vector2.zero(); Vector2 _queuedRotationDelta = Vector2.zero();
double _queuedZoomDelta = 0.0; double _queuedZoomDelta = 0.0;
@@ -24,6 +27,8 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
this.viewer, { this.viewer, {
Vector3? target, Vector3? target,
this.minimumDistance = 10.0, this.minimumDistance = 10.0,
this.rotationSensitivity = 0.01,
this.zoomSensitivity = 0.1,
}) { }) {
this.target = target ?? Vector3.zero(); this.target = target ?? Vector3.zero();
_camera = viewer.getMainCamera().then((Camera cam) async { _camera = viewer.getMainCamera().then((Camera cam) async {
@@ -95,7 +100,7 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
// Zoom // Zoom
if (_queuedZoomDelta != 0.0) { if (_queuedZoomDelta != 0.0) {
var newPosition = currentPosition + var newPosition = currentPosition +
(currentPosition - target).scaled(_queuedZoomDelta * 0.1); (currentPosition - target).scaled(_queuedZoomDelta * zoomSensitivity);
var distToTarget = (newPosition - target).length; var distToTarget = (newPosition - target).length;
@@ -113,8 +118,8 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
await (await _camera).setModelMatrix(newViewMatrix); await (await _camera).setModelMatrix(newViewMatrix);
} }
} else if (_queuedRotationDelta.length != 0) { } else if (_queuedRotationDelta.length != 0) {
double rotateX = _queuedRotationDelta.x * 0.01; double rotateX = _queuedRotationDelta.x * rotationSensitivity;
double rotateY = _queuedRotationDelta.y * 0.01; double rotateY = _queuedRotationDelta.y * rotationSensitivity;
var modelMatrix = await viewer.getCameraModelMatrix(); var modelMatrix = await viewer.getCameraModelMatrix();
@@ -126,9 +131,8 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
var rot2 = Matrix4.identity() var rot2 = Matrix4.identity()
..setRotation(Quaternion.axisAngle(modelMatrix.right, rotateY) ..setRotation(Quaternion.axisAngle(modelMatrix.right, rotateY)
.asRotationMatrix()); .asRotationMatrix());
modelMatrix = rot1 * modelMatrix = rot1 * rot2 * modelMatrix;
rot2 * modelMatrix;
await (await _camera).setModelMatrix(modelMatrix); await (await _camera).setModelMatrix(modelMatrix);
} }
@@ -13,7 +13,9 @@ enum InputType {
MMB_UP, MMB_UP,
MMB_HOVER, MMB_HOVER,
SCALE1, SCALE1,
SCALE2, SCALE2, // two fingers pinchin in/out
SCALE2_ROTATE, // two fingers rotating in a circle
SCALE2_MOVE, // two fingers sliding along a line
SCROLLWHEEL, SCROLLWHEEL,
POINTER_MOVE, POINTER_MOVE,
KEYDOWN_W, KEYDOWN_W,
@@ -35,9 +37,9 @@ abstract class InputHandler {
Future<void> onPointerMove( Future<void> onPointerMove(
Vector2 localPosition, Vector2 delta, bool isMiddle); Vector2 localPosition, Vector2 delta, bool isMiddle);
Future<void> onPointerUp(bool isMiddle); Future<void> onPointerUp(bool isMiddle);
Future<void> onScaleStart(Vector2 focalPoint, int pointerCount); Future<void> onScaleStart(Vector2 focalPoint, int pointerCount, Duration? sourceTimestamp);
Future<void> onScaleUpdate(Vector2 focalPoint, Vector2 focalPointDelta, double horizontalScale, double verticalScale, double scale, int pointerCount); Future<void> onScaleUpdate(Vector2 focalPoint, Vector2 focalPointDelta, double horizontalScale, double verticalScale, double scale, int pointerCount, double rotation, Duration? sourceTimestamp);
Future<void> onScaleEnd(int pointerCount); Future<void> onScaleEnd(int pointerCount, double velocity);
Future<bool> get initialized; Future<bool> get initialized;
Future dispose(); Future dispose();
@@ -29,7 +29,7 @@ class FFIGizmo extends BaseGizmo {
} }
void _onPickResult(DartEntityId entityId, int x, int y, Pointer<TView> view) { void _onPickResult(DartEntityId entityId, int x, int y, Pointer<TView> view) {
_callback?.call((entity: entityId, x: x, y: y)); _callback?.call((entity: entityId, x: x, y: y, depth: 0, fragX: 0, fragY: 0, fragZ: 0));
} }
/// ///
@@ -150,8 +150,15 @@ external void Viewer_setViewRenderable(
ffi.Int, ffi.Int,
ffi.Pointer< ffi.Pointer<
ffi.NativeFunction< ffi.NativeFunction<
ffi.Void Function(EntityId entityId, ffi.Int x, ffi.Int y, ffi.Void Function(
ffi.Pointer<TView> tView)>>)>(isLeaf: true) EntityId entityId,
ffi.Int x,
ffi.Int y,
ffi.Pointer<TView> tView,
ffi.Float depth,
ffi.Float fragX,
ffi.Float fragY,
ffi.Float fragZ)>>)>(isLeaf: true)
external void Viewer_pick( external void Viewer_pick(
ffi.Pointer<TViewer> viewer, ffi.Pointer<TViewer> viewer,
ffi.Pointer<TView> tView, ffi.Pointer<TView> tView,
@@ -159,11 +166,24 @@ external void Viewer_pick(
int y, int y,
ffi.Pointer< ffi.Pointer<
ffi.NativeFunction< ffi.NativeFunction<
ffi.Void Function(EntityId entityId, ffi.Int x, ffi.Int y, ffi.Void Function(
ffi.Pointer<TView> tView)>> EntityId entityId,
ffi.Int x,
ffi.Int y,
ffi.Pointer<TView> tView,
ffi.Float depth,
ffi.Float fragX,
ffi.Float fragY,
ffi.Float fragZ)>>
callback, callback,
); );
@ffi.Native<ffi.Bool Function(ffi.Pointer<TViewer>, EntityId)>(isLeaf: true)
external bool Viewer_isNonPickableEntity(
ffi.Pointer<TViewer> viewer,
int entityId,
);
@ffi.Native<ffi.Pointer<TEngine> Function(ffi.Pointer<TViewer>)>(isLeaf: true) @ffi.Native<ffi.Pointer<TEngine> Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external ffi.Pointer<TEngine> Viewer_getEngine( external ffi.Pointer<TEngine> Viewer_getEngine(
ffi.Pointer<TViewer> viewer, ffi.Pointer<TViewer> viewer,
@@ -418,23 +438,6 @@ external ffi.Pointer<TMaterialInstance> create_material_instance(
TMaterialKey materialConfig, TMaterialKey materialConfig,
); );
@ffi.Native<
ffi.Pointer<TMaterialInstance> Function(
ffi.Pointer<TSceneManager>)>(isLeaf: true)
external ffi.Pointer<TMaterialInstance> SceneManager_createUnlitMaterialInstance(
ffi.Pointer<TSceneManager> sceneManager,
);
@ffi.Native<
ffi.Pointer<TMaterialInstance> Function(
ffi.Pointer<TSceneManager>, ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TMaterialInstance>)>>)>(isLeaf: true)
external ffi.Pointer<TMaterialInstance> SceneManager_createUnlitMaterialInstanceRenderThread(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TMaterialInstance>)>>
onComplete
);
@ffi.Native< @ffi.Native<
ffi.Void Function(ffi.Pointer<TSceneManager>, ffi.Void Function(ffi.Pointer<TSceneManager>,
ffi.Pointer<TMaterialInstance>)>(isLeaf: true) ffi.Pointer<TMaterialInstance>)>(isLeaf: true)
@@ -618,6 +621,60 @@ external int get_bone(
int boneIndex, int boneIndex,
); );
@ffi.Native<
ffi.Pointer<TGizmo> Function(ffi.Pointer<TSceneManager>, ffi.Pointer<TView>,
ffi.Pointer<TScene>)>(isLeaf: true)
external ffi.Pointer<TGizmo> SceneManager_createGizmo(
ffi.Pointer<TSceneManager> tSceneManager,
ffi.Pointer<TView> tView,
ffi.Pointer<TScene> tScene,
);
@ffi.Native<
EntityId Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<ffi.Float>,
ffi.Int,
ffi.Pointer<ffi.Float>,
ffi.Int,
ffi.Pointer<ffi.Float>,
ffi.Int,
ffi.Pointer<ffi.Uint16>,
ffi.Int,
ffi.Int,
ffi.Pointer<TMaterialInstance>,
ffi.Bool)>(isLeaf: true)
external int SceneManager_createGeometry(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<ffi.Float> vertices,
int numVertices,
ffi.Pointer<ffi.Float> normals,
int numNormals,
ffi.Pointer<ffi.Float> uvs,
int numUvs,
ffi.Pointer<ffi.Uint16> indices,
int numIndices,
int primitiveType,
ffi.Pointer<TMaterialInstance> materialInstance,
bool keepData,
);
@ffi.Native<
ffi.Pointer<TMaterialInstance> Function(
ffi.Pointer<TSceneManager>)>(isLeaf: true)
external ffi.Pointer<TMaterialInstance>
SceneManager_createUnlitMaterialInstance(
ffi.Pointer<TSceneManager> sceneManager,
);
@ffi.Native<
ffi.Pointer<TMaterialInstance> Function(
ffi.Pointer<TSceneManager>)>(isLeaf: true)
external ffi.Pointer<TMaterialInstance>
SceneManager_createUnlitFixedSizeMaterialInstance(
ffi.Pointer<TSceneManager> sceneManager,
);
@ffi.Native< @ffi.Native<
ffi.Bool Function(ffi.Pointer<TSceneManager>, EntityId, ffi.Bool Function(ffi.Pointer<TSceneManager>, EntityId,
ffi.Pointer<ffi.Double>)>(isLeaf: true) ffi.Pointer<ffi.Double>)>(isLeaf: true)
@@ -956,35 +1013,6 @@ external void remove_animation_component(
int entityId, int entityId,
); );
@ffi.Native<
EntityId Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<ffi.Float>,
ffi.Int,
ffi.Pointer<ffi.Float>,
ffi.Int,
ffi.Pointer<ffi.Float>,
ffi.Int,
ffi.Pointer<ffi.Uint16>,
ffi.Int,
ffi.Int,
ffi.Pointer<TMaterialInstance>,
ffi.Bool)>(isLeaf: true)
external int SceneManager_createGeometry(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<ffi.Float> vertices,
int numVertices,
ffi.Pointer<ffi.Float> normals,
int numNormals,
ffi.Pointer<ffi.Float> uvs,
int numUvs,
ffi.Pointer<ffi.Uint16> indices,
int numIndices,
int primitiveType,
ffi.Pointer<TMaterialInstance> materialInstance,
bool keepData,
);
@ffi.Native<EntityId Function(ffi.Pointer<TSceneManager>, EntityId)>( @ffi.Native<EntityId Function(ffi.Pointer<TSceneManager>, EntityId)>(
isLeaf: true) isLeaf: true)
external int get_parent( external int get_parent(
@@ -1195,6 +1223,15 @@ external void MaterialInstance_setParameterFloat2(
double y, double y,
); );
@ffi.Native<
ffi.Void Function(ffi.Pointer<TMaterialInstance>, ffi.Pointer<ffi.Char>,
ffi.Double)>(isLeaf: true)
external void MaterialInstance_setParameterFloat(
ffi.Pointer<TMaterialInstance> materialInstance,
ffi.Pointer<ffi.Char> name,
double value,
);
@ffi.Native<TViewport Function(ffi.Pointer<TView>)>(isLeaf: true) @ffi.Native<TViewport Function(ffi.Pointer<TView>)>(isLeaf: true)
external TViewport View_getViewport( external TViewport View_getViewport(
ffi.Pointer<TView> view, ffi.Pointer<TView> view,
@@ -1527,6 +1564,38 @@ external void remove_skybox_render_thread(
ffi.Pointer<TViewer> viewer, ffi.Pointer<TViewer> viewer,
); );
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<ffi.Float>,
ffi.Int,
ffi.Pointer<ffi.Float>,
ffi.Int,
ffi.Pointer<ffi.Float>,
ffi.Int,
ffi.Pointer<ffi.Uint16>,
ffi.Int,
ffi.Int,
ffi.Pointer<TMaterialInstance>,
ffi.Bool,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>>)>(
isLeaf: true)
external void SceneManager_createGeometryRenderThread(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<ffi.Float> vertices,
int numVertices,
ffi.Pointer<ffi.Float> normals,
int numNormals,
ffi.Pointer<ffi.Float> uvs,
int numUvs,
ffi.Pointer<ffi.Uint16> indices,
int numIndices,
int primitiveType,
ffi.Pointer<TMaterialInstance> materialInstance,
bool keepData,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>> callback,
);
@ffi.Native< @ffi.Native<
ffi.Void Function( ffi.Void Function(
ffi.Pointer<TSceneManager>, ffi.Pointer<TSceneManager>,
@@ -1551,6 +1620,34 @@ external void SceneManager_loadGlbFromBufferRenderThread(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>> callback, ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>> callback,
); );
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(
ffi.Pointer<TMaterialInstance>)>>)>(isLeaf: true)
external void SceneManager_createUnlitMaterialInstanceRenderThread(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TMaterialInstance>)>>
callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(
ffi.Pointer<TMaterialInstance>)>>)>(isLeaf: true)
external void SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TMaterialInstance>)>>
callback,
);
@ffi.Native< @ffi.Native<
ffi.Void Function( ffi.Void Function(
ffi.Pointer<TSceneManager>, ffi.Pointer<TSceneManager>,
@@ -1751,38 +1848,6 @@ external void reset_to_rest_pose_render_thread(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback, ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
); );
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<ffi.Float>,
ffi.Int,
ffi.Pointer<ffi.Float>,
ffi.Int,
ffi.Pointer<ffi.Float>,
ffi.Int,
ffi.Pointer<ffi.Uint16>,
ffi.Int,
ffi.Int,
ffi.Pointer<TMaterialInstance>,
ffi.Bool,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>>)>(
isLeaf: true)
external void SceneManager_createGeometryRenderThread(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<ffi.Float> vertices,
int numVertices,
ffi.Pointer<ffi.Float> normals,
int numNormals,
ffi.Pointer<ffi.Float> uvs,
int numUvs,
ffi.Pointer<ffi.Uint16> indices,
int numIndices,
int primitiveType,
ffi.Pointer<TMaterialInstance> materialInstance,
bool keepData,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>> callback,
);
@ffi.Native< @ffi.Native<
ffi.Void Function( ffi.Void Function(
ffi.Pointer<TViewer>, ffi.Pointer<TViewer>,
@@ -2003,15 +2068,6 @@ void Camera_setProjection(
far, far,
); );
@ffi.Native<
ffi.Pointer<TGizmo> Function(ffi.Pointer<TEngine>, ffi.Pointer<TView>,
ffi.Pointer<TScene>)>(isLeaf: true)
external ffi.Pointer<TGizmo> Gizmo_new(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TView> tView,
ffi.Pointer<TScene> tScene,
);
@ffi.Native< @ffi.Native<
ffi.Void Function(ffi.Pointer<TGizmo>, ffi.Uint32, ffi.Uint32, ffi.Void Function(ffi.Pointer<TGizmo>, ffi.Uint32, ffi.Uint32,
GizmoPickCallback)>(isLeaf: true) GizmoPickCallback)>(isLeaf: true)
@@ -84,7 +84,7 @@ class ThermionViewerFFI extends ThermionViewer {
_onPickResultCallable = NativeCallable< _onPickResultCallable = NativeCallable<
Void Function(EntityId entityId, Int x, Int y, Void Function(EntityId entityId, Int x, Int y,
Pointer<TView> view)>.listener(_onPickResult); Pointer<TView> view, Float depth, Float fragX, Float fragY, Float fragZ)>.listener(_onPickResult);
_initialize(); _initialize();
} }
@@ -1509,26 +1509,26 @@ class ThermionViewerFFI extends ThermionViewer {
} }
void _onPickResult( void _onPickResult(
ThermionEntity entityId, int x, int y, Pointer<TView> viewPtr) async { ThermionEntity entityId, int x, int y, Pointer<TView> viewPtr, double depth, double fragX, double fragY, double fragZ) async {
final view = FFIView(viewPtr, _viewer!); final view = FFIView(viewPtr, _viewer!);
final viewport = await view.getViewport(); final viewport = await view.getViewport();
_pickResultController _pickResultController
.add((entity: entityId, x: x.ceil(), y: (viewport.height - y).ceil())); .add((entity: entityId, x: x, y: (viewport.height - y), depth: depth, fragX: fragX, fragY: viewport.height - fragY, fragZ: fragZ ));
} }
late NativeCallable< late NativeCallable<
Void Function(EntityId entityId, Int x, Int y, Pointer<TView> view)> Void Function(EntityId entityId, Int x, Int y, Pointer<TView> view, Float depth, Float fragX, Float fragY, Float fragZ)>
_onPickResultCallable; _onPickResultCallable;
/// ///
/// ///
/// ///
@override @override
void pick(int x, int y) async { Future pick(int x, int y) async {
final view = (await getViewAt(0)) as FFIView; final view = (await getViewAt(0)) as FFIView;
var viewport = await view.getViewport(); var viewport = await view.getViewport();
y = (viewport.height - y).ceil(); y = viewport.height - y;
Viewer_pick( Viewer_pick(
_viewer!, view.view, x, y, _onPickResultCallable.nativeFunction); _viewer!, view.view, x, y, _onPickResultCallable.nativeFunction);
} }
@@ -2035,6 +2035,9 @@ class ThermionViewerFFI extends ThermionViewer {
destroy_material_instance(_sceneManager!, materialInstance._pointer); destroy_material_instance(_sceneManager!, materialInstance._pointer);
} }
///
///
///
Future<ThermionFFIMaterialInstance> createUnlitMaterialInstance() async { Future<ThermionFFIMaterialInstance> createUnlitMaterialInstance() async {
var instance = await withPointerCallback<TMaterialInstance>((cb) { var instance = await withPointerCallback<TMaterialInstance>((cb) {
SceneManager_createUnlitMaterialInstanceRenderThread(_sceneManager!, cb); SceneManager_createUnlitMaterialInstanceRenderThread(_sceneManager!, cb);
@@ -2045,6 +2048,19 @@ class ThermionViewerFFI extends ThermionViewer {
return ThermionFFIMaterialInstance(instance); return ThermionFFIMaterialInstance(instance);
} }
///
///
///
Future<ThermionFFIMaterialInstance> createUnlitFixedSizeMaterialInstance() async {
var instance = await withPointerCallback<TMaterialInstance>((cb) {
SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread(_sceneManager!, cb);
});
if (instance == nullptr) {
throw Exception("Failed to create material instance");
}
return ThermionFFIMaterialInstance(instance);
}
@override @override
Future setMaterialPropertyInt(ThermionEntity entity, String propertyName, Future setMaterialPropertyInt(ThermionEntity entity, String propertyName,
int materialIndex, int value) { int materialIndex, int value) {
@@ -2163,7 +2179,7 @@ class ThermionViewerFFI extends ThermionViewer {
Future<Gizmo> createGizmo(FFIView view) async { Future<Gizmo> createGizmo(FFIView view) async {
var view = (await getViewAt(0)) as FFIView; var view = (await getViewAt(0)) as FFIView;
var scene = View_getScene(view.view); var scene = View_getScene(view.view);
final gizmo = Gizmo_new(Viewer_getEngine(_viewer!), view.view, scene); final gizmo = SceneManager_createGizmo(_sceneManager!, view.view, scene);
return FFIGizmo(gizmo, this); return FFIGizmo(gizmo, this);
} }
} }
@@ -2194,6 +2210,12 @@ class ThermionFFIMaterialInstance extends MaterialInstance {
MaterialInstance_setParameterFloat2( MaterialInstance_setParameterFloat2(
_pointer, name.toNativeUtf8().cast<Char>(), x, y); _pointer, name.toNativeUtf8().cast<Char>(), x, y);
} }
@override
Future setParameterFloat(String name, double value) async {
MaterialInstance_setParameterFloat(
_pointer, name.toNativeUtf8().cast<Char>(), value);
}
} }
class FFIRenderTarget extends RenderTarget { class FFIRenderTarget extends RenderTarget {
@@ -2,6 +2,7 @@ abstract class MaterialInstance {
Future setDepthWriteEnabled(bool enabled); Future setDepthWriteEnabled(bool enabled);
Future setDepthCullingEnabled(bool enabled); Future setDepthCullingEnabled(bool enabled);
Future setParameterFloat2(String name, double x, double y); Future setParameterFloat2(String name, double x, double y);
Future setParameterFloat(String name, double x);
} }
enum AlphaMode { OPAQUE, MASK, BLEND } enum AlphaMode { OPAQUE, MASK, BLEND }
@@ -1,5 +1,17 @@
// "picking" means clicking/tapping on the viewport, and unprojecting the X/Y coordinate to determine whether any renderable entities were present at those coordinates.
import '../../viewer.dart'; import '../../viewer.dart';
typedef FilamentPickResult = ({ThermionEntity entity, int x, int y}); /// The result of a picking operation (see [ThermionViewer.pick] for more details).
/// [x] and [y] refer to the original screen coordinates used to call [pick]; this should
/// match the values of [fragX] and [fragY]. [fragZ] is the depth value in screen coordinates,
/// [depth] is the value in the depth buffer (i.e. fragZ = 1.0 - depth).
///
typedef FilamentPickResult = ({
ThermionEntity entity,
int x,
int y,
double depth,
double fragX,
double fragY,
double fragZ
});
typedef PickResult = FilamentPickResult; typedef PickResult = FilamentPickResult;
@@ -695,7 +695,7 @@ abstract class ThermionViewer {
/// This is asynchronous and will require 2-3 frames to complete - subscribe to the [pickResult] stream to receive the results of this method. /// This is asynchronous and will require 2-3 frames to complete - subscribe to the [pickResult] stream to receive the results of this method.
/// [x] and [y] must be in local logical coordinates (i.e. where 0,0 is at top-left of the ThermionWidget). /// [x] and [y] must be in local logical coordinates (i.e. where 0,0 is at top-left of the ThermionWidget).
/// ///
void pick(int x, int y); Future pick(int x, int y);
/// ///
/// Retrieves the name assigned to the given ThermionEntity (usually corresponds to the glTF mesh name). /// Retrieves the name assigned to the given ThermionEntity (usually corresponds to the glTF mesh name).
@@ -796,14 +796,23 @@ abstract class ThermionViewer {
Future<Aabb2> getViewportBoundingBox(ThermionEntity entity); Future<Aabb2> getViewportBoundingBox(ThermionEntity entity);
/// ///
/// Filament assigns renderables to a numeric layer. /// Toggles the visibility of the respective layer.
/// We place all scene assets in layer 0 (enabled by default), gizmos in layer 1 (enabled by default), world grid in layer 2 (disabled by default).
/// Use this method to toggle visibility of the respective layer.
/// ///
Future setLayerVisibility(int layer, bool visible); Future setLayerVisibility(int layer, bool visible);
/// ///
/// Assigns [entity] to visibility layer [layer]. /// All renderable entities are assigned a layer mask.
///
/// By calling [setLayerVisibility], all renderable entities allocated to
/// the given layer can be efficiently hidden/revealed.
///
/// By default, all renderable entities are assigned to layer 0 (and this
/// layer is enabled by default). Call [setVisibilityLayer] to change the
/// layer for the specified entity.
///
/// Note that we currently also assign gizmos to layer 1 (enabled by default)
/// and the world grid to layer 2 (disabled by default). We suggest you avoid
/// using these layers.
/// ///
Future setVisibilityLayer(ThermionEntity entity, int layer); Future setVisibilityLayer(ThermionEntity entity, int layer);
@@ -886,6 +895,11 @@ abstract class ThermionViewer {
/// ///
Future<MaterialInstance> createUnlitMaterialInstance(); Future<MaterialInstance> createUnlitMaterialInstance();
///
///
///
Future<MaterialInstance> createUnlitFixedSizeMaterialInstance();
/// ///
/// ///
/// ///
@@ -21,4 +21,10 @@ class ThermionWasmMaterialInstance extends MaterialInstance {
// TODO: implement setParameterFloat2 // TODO: implement setParameterFloat2
throw UnimplementedError(); throw UnimplementedError();
} }
@override
Future setParameterFloat(String name, double x) {
// TODO: implement setParameterFloat
throw UnimplementedError();
}
} }
View File
@@ -98,7 +98,15 @@ namespace thermion
void clearBackgroundImage(); void clearBackgroundImage();
void setBackgroundImagePosition(float x, float y, bool clamp, uint32_t width, uint32_t height); void setBackgroundImagePosition(float x, float y, bool clamp, uint32_t width, uint32_t height);
void pick(View *view, uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y, View *view)); typedef void (*PickCallback)(EntityId entityId, int x, int y, View *view, float depth, float fragX, float fragY, float fragZ);
///
/// Returns true if the specified entity is a gizmo, grid or background image entity.
///
bool isNonPickableEntity(EntityId entityId);
void pick(View *view, uint32_t x, uint32_t y, PickCallback callback);
Engine* getEngine() { Engine* getEngine() {
return _engine; return _engine;
} }
+4 -4
View File
@@ -17,8 +17,6 @@
#include <filament/IndexBuffer.h> #include <filament/IndexBuffer.h>
#include <filament/InstanceBuffer.h> #include <filament/InstanceBuffer.h>
#include "material/gizmo.h"
#include "ThermionDartApi.h" #include "ThermionDartApi.h"
namespace thermion { namespace thermion {
@@ -31,7 +29,7 @@ class Gizmo {
enum Axis { X, Y, Z}; enum Axis { X, Y, Z};
public: public:
Gizmo(Engine *engine, View *view, Scene *scene); Gizmo(Engine *engine, View *view, Scene *scene, Material* material);
~Gizmo(); ~Gizmo();
typedef void (*PickCallback)(EntityId entityId, uint32_t x, uint32_t y, View *view); typedef void (*PickCallback)(EntityId entityId, uint32_t x, uint32_t y, View *view);
@@ -91,8 +89,10 @@ class Gizmo {
Engine *_engine; Engine *_engine;
Scene *_scene; Scene *_scene;
View *_view; View *_view;
utils::Entity _entities[7] = { utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity() };
Material* _material; Material* _material;
utils::Entity _entities[7] = { utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity() };
MaterialInstance* _materialInstances[7]; MaterialInstance* _materialInstances[7];
math::float4 inactiveColors[3] { math::float4 inactiveColors[3] {
math::float4 { 1.0f, 0.0f, 0.0f, 0.5f }, math::float4 { 1.0f, 0.0f, 0.0f, 0.5f },
@@ -19,9 +19,6 @@
#include <filament/IndexBuffer.h> #include <filament/IndexBuffer.h>
#include <filament/InstanceBuffer.h> #include <filament/InstanceBuffer.h>
#include "material/gizmo.h"
namespace thermion { namespace thermion {
using namespace filament; using namespace filament;
+10 -3
View File
@@ -19,16 +19,17 @@
#include <filament/InstanceBuffer.h> #include <filament/InstanceBuffer.h>
#include <utils/NameComponentManager.h> #include <utils/NameComponentManager.h>
#include "CustomGeometry.hpp" #include "tsl/robin_map.h"
#include "APIBoundaryTypes.h" #include "APIBoundaryTypes.h"
#include "CustomGeometry.hpp"
#include "Gizmo.hpp"
#include "GridOverlay.hpp" #include "GridOverlay.hpp"
#include "ResourceBuffer.hpp" #include "ResourceBuffer.hpp"
#include "components/CollisionComponentManager.hpp" #include "components/CollisionComponentManager.hpp"
#include "components/AnimationComponentManager.hpp" #include "components/AnimationComponentManager.hpp"
#include "tsl/robin_map.h"
namespace thermion namespace thermion
{ {
@@ -287,6 +288,8 @@ namespace thermion
return _ubershaderProvider; return _ubershaderProvider;
} }
MaterialInstance* createUnlitFixedSizeMaterialInstance();
MaterialInstance* createUnlitMaterialInstance(); MaterialInstance* createUnlitMaterialInstance();
void setVisibilityLayer(EntityId entityId, int layer); void setVisibilityLayer(EntityId entityId, int layer);
@@ -298,6 +301,8 @@ namespace thermion
size_t getCameraCount(); size_t getCameraCount();
Camera* getCameraAt(size_t index); Camera* getCameraAt(size_t index);
Gizmo *createGizmo(View *view, Scene *scene);
bool isGizmoEntity(utils::Entity entity); bool isGizmoEntity(utils::Entity entity);
@@ -321,6 +326,8 @@ namespace thermion
std::mutex _stencilMutex; std::mutex _stencilMutex;
std::vector<MaterialInstance*> _materialInstances; std::vector<MaterialInstance*> _materialInstances;
Material* _gizmoMaterial = nullptr;
utils::NameComponentManager *_ncm; utils::NameComponentManager *_ncm;
tsl::robin_map< tsl::robin_map<
-1
View File
@@ -10,7 +10,6 @@ extern "C"
typedef void (*GizmoPickCallback)(EntityId entityId, uint32_t x, uint32_t y, TView* view); typedef void (*GizmoPickCallback)(EntityId entityId, uint32_t x, uint32_t y, TView* view);
EMSCRIPTEN_KEEPALIVE TGizmo* Gizmo_new(TEngine *tEngine, TView *tView, TScene *tScene);
EMSCRIPTEN_KEEPALIVE void Gizmo_pick(TGizmo *tGizmo, uint32_t x, uint32_t y, GizmoPickCallback callback); EMSCRIPTEN_KEEPALIVE void Gizmo_pick(TGizmo *tGizmo, uint32_t x, uint32_t y, GizmoPickCallback callback);
EMSCRIPTEN_KEEPALIVE void Gizmo_setVisibility(TGizmo *tGizmo, bool visible); EMSCRIPTEN_KEEPALIVE void Gizmo_setVisibility(TGizmo *tGizmo, bool visible);
@@ -85,7 +85,8 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void Viewer_setMainCamera(TViewer *tViewer, TView *tView); EMSCRIPTEN_KEEPALIVE void Viewer_setMainCamera(TViewer *tViewer, TView *tView);
EMSCRIPTEN_KEEPALIVE TSwapChain* Viewer_getSwapChainAt(TViewer *tViewer, int index); EMSCRIPTEN_KEEPALIVE TSwapChain* Viewer_getSwapChainAt(TViewer *tViewer, int index);
EMSCRIPTEN_KEEPALIVE void Viewer_setViewRenderable(TViewer *viewer, TSwapChain *swapChain, TView* view, bool renderable); EMSCRIPTEN_KEEPALIVE void Viewer_setViewRenderable(TViewer *viewer, TSwapChain *swapChain, TView* view, bool renderable);
EMSCRIPTEN_KEEPALIVE void Viewer_pick(TViewer *viewer, TView* tView, int x, int y, void (*callback)(EntityId entityId, int x, int y, TView *tView)); EMSCRIPTEN_KEEPALIVE void Viewer_pick(TViewer *viewer, TView* tView, int x, int y, void (*callback)(EntityId entityId, int x, int y, TView *tView, float depth, float fragX, float fragY, float fragZ));
EMSCRIPTEN_KEEPALIVE bool Viewer_isNonPickableEntity(TViewer *viewer, EntityId entityId);
// Engine // Engine
EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer* viewer); EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer* viewer);
@@ -197,6 +198,7 @@ extern "C"
int skinIndex, int skinIndex,
int boneIndex); int boneIndex);
EMSCRIPTEN_KEEPALIVE TGizmo* SceneManager_createGizmo(TSceneManager *tSceneManager, TView *tView, TScene *tScene);
EMSCRIPTEN_KEEPALIVE EntityId SceneManager_createGeometry( EMSCRIPTEN_KEEPALIVE EntityId SceneManager_createGeometry(
TSceneManager *sceneManager, TSceneManager *sceneManager,
float *vertices, float *vertices,
@@ -211,6 +213,7 @@ extern "C"
TMaterialInstance *materialInstance, TMaterialInstance *materialInstance,
bool keepData); bool keepData);
EMSCRIPTEN_KEEPALIVE TMaterialInstance *SceneManager_createUnlitMaterialInstance(TSceneManager *sceneManager); EMSCRIPTEN_KEEPALIVE TMaterialInstance *SceneManager_createUnlitMaterialInstance(TSceneManager *sceneManager);
EMSCRIPTEN_KEEPALIVE TMaterialInstance *SceneManager_createUnlitFixedSizeMaterialInstance(TSceneManager *sceneManager);
EMSCRIPTEN_KEEPALIVE bool SceneManager_setTransform(TSceneManager *sceneManager, EntityId entityId, const double *const transform); EMSCRIPTEN_KEEPALIVE bool SceneManager_setTransform(TSceneManager *sceneManager, EntityId entityId, const double *const transform);
EMSCRIPTEN_KEEPALIVE void SceneManager_queueTransformUpdates(TSceneManager *sceneManager, EntityId* entities, const double* const transforms, int numEntities); EMSCRIPTEN_KEEPALIVE void SceneManager_queueTransformUpdates(TSceneManager *sceneManager, EntityId* entities, const double* const transforms, int numEntities);
EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_findCameraByName(TSceneManager* tSceneManager, EntityId entity, const char* name); EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_findCameraByName(TSceneManager* tSceneManager, EntityId entity, const char* name);
@@ -294,6 +297,7 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthWrite(TMaterialInstance* materialInstance, bool enabled); EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthWrite(TMaterialInstance* materialInstance, bool enabled);
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthCulling(TMaterialInstance* materialInstance, bool enabled); EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthCulling(TMaterialInstance* materialInstance, bool enabled);
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat2(TMaterialInstance* materialInstance, const char* name, double x, double y); EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat2(TMaterialInstance* materialInstance, const char* name, double x, double y);
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat(TMaterialInstance* materialInstance, const char* name, double value);
#ifdef __cplusplus #ifdef __cplusplus
@@ -67,6 +67,7 @@ extern "C"
void (*callback)(EntityId)); void (*callback)(EntityId));
EMSCRIPTEN_KEEPALIVE void SceneManager_loadGlbFromBufferRenderThread(TSceneManager *sceneManager, const uint8_t *const data, size_t length, int numInstances, bool keepData, int priority, int layer, bool loadResourcesAsync, void (*callback)(EntityId)); EMSCRIPTEN_KEEPALIVE void SceneManager_loadGlbFromBufferRenderThread(TSceneManager *sceneManager, const uint8_t *const data, size_t length, int numInstances, bool keepData, int priority, int layer, bool loadResourcesAsync, void (*callback)(EntityId));
EMSCRIPTEN_KEEPALIVE void SceneManager_createUnlitMaterialInstanceRenderThread(TSceneManager *sceneManager, void (*callback)(TMaterialInstance*)); EMSCRIPTEN_KEEPALIVE void SceneManager_createUnlitMaterialInstanceRenderThread(TSceneManager *sceneManager, void (*callback)(TMaterialInstance*));
EMSCRIPTEN_KEEPALIVE void SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread(TSceneManager *sceneManager, void (*callback)(TMaterialInstance*));
EMSCRIPTEN_KEEPALIVE void load_glb_render_thread(TSceneManager *sceneManager, const char *assetPath, int numInstances, bool keepData, void (*callback)(EntityId)); EMSCRIPTEN_KEEPALIVE void load_glb_render_thread(TSceneManager *sceneManager, const char *assetPath, int numInstances, bool keepData, void (*callback)(EntityId));
EMSCRIPTEN_KEEPALIVE void load_gltf_render_thread(TSceneManager *sceneManager, const char *assetPath, const char *relativePath, bool keepData, void (*callback)(EntityId)); EMSCRIPTEN_KEEPALIVE void load_gltf_render_thread(TSceneManager *sceneManager, const char *assetPath, const char *relativePath, bool keepData, void (*callback)(EntityId));
EMSCRIPTEN_KEEPALIVE void create_instance_render_thread(TSceneManager *sceneManager, EntityId entityId, void (*callback)(EntityId)); EMSCRIPTEN_KEEPALIVE void create_instance_render_thread(TSceneManager *sceneManager, EntityId entityId, void (*callback)(EntityId));
@@ -11,8 +11,6 @@
#pragma comment(lib, "bluevk.lib") #pragma comment(lib, "bluevk.lib")
#pragma comment(lib, "bluegl.lib") #pragma comment(lib, "bluegl.lib")
#pragma comment(lib, "backend.lib") #pragma comment(lib, "backend.lib")
#pragma comment(lib, "filameshio.lib")
#pragma comment(lib, "viewer.lib")
#pragma comment(lib, "filamat.lib") #pragma comment(lib, "filamat.lib")
#pragma comment(lib, "geometry.lib") #pragma comment(lib, "geometry.lib")
#pragma comment(lib, "utils.lib") #pragma comment(lib, "utils.lib")
@@ -1,12 +0,0 @@
.global GIZMO_GIZMO_OFFSET;
.global GIZMO_GIZMO_SIZE;
.global GIZMO_PACKAGE
.section .rodata
GIZMO_PACKAGE:
.incbin "gizmo.bin"
GIZMO_GIZMO_OFFSET:
.int 0
GIZMO_GIZMO_SIZE:
.int 27809
@@ -1,12 +0,0 @@
.global _GIZMO_GIZMO_OFFSET;
.global _GIZMO_GIZMO_SIZE;
.global _GIZMO_PACKAGE
.section __TEXT,__const
_GIZMO_PACKAGE:
.incbin "gizmo.bin"
_GIZMO_GIZMO_OFFSET:
.int 0
_GIZMO_GIZMO_SIZE:
.int 27809
Binary file not shown.
@@ -1,13 +0,0 @@
#ifndef GIZMO_H_
#define GIZMO_H_
#include <stdint.h>
extern "C" {
extern const uint8_t GIZMO_PACKAGE[];
extern int GIZMO_GIZMO_OFFSET;
extern int GIZMO_GIZMO_SIZE;
}
#define GIZMO_GIZMO_DATA (GIZMO_PACKAGE + GIZMO_GIZMO_OFFSET)
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,12 @@
.global UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_OFFSET;
.global UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE;
.global UNLIT_FIXED_SIZE_PACKAGE
.section .rodata
UNLIT_FIXED_SIZE_PACKAGE:
.incbin "unlit_fixed_size.bin"
UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_OFFSET:
.int 0
UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE:
.int 28235
@@ -0,0 +1,12 @@
.global _UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_OFFSET;
.global _UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE;
.global _UNLIT_FIXED_SIZE_PACKAGE
.section __TEXT,__const
_UNLIT_FIXED_SIZE_PACKAGE:
.incbin "unlit_fixed_size.bin"
_UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_OFFSET:
.int 0
_UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE:
.int 28235
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,13 @@
#ifndef UNLIT_FIXED_SIZE_H_
#define UNLIT_FIXED_SIZE_H_
#include <stdint.h>
extern "C" {
extern const uint8_t UNLIT_FIXED_SIZE_PACKAGE[];
extern int UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_OFFSET;
extern int UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE;
}
#define UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_DATA (UNLIT_FIXED_SIZE_PACKAGE + UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_OFFSET)
#endif
+9 -16
View File
@@ -1191,23 +1191,16 @@ namespace thermion
return _engine->getCameraComponent(Entity::import(entity)); return _engine->getCameraComponent(Entity::import(entity));
} }
void FilamentViewer::pick(View *view, uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y, View *view)) bool FilamentViewer::isNonPickableEntity(EntityId entityId) {
auto renderable = Entity::import(entityId);
return _sceneManager->isGizmoEntity(renderable) || renderable == _imageEntity || renderable == _sceneManager->_gridOverlay->sphere() || _sceneManager->_gridOverlay->grid();
}
void FilamentViewer::pick(View *view, uint32_t x, uint32_t y, PickCallback callback)
{ {
view->pick(x, y, [=](filament::View::PickingQueryResult const &result) { view->pick(x, y, [=](filament::View::PickingQueryResult const &result) {
callback(Entity::smuggle(result.renderable), x, y, view, result.depth, result.fragCoords.x, result.fragCoords.y, result.fragCoords.z);
if(_sceneManager->isGizmoEntity(result.renderable)) { });
Log("Gizmo entity, ignoring");
return;
}
std::unordered_set<Entity, Entity::Hasher> nonPickableEntities = {
_imageEntity,
_sceneManager->_gridOverlay->sphere(),
_sceneManager->_gridOverlay->grid(),
};
if (nonPickableEntities.find(result.renderable) == nonPickableEntities.end()) {
callback(Entity::smuggle(result.renderable), x, y, view);
} });
} }
void FilamentViewer::unprojectTexture(EntityId entityId, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight) void FilamentViewer::unprojectTexture(EntityId entityId, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight)
+4 -9
View File
@@ -7,31 +7,26 @@
#include <filament/TransformManager.h> #include <filament/TransformManager.h>
#include <gltfio/math.h> #include <gltfio/math.h>
#include "SceneManager.hpp" #include "SceneManager.hpp"
#include "material/gizmo.h" #include "material/unlit_fixed_size.h"
#include "Log.hpp" #include "Log.hpp"
namespace thermion { namespace thermion {
using namespace filament::gltfio; using namespace filament::gltfio;
Gizmo::Gizmo(Engine *engine, View *view, Scene* scene) : _engine(engine), _view(view), _scene(scene) Gizmo::Gizmo(Engine *engine, View *view, Scene* scene, Material* material) : _engine(engine), _view(view), _scene(scene), _material(material)
{ {
auto &entityManager = EntityManager::get(); auto &entityManager = EntityManager::get();
auto &transformManager = _engine->getTransformManager(); auto &transformManager = _engine->getTransformManager();
_material =
Material::Builder()
.package(GIZMO_GIZMO_DATA, GIZMO_GIZMO_SIZE)
.build(*_engine);
// First, create the black cube at the center // First, create the black cube at the center
// The axes widgets will be parented to this entity // The axes widgets will be parented to this entity
_entities[3] = entityManager.create(); _entities[3] = entityManager.create();
_materialInstances[3] = _material->createInstance(); _materialInstances[3] = _material->createInstance();
_materialInstances[3]->setParameter("color", math::float4{0.0f, 0.0f, 0.0f, 1.0f}); // Black color _materialInstances[3]->setParameter("baseColorFactor", math::float4{0.0f, 0.0f, 0.0f, 1.0f}); // Black color
// Create center cube vertices // Create center cube vertices
float centerCubeSize = 0.01f; float centerCubeSize = 0.01f;
@@ -160,7 +155,7 @@ Gizmo::Gizmo(Engine *engine, View *view, Scene* scene) : _engine(engine), _view(
break; break;
} }
_materialInstances[i]->setParameter("color", baseColor); _materialInstances[i]->setParameter("baseColorFactor", baseColor);
RenderableManager::Builder(1) RenderableManager::Builder(1)
.boundingBox({{-arrowWidth, -arrowWidth, 0}, .boundingBox({{-arrowWidth, -arrowWidth, 0},
+192 -147
View File
@@ -33,9 +33,12 @@
#include "CustomGeometry.hpp" #include "CustomGeometry.hpp"
#include "UnprojectTexture.hpp" #include "UnprojectTexture.hpp"
#include "Gizmo.hpp"
extern "C" extern "C"
{ {
#include "material/image.h" #include "material/image.h"
#include "material/unlit_fixed_size.h"
} }
namespace thermion namespace thermion
@@ -52,9 +55,8 @@ namespace thermion
Engine *engine, Engine *engine,
Scene *scene, Scene *scene,
const char *uberArchivePath, const char *uberArchivePath,
Camera *mainCamera) Camera *mainCamera)
: : _resourceLoaderWrapper(resourceLoaderWrapper),
_resourceLoaderWrapper(resourceLoaderWrapper),
_engine(engine), _engine(engine),
_scene(scene), _scene(scene),
_mainCamera(mainCamera) _mainCamera(mainCamera)
@@ -103,17 +105,22 @@ namespace thermion
_scene->addEntity(_gridOverlay->sphere()); _scene->addEntity(_gridOverlay->sphere());
_scene->addEntity(_gridOverlay->grid()); _scene->addEntity(_gridOverlay->grid());
_gizmoMaterial =
Material::Builder()
.package(UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_DATA, UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE)
.build(*_engine);
} }
SceneManager::~SceneManager() SceneManager::~SceneManager()
{ {
for(auto camera : _cameras) { for (auto camera : _cameras)
{
auto entity = camera->getEntity(); auto entity = camera->getEntity();
_engine->destroyCameraComponent(entity); _engine->destroyCameraComponent(entity);
_engine->getEntityManager().destroy(entity); _engine->getEntityManager().destroy(entity);
} }
_cameras.clear(); _cameras.clear();
_gridOverlay->destroy(); _gridOverlay->destroy();
destroyAll(); destroyAll();
@@ -131,8 +138,14 @@ namespace thermion
AssetLoader::destroy(&_assetLoader); AssetLoader::destroy(&_assetLoader);
} }
bool SceneManager::isGizmoEntity(Entity entity) { Gizmo *SceneManager::createGizmo(View *view, Scene *scene)
return false; // TODO {
return new Gizmo(_engine, view, scene, _gizmoMaterial);
}
bool SceneManager::isGizmoEntity(Entity entity)
{
return false; // TODO
} }
int SceneManager::getInstanceCount(EntityId entityId) int SceneManager::getInstanceCount(EntityId entityId)
@@ -246,15 +259,16 @@ namespace thermion
return eid; return eid;
} }
void SceneManager::setVisibilityLayer(EntityId entityId, int layer) { void SceneManager::setVisibilityLayer(EntityId entityId, int layer)
auto& rm = _engine->getRenderableManager(); {
auto &rm = _engine->getRenderableManager();
auto renderable = rm.getInstance(utils::Entity::import(entityId)); auto renderable = rm.getInstance(utils::Entity::import(entityId));
if(!renderable.isValid()) { if (!renderable.isValid())
{
Log("Warning: no renderable found"); Log("Warning: no renderable found");
} }
rm.setLayerMask(renderable, 0xFF, 1u << layer); rm.setLayerMask(renderable, 0xFF, 1u << layer);
} }
EntityId SceneManager::loadGlbFromBuffer(const uint8_t *data, size_t length, int numInstances, bool keepData, int priority, int layer, bool loadResourcesAsync) EntityId SceneManager::loadGlbFromBuffer(const uint8_t *data, size_t length, int numInstances, bool keepData, int priority, int layer, bool loadResourcesAsync)
@@ -281,11 +295,13 @@ namespace thermion
_scene->addEntities(asset->getEntities(), entityCount); _scene->addEntities(asset->getEntities(), entityCount);
auto & rm = _engine->getRenderableManager(); auto &rm = _engine->getRenderableManager();
for(int i=0; i < entityCount; i++) { for (int i = 0; i < entityCount; i++)
{
auto instance = rm.getInstance(asset->getEntities()[i]); auto instance = rm.getInstance(asset->getEntities()[i]);
if(!instance.isValid()) { if (!instance.isValid())
{
Log("No valid renderable for entity"); Log("No valid renderable for entity");
continue; continue;
} }
@@ -304,13 +320,16 @@ namespace thermion
_gltfResourceLoader->asyncUpdateLoad(); _gltfResourceLoader->asyncUpdateLoad();
} }
#else #else
if(loadResourcesAsync) { if (loadResourcesAsync)
{
if (!_gltfResourceLoader->asyncBeginLoad(asset)) if (!_gltfResourceLoader->asyncBeginLoad(asset))
{ {
Log("Unknown error loading glb asset"); Log("Unknown error loading glb asset");
return 0; return 0;
} }
} else { }
else
{
if (!_gltfResourceLoader->loadResources(asset)) if (!_gltfResourceLoader->loadResources(asset))
{ {
Log("Unknown error loading glb asset"); Log("Unknown error loading glb asset");
@@ -539,11 +558,13 @@ namespace thermion
asset.second->getLightEntityCount()); asset.second->getLightEntityCount());
_assetLoader->destroyAsset(asset.second); _assetLoader->destroyAsset(asset.second);
} }
for(auto *texture : _textures) { for (auto *texture : _textures)
{
_engine->destroy(texture); _engine->destroy(texture);
} }
for(auto *materialInstance : _materialInstances) { for (auto *materialInstance : _materialInstances)
{
_engine->destroy(materialInstance); _engine->destroy(materialInstance);
} }
@@ -661,7 +682,6 @@ namespace thermion
auto entity = Entity::import(entityId); auto entity = Entity::import(entityId);
if (_animationComponentManager->hasComponent(entity)) if (_animationComponentManager->hasComponent(entity))
{ {
_animationComponentManager->removeComponent(entity); _animationComponentManager->removeComponent(entity);
@@ -674,7 +694,8 @@ namespace thermion
_scene->remove(entity); _scene->remove(entity);
if(isGeometryEntity(entityId)) { if (isGeometryEntity(entityId))
{
return; return;
} }
@@ -1412,7 +1433,7 @@ namespace thermion
return texture; return texture;
} }
bool SceneManager::applyTexture(EntityId entityId, Texture *texture, const char* parameterName, int materialIndex) bool SceneManager::applyTexture(EntityId entityId, Texture *texture, const char *parameterName, int materialIndex)
{ {
auto entity = Entity::import(entityId); auto entity = Entity::import(entityId);
@@ -1446,10 +1467,12 @@ namespace thermion
return true; return true;
} }
void SceneManager::destroyTexture(Texture* texture) { void SceneManager::destroyTexture(Texture *texture)
if(_textures.find(texture) == _textures.end()) { {
if (_textures.find(texture) == _textures.end())
{
Log("Warning: couldn't find texture"); Log("Warning: couldn't find texture");
} }
_textures.erase(texture); _textures.erase(texture);
_engine->destroy(texture); _engine->destroy(texture);
} }
@@ -1904,7 +1927,7 @@ namespace thermion
tm.setTransform(transformInstance, newTransform); tm.setTransform(transformInstance, newTransform);
} }
void SceneManager::queueRelativePositionUpdateFromViewportVector(View* view, EntityId entityId, float viewportCoordX, float viewportCoordY) void SceneManager::queueRelativePositionUpdateFromViewportVector(View *view, EntityId entityId, float viewportCoordX, float viewportCoordY)
{ {
// Get the camera and viewport // Get the camera and viewport
const auto &camera = view->getCamera(); const auto &camera = view->getCamera();
@@ -1941,14 +1964,14 @@ namespace thermion
auto entityPlaneInWorldSpace = camera.getModelMatrix() * entityPlaneInCameraSpace; auto entityPlaneInWorldSpace = camera.getModelMatrix() * entityPlaneInCameraSpace;
// Queue the position update (as a relative movement) // Queue the position update (as a relative movement)
} }
void SceneManager::queueTransformUpdates(EntityId* entities, math::mat4* transforms, int numEntities) void SceneManager::queueTransformUpdates(EntityId *entities, math::mat4 *transforms, int numEntities)
{ {
std::lock_guard lock(_mutex); std::lock_guard lock(_mutex);
for(int i= 0; i < numEntities; i++) { for (int i = 0; i < numEntities; i++)
{
auto entity = entities[i]; auto entity = entities[i];
const auto &pos = _transformUpdates.find(entity); const auto &pos = _transformUpdates.find(entity);
if (pos == _transformUpdates.end()) if (pos == _transformUpdates.end())
@@ -2279,112 +2302,117 @@ namespace thermion
} }
} }
EntityId SceneManager::createGeometry( EntityId SceneManager::createGeometry(
float *vertices, float *vertices,
uint32_t numVertices, uint32_t numVertices,
float *normals, float *normals,
uint32_t numNormals, uint32_t numNormals,
float *uvs, float *uvs,
uint32_t numUvs, uint32_t numUvs,
uint16_t *indices, uint16_t *indices,
uint32_t numIndices, uint32_t numIndices,
filament::RenderableManager::PrimitiveType primitiveType, filament::RenderableManager::PrimitiveType primitiveType,
filament::MaterialInstance* materialInstance, filament::MaterialInstance *materialInstance,
bool keepData) bool keepData)
{
auto geometry = std::make_unique<CustomGeometry>(vertices, numVertices, normals, numNormals, uvs, numUvs, indices, numIndices, primitiveType, _engine);
auto entity = utils::EntityManager::get().create();
RenderableManager::Builder builder(1);
builder.boundingBox(geometry->getBoundingBox())
.geometry(0, primitiveType, geometry->vertexBuffer(), geometry->indexBuffer(), 0, numIndices)
.culling(true)
.receiveShadows(true)
.castShadows(true);
filament::Material *mat = nullptr;
if (!materialInstance) {
Log("Using default ubershader material");
filament::gltfio::MaterialKey config;
memset(&config, 0, sizeof(config)); // Initialize all bits to zero
config.unlit = false;
config.doubleSided = false;
config.useSpecularGlossiness = false;
config.alphaMode = filament::gltfio::AlphaMode::OPAQUE;
config.hasBaseColorTexture = numUvs > 0;
config.hasClearCoat = false;
config.hasClearCoatNormalTexture = false;
config.hasClearCoatRoughnessTexture = false;
config.hasEmissiveTexture = false;
config.hasIOR = false;
config.hasMetallicRoughnessTexture = false;
config.hasNormalTexture = false;
config.hasOcclusionTexture = false;
config.hasSheen = false;
config.hasSheenColorTexture = false;
config.hasSheenRoughnessTexture = false;
config.hasSpecularGlossinessTexture = false;
config.hasTextureTransforms = false;
config.hasTransmission = false;
config.hasTransmissionTexture = false;
config.hasVolume = false;
config.hasVolumeThicknessTexture = false;
config.baseColorUV = 0;
config.hasVertexColors = false;
config.hasVolume = false;
materialInstance = createUbershaderMaterialInstance(config);
if(!materialInstance) {
Log("Failed to create material instance");
return Entity::smuggle(Entity());
}
}
// Set up texture and sampler if UVs are available
if (uvs != nullptr && numUvs > 0)
{ {
// Create a default white texture auto geometry = std::make_unique<CustomGeometry>(vertices, numVertices, normals, numNormals, uvs, numUvs, indices, numIndices, primitiveType, _engine);
static constexpr uint32_t textureSize = 1;
static constexpr uint32_t white = 0x00ffffff;
Texture* texture = Texture::Builder()
.width(textureSize)
.height(textureSize)
.levels(1)
.format(Texture::InternalFormat::RGBA8)
.build(*_engine);
_textures.insert(texture); auto entity = utils::EntityManager::get().create();
RenderableManager::Builder builder(1);
filament::backend::PixelBufferDescriptor pbd(&white, 4, Texture::Format::RGBA, Texture::Type::UBYTE);
texture->setImage(*_engine, 0, std::move(pbd));
// Create a sampler builder.boundingBox(geometry->getBoundingBox())
TextureSampler sampler(TextureSampler::MinFilter::NEAREST, TextureSampler::MagFilter::NEAREST); .geometry(0, primitiveType, geometry->vertexBuffer(), geometry->indexBuffer(), 0, numIndices)
sampler.setWrapModeS(TextureSampler::WrapMode::REPEAT); .culling(true)
sampler.setWrapModeT(TextureSampler::WrapMode::REPEAT); .receiveShadows(true)
.castShadows(true);
// Set the texture and sampler to the material instance filament::Material *mat = nullptr;
materialInstance->setParameter("baseColorMap", texture, sampler);
if (!materialInstance)
{
Log("Using default ubershader material");
filament::gltfio::MaterialKey config;
memset(&config, 0, sizeof(config)); // Initialize all bits to zero
config.unlit = false;
config.doubleSided = false;
config.useSpecularGlossiness = false;
config.alphaMode = filament::gltfio::AlphaMode::OPAQUE;
config.hasBaseColorTexture = numUvs > 0;
config.hasClearCoat = false;
config.hasClearCoatNormalTexture = false;
config.hasClearCoatRoughnessTexture = false;
config.hasEmissiveTexture = false;
config.hasIOR = false;
config.hasMetallicRoughnessTexture = false;
config.hasNormalTexture = false;
config.hasOcclusionTexture = false;
config.hasSheen = false;
config.hasSheenColorTexture = false;
config.hasSheenRoughnessTexture = false;
config.hasSpecularGlossinessTexture = false;
config.hasTextureTransforms = false;
config.hasTransmission = false;
config.hasTransmissionTexture = false;
config.hasVolume = false;
config.hasVolumeThicknessTexture = false;
config.baseColorUV = 0;
config.hasVertexColors = false;
config.hasVolume = false;
materialInstance = createUbershaderMaterialInstance(config);
if (!materialInstance)
{
Log("Failed to create material instance");
return Entity::smuggle(Entity());
}
}
// Set up texture and sampler if UVs are available
if (uvs != nullptr && numUvs > 0)
{
if(materialInstance->getMaterial()->hasParameter("baseColorMap")) {
// Create a default white texture
static constexpr uint32_t textureSize = 1;
static constexpr uint32_t white = 0x00ffffff;
Texture *texture = Texture::Builder()
.width(textureSize)
.height(textureSize)
.levels(1)
.format(Texture::InternalFormat::RGBA8)
.build(*_engine);
_textures.insert(texture);
filament::backend::PixelBufferDescriptor pbd(&white, 4, Texture::Format::RGBA, Texture::Type::UBYTE);
texture->setImage(*_engine, 0, std::move(pbd));
// Create a sampler
TextureSampler sampler(TextureSampler::MinFilter::NEAREST, TextureSampler::MagFilter::NEAREST);
sampler.setWrapModeS(TextureSampler::WrapMode::REPEAT);
sampler.setWrapModeT(TextureSampler::WrapMode::REPEAT);
// Set the texture and sampler to the material instance
materialInstance->setParameter("baseColorMap", texture, sampler);
}
}
builder.material(0, materialInstance);
builder.build(*_engine, entity);
_scene->addEntity(entity);
auto entityId = Entity::smuggle(entity);
_geometry.emplace(entityId, std::move(geometry));
return entityId;
} }
builder.material(0, materialInstance); MaterialInstance *SceneManager::getMaterialInstanceAt(EntityId entityId, int materialIndex)
builder.build(*_engine, entity); {
_scene->addEntity(entity);
auto entityId = Entity::smuggle(entity);
_geometry.emplace(entityId, std::move(geometry));
return entityId;
}
MaterialInstance* SceneManager::getMaterialInstanceAt(EntityId entityId, int materialIndex) {
auto entity = Entity::import(entityId); auto entity = Entity::import(entityId);
const auto &rm = _engine->getRenderableManager(); const auto &rm = _engine->getRenderableManager();
auto renderableInstance = rm.getInstance(entity); auto renderableInstance = rm.getInstance(entity);
@@ -2436,7 +2464,7 @@ EntityId SceneManager::createGeometry(
materialInstance->setParameter(property, value); materialInstance->setParameter(property, value);
} }
void SceneManager::setMaterialProperty(EntityId entityId, int materialIndex, const char *property, filament::math::float4& value) void SceneManager::setMaterialProperty(EntityId entityId, int materialIndex, const char *property, filament::math::float4 &value)
{ {
auto entity = Entity::import(entityId); auto entity = Entity::import(entityId);
const auto &rm = _engine->getRenderableManager(); const auto &rm = _engine->getRenderableManager();
@@ -2453,17 +2481,20 @@ EntityId SceneManager::createGeometry(
Log("Parameter %s not found", property); Log("Parameter %s not found", property);
return; return;
} }
materialInstance->setParameter(property, filament::math::float4 { value.x, value.y, value.z, value.w }); materialInstance->setParameter(property, filament::math::float4{value.x, value.y, value.z, value.w});
} }
void SceneManager::destroy(MaterialInstance* instance) { void SceneManager::destroy(MaterialInstance *instance)
{
_engine->destroy(instance); _engine->destroy(instance);
} }
MaterialInstance* SceneManager::createUbershaderMaterialInstance(filament::gltfio::MaterialKey config) { MaterialInstance *SceneManager::createUbershaderMaterialInstance(filament::gltfio::MaterialKey config)
filament::gltfio::UvMap uvmap {}; {
auto * materialInstance = _ubershaderProvider->createMaterialInstance(&config, &uvmap); filament::gltfio::UvMap uvmap{};
if(!materialInstance) { auto *materialInstance = _ubershaderProvider->createMaterialInstance(&config, &uvmap);
if (!materialInstance)
{
Log("Invalid material configuration"); Log("Invalid material configuration");
return nullptr; return nullptr;
} }
@@ -2473,44 +2504,58 @@ EntityId SceneManager::createGeometry(
return materialInstance; return materialInstance;
} }
MaterialInstance* SceneManager::createUnlitMaterialInstance() { MaterialInstance *SceneManager::createUnlitFixedSizeMaterialInstance()
{
auto instance = _gizmoMaterial->createInstance();
instance->setParameter("scale", 1.0f);
return instance;
}
MaterialInstance *SceneManager::createUnlitMaterialInstance()
{
UvMap uvmap; UvMap uvmap;
auto instance = _unlitMaterialProvider->createMaterialInstance(nullptr, &uvmap); auto instance = _unlitMaterialProvider->createMaterialInstance(nullptr, &uvmap);
instance->setParameter("uvScale", filament::math::float2 { 1.0f, 1.0f }); instance->setParameter("uvScale", filament::math::float2{1.0f, 1.0f});
_materialInstances.push_back(instance); _materialInstances.push_back(instance);
return instance; return instance;
} }
Camera* SceneManager::createCamera() { Camera *SceneManager::createCamera()
{
auto entity = EntityManager::get().create(); auto entity = EntityManager::get().create();
auto camera = _engine->createCamera(entity); auto camera = _engine->createCamera(entity);
_cameras.push_back(camera); _cameras.push_back(camera);
return camera; return camera;
} }
void SceneManager::destroyCamera(Camera* camera) { void SceneManager::destroyCamera(Camera *camera)
{
auto entity = camera->getEntity(); auto entity = camera->getEntity();
_engine->destroyCameraComponent(entity); _engine->destroyCameraComponent(entity);
_engine->getEntityManager().destroy(entity); _engine->getEntityManager().destroy(entity);
auto it = std::find(_cameras.begin(), _cameras.end(), camera); auto it = std::find(_cameras.begin(), _cameras.end(), camera);
if(it != _cameras.end()) { if (it != _cameras.end())
{
_cameras.erase(it); _cameras.erase(it);
} }
} }
size_t SceneManager::getCameraCount() { size_t SceneManager::getCameraCount()
{
return _cameras.size() + 1; return _cameras.size() + 1;
} }
Camera* SceneManager::getCameraAt(size_t index) { Camera *SceneManager::getCameraAt(size_t index)
if(index == 0) { {
if (index == 0)
{
return _mainCamera; return _mainCamera;
} }
if(index - 1 > _cameras.size() - 1) { if (index - 1 > _cameras.size() - 1)
{
return nullptr; return nullptr;
} }
return _cameras[index-1]; return _cameras[index - 1];
} }
} // namespace thermion } // namespace thermion
-9
View File
@@ -14,15 +14,6 @@ extern "C"
using namespace filament; using namespace filament;
#endif #endif
EMSCRIPTEN_KEEPALIVE TGizmo* Gizmo_new(TEngine *tEngine, TView *tView, TScene *tScene)
{
auto *view = reinterpret_cast<View*>(tView);
auto *engine = reinterpret_cast<Engine*>(tEngine);
auto *scene = reinterpret_cast<Scene*>(tScene);
auto gizmo = new Gizmo(engine, view, scene);
return reinterpret_cast<TGizmo*>(gizmo);
}
EMSCRIPTEN_KEEPALIVE void Gizmo_pick(TGizmo *tGizmo, uint32_t x, uint32_t y, GizmoPickCallback callback) EMSCRIPTEN_KEEPALIVE void Gizmo_pick(TGizmo *tGizmo, uint32_t x, uint32_t y, GizmoPickCallback callback)
{ {
auto *gizmo = reinterpret_cast<Gizmo*>(tGizmo); auto *gizmo = reinterpret_cast<Gizmo*>(tGizmo);
+26 -3
View File
@@ -49,11 +49,16 @@ extern "C"
viewer->destroyRenderTarget(renderTarget); viewer->destroyRenderTarget(renderTarget);
} }
EMSCRIPTEN_KEEPALIVE void Viewer_pick(TViewer *tViewer, TView* tView, int x, int y, void (*callback)(EntityId entityId, int x, int y, TView *tView)) EMSCRIPTEN_KEEPALIVE void Viewer_pick(TViewer *tViewer, TView* tView, int x, int y, void (*callback)(EntityId entityId, int x, int y, TView *tView, float depth, float fragX, float fragY, float fragZ))
{ {
auto *viewer = reinterpret_cast<FilamentViewer*>(tViewer); auto *viewer = reinterpret_cast<FilamentViewer*>(tViewer);
auto *view = reinterpret_cast<View*>(tView); auto *view = reinterpret_cast<View*>(tView);
((FilamentViewer *)viewer)->pick(view, static_cast<uint32_t>(x), static_cast<uint32_t>(y), reinterpret_cast<void (*)(EntityId entityId, int x, int y, View *view)>(callback)); ((FilamentViewer *)viewer)->pick(view, static_cast<uint32_t>(x), static_cast<uint32_t>(y), reinterpret_cast<FilamentViewer::PickCallback>(callback));
}
EMSCRIPTEN_KEEPALIVE bool Viewer_isNonPickableEntity(TViewer *tViewer, EntityId entityId) {
auto *viewer = reinterpret_cast<FilamentViewer*>(tViewer);
return viewer->isNonPickableEntity(entityId);
} }
EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer(TViewer *viewer) EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer(TViewer *viewer)
@@ -168,9 +173,17 @@ extern "C"
return ((SceneManager *)sceneManager)->loadGlb(assetPath, numInstances, keepData); return ((SceneManager *)sceneManager)->loadGlb(assetPath, numInstances, keepData);
} }
EMSCRIPTEN_KEEPALIVE TGizmo* SceneManager_createGizmo(TSceneManager *tSceneManager, TView *tView, TScene *tScene) {
auto sceneManager = reinterpret_cast<SceneManager*>(tSceneManager);
auto *scene = reinterpret_cast<Scene*>(tScene);
auto *view = reinterpret_cast<View*>(tView);
auto gizmo = sceneManager->createGizmo(view, scene);
return reinterpret_cast<TGizmo*>(gizmo);
}
EMSCRIPTEN_KEEPALIVE EntityId SceneManager_loadGlbFromBuffer(TSceneManager *sceneManager, const uint8_t *const data, size_t length, bool keepData, int priority, int layer, bool loadResourcesAsync) EMSCRIPTEN_KEEPALIVE EntityId SceneManager_loadGlbFromBuffer(TSceneManager *sceneManager, const uint8_t *const data, size_t length, bool keepData, int priority, int layer, bool loadResourcesAsync)
{ {
return ((SceneManager *)sceneManager)->loadGlbFromBuffer((const uint8_t *)data, length, 1, keepData, priority, layer); return ((SceneManager *)sceneManager)->loadGlbFromBuffer((const uint8_t *)data, length, 1, keepData, priority, layer, loadResourcesAsync);
} }
EMSCRIPTEN_KEEPALIVE EntityId create_instance(TSceneManager *sceneManager, EntityId entityId) EMSCRIPTEN_KEEPALIVE EntityId create_instance(TSceneManager *sceneManager, EntityId entityId)
@@ -1021,6 +1034,12 @@ extern "C"
return reinterpret_cast<TMaterialInstance *>(instance); return reinterpret_cast<TMaterialInstance *>(instance);
} }
EMSCRIPTEN_KEEPALIVE TMaterialInstance *SceneManager_createUnlitFixedSizeMaterialInstance(TSceneManager *sceneManager)
{
auto *instance = ((SceneManager *)sceneManager)->createUnlitFixedSizeMaterialInstance();
return reinterpret_cast<TMaterialInstance *>(instance);
}
EMSCRIPTEN_KEEPALIVE void destroy_material_instance(TSceneManager *sceneManager, TMaterialInstance *instance) EMSCRIPTEN_KEEPALIVE void destroy_material_instance(TSceneManager *sceneManager, TMaterialInstance *instance)
{ {
((SceneManager *)sceneManager)->destroy(reinterpret_cast<MaterialInstance *>(instance)); ((SceneManager *)sceneManager)->destroy(reinterpret_cast<MaterialInstance *>(instance));
@@ -1042,6 +1061,10 @@ extern "C"
reinterpret_cast<MaterialInstance *>(materialInstance)->setParameter(propertyName, data); reinterpret_cast<MaterialInstance *>(materialInstance)->setParameter(propertyName, data);
} }
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat(TMaterialInstance *materialInstance, const char *propertyName, double value)
{
reinterpret_cast<MaterialInstance *>(materialInstance)->setParameter(propertyName, static_cast<float>(value));
}
EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine *tEngine, EntityId entityId) EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine *tEngine, EntityId entityId)
{ {
@@ -371,6 +371,16 @@ extern "C"
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
} }
EMSCRIPTEN_KEEPALIVE void SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread(TSceneManager *sceneManager, void (*callback)(TMaterialInstance*)) {
std::packaged_task<void()> lambda(
[=]() mutable
{
auto instance = SceneManager_createUnlitFixedSizeMaterialInstance(sceneManager);
callback(instance);
});
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void SceneManager_loadGlbFromBufferRenderThread(TSceneManager *sceneManager, EMSCRIPTEN_KEEPALIVE void SceneManager_loadGlbFromBufferRenderThread(TSceneManager *sceneManager,
const uint8_t *const data, const uint8_t *const data,
size_t length, size_t length,
+1 -1
View File
@@ -62,7 +62,7 @@ add_executable(${MODULE_NAME}
"${CMAKE_CURRENT_SOURCE_DIR}/../src/camutils/Manipulator.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../src/camutils/Manipulator.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../src/camutils/Bookmark.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../src/camutils/Bookmark.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../include/material/image.c" "${CMAKE_CURRENT_SOURCE_DIR}/../include/material/image.c"
"${CMAKE_CURRENT_SOURCE_DIR}/../include/material/gizmo.c" "${CMAKE_CURRENT_SOURCE_DIR}/../include/material/unlit_fixed_size.c"
"${CMAKE_CURRENT_SOURCE_DIR}/src/cpp/ThermionDartWebApi.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/cpp/ThermionDartWebApi.cpp"
) )
set_target_properties(${MODULE_NAME} PROPERTIES set_target_properties(${MODULE_NAME} PROPERTIES
+2 -1
View File
@@ -1,6 +1,6 @@
name: thermion_dart name: thermion_dart
description: 3D rendering toolkit for Dart. description: 3D rendering toolkit for Dart.
version: 0.2.1-dev.0.0.10 version: 0.2.1-dev.0.0.16
homepage: https://thermion.dev homepage: https://thermion.dev
repository: https://github.com/nmfisher/thermion repository: https://github.com/nmfisher/thermion
@@ -18,6 +18,7 @@ dependencies:
web: ^1.0.0 web: ^1.0.0
logging: ^1.2.0 logging: ^1.2.0
http: ^1.2.2 http: ^1.2.2
path: ^1.9.0
dev_dependencies: dev_dependencies:
ffigen: ^13.0.0 ffigen: ^13.0.0
-4
View File
@@ -1,10 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:animation_tools_dart/animation_tools_dart.dart'; import 'package:animation_tools_dart/animation_tools_dart.dart';
import 'package:thermion_dart/src/viewer/src/events.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'package:vector_math/vector_math_64.dart'; import 'package:vector_math/vector_math_64.dart';
import 'helpers.dart'; import 'helpers.dart';
+36 -10
View File
@@ -1,3 +1,7 @@
// ignore_for_file: unused_local_variable
import 'dart:math';
import 'package:thermion_dart/thermion_dart.dart'; import 'package:thermion_dart/thermion_dart.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'package:vector_math/vector_math_64.dart'; import 'package:vector_math/vector_math_64.dart';
@@ -7,7 +11,6 @@ void main() async {
final testHelper = TestHelper("integration"); final testHelper = TestHelper("integration");
group('camera', () { group('camera', () {
test('getCameraModelMatrix, getCameraPosition, rotation', () async { test('getCameraModelMatrix, getCameraPosition, rotation', () async {
var viewer = await testHelper.createViewer(); var viewer = await testHelper.createViewer();
var matrix = await viewer.getCameraModelMatrix(); var matrix = await viewer.getCameraModelMatrix();
@@ -24,7 +27,7 @@ void main() async {
expect(position.x, 2.0); expect(position.x, 2.0);
expect(position.y, 2.0); expect(position.y, 2.0);
expect(position.z, 2.0); expect(position.z, 2.0);
await viewer.dispose(); await viewer.dispose();
}); });
@@ -50,7 +53,6 @@ void main() async {
expect(position.y, closeTo(4.0, 1e-6)); expect(position.y, closeTo(4.0, 1e-6));
expect(position.z, closeTo(5.0, 1e-6)); expect(position.z, closeTo(5.0, 1e-6));
await viewer.dispose(); await viewer.dispose();
}); });
test('getCameraProjectionMatrix', () async { test('getCameraProjectionMatrix', () async {
@@ -62,11 +64,11 @@ void main() async {
test('getCameraCullingProjectionMatrix', () async { test('getCameraCullingProjectionMatrix', () async {
throw Exception("TODO"); throw Exception("TODO");
// ignore: dead_code
var viewer = await testHelper.createViewer(); var viewer = await testHelper.createViewer();
var matrix = await viewer.getCameraCullingProjectionMatrix(); var matrix = await viewer.getCameraCullingProjectionMatrix();
print(matrix); print(matrix);
await viewer.dispose(); await viewer.dispose();
}); });
test('getCameraFrustum', () async { test('getCameraFrustum', () async {
@@ -92,24 +94,48 @@ void main() async {
var camera = await viewer.getMainCamera(); var camera = await viewer.getMainCamera();
await viewer.createGeometry(GeometryHelper.cube()); await viewer.createGeometry(GeometryHelper.cube());
await camera.setProjection(Projection.Orthographic, -0.05, 0.05, -0.05, 0.05, 0.05, 10000); await camera.setProjection(
await testHelper.capture( Projection.Orthographic, -0.05, 0.05, -0.05, 0.05, 0.05, 10000);
viewer, "camera_set_orthographic_projection"); await testHelper.capture(viewer, "camera_set_orthographic_projection");
await viewer.dispose(); await viewer.dispose();
}); });
test('set custom projection/culling matrix', () async { test('set perspective projection/culling matrix', () async {
var viewer = await testHelper.createViewer( var viewer = await testHelper.createViewer(
bg: kRed, cameraPosition: Vector3(0, 0, 4)); bg: kRed, cameraPosition: Vector3(0, 0, 4));
var camera = await viewer.getMainCamera(); var camera = await viewer.getMainCamera();
final cube = await viewer.createGeometry(GeometryHelper.cube()); final cube = await viewer.createGeometry(GeometryHelper.cube());
var fovY = pi / 2;
await camera.setProjectionMatrixWithCulling(
makePerspectiveMatrix(fovY, 1.0, 0.05, 10000), 0.05, 10000);
await testHelper.capture(
viewer, "camera_set_perspective_projection_culling_matrix_object_fov90");
// cube no longer visible when the far plane is moved closer to camera so cube is outside
fovY = 2*(pi/3);
await camera.setProjectionMatrixWithCulling(
makePerspectiveMatrix(fovY, 1.0, 0.05, 10000), 0.05, 10000);
await testHelper.capture(
viewer, "camera_set_perspective_projection_culling_matrix_object_fov120");
await viewer.dispose();
});
test('set custom projection/culling matrix (orthographic)', () async {
var viewer = await testHelper.createViewer(
bg: kRed, cameraPosition: Vector3(0, 0, 4));
var camera = await viewer.getMainCamera();
final cube = await viewer.createGeometry(GeometryHelper.cube());
// cube is visible when inside the frustum, cube is visible // cube is visible when inside the frustum, cube is visible
var projectionMatrix = var projectionMatrix =
makeOrthographicMatrix(-10.0, 10.0, -10.0, 10.0, 0.05, 10000); makeOrthographicMatrix(-10.0, 10.0, -10.0, 10.0, 0.05, 10000);
await camera.setProjectionMatrixWithCulling( await camera.setProjectionMatrixWithCulling(
projectionMatrix, 0.05, 10000); projectionMatrix, 0.05, 10000);
await testHelper.capture( await testHelper.capture(
viewer, "camera_projection_culling_matrix_object_in_frustum"); viewer, "camera_projection_culling_matrix_object_in_frustum");
@@ -119,7 +145,7 @@ void main() async {
await camera.setProjectionMatrixWithCulling(projectionMatrix, 0.05, 1); await camera.setProjectionMatrixWithCulling(projectionMatrix, 0.05, 1);
await testHelper.capture( await testHelper.capture(
viewer, "camera_projection_culling_matrix_object_outside_frustum"); viewer, "camera_projection_culling_matrix_object_outside_frustum");
await viewer.dispose(); await viewer.dispose();
}); });
+16
View File
@@ -0,0 +1,16 @@
// just for investigating crashes on GitHub actions
import 'package:test/test.dart';
import 'helpers.dart';
void main() async {
group("test", () {
test("test", () async {
print("Creating test helper");
final testHelper = TestHelper("dummy");
var viewer = await testHelper.createViewer();
expect(1, 1);
});
});
}
+2
View File
@@ -1,3 +1,5 @@
// ignore_for_file: unused_local_variable
import 'dart:io'; import 'dart:io';
import 'dart:math'; import 'dart:math';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
+2
View File
@@ -1,3 +1,5 @@
// ignore_for_file: unused_local_variable
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'helpers.dart'; import 'helpers.dart';
+2
View File
@@ -1,3 +1,5 @@
// ignore_for_file: unused_local_variable
import 'dart:io'; import 'dart:io';
import 'package:thermion_dart/thermion_dart.dart'; import 'package:thermion_dart/thermion_dart.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
+18 -13
View File
@@ -1,3 +1,5 @@
// ignore_for_file: unused_local_variable
import 'dart:ffi'; import 'dart:ffi';
import 'dart:io'; import 'dart:io';
import 'dart:math'; import 'dart:math';
@@ -10,7 +12,6 @@ import 'package:thermion_dart/src/utils/src/dart_resources.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
import 'package:thermion_dart/src/viewer/src/ffi/thermion_viewer_ffi.dart'; import 'package:thermion_dart/src/viewer/src/ffi/thermion_viewer_ffi.dart';
import 'package:thermion_dart/src/viewer/src/shared_types/view.dart';
import 'package:thermion_dart/thermion_dart.dart'; import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart'; import 'package:vector_math/vector_math_64.dart';
import 'package:path/path.dart' as p; import 'package:path/path.dart' as p;
@@ -72,28 +73,31 @@ class TestHelper {
TestHelper(String dir) { TestHelper(String dir) {
final packageUri = findPackageRoot('thermion_dart'); final packageUri = findPackageRoot('thermion_dart');
print("Package URIL $packageUri");
testDir = Directory("${packageUri.toFilePath()}/test").path; testDir = Directory("${packageUri.toFilePath()}/test").path;
print("Test dir : $packageUri");
outDir = Directory("$testDir/output/${dir}"); outDir = Directory("$testDir/output/${dir}");
print("Out dir : $packageUri");
// outDir.deleteSync(recursive: true); // outDir.deleteSync(recursive: true);
outDir.createSync(recursive: true); outDir.createSync(recursive: true);
if(Platform.isMacOS) { print("Created out dir : $packageUri");
if (Platform.isMacOS) {
DynamicLibrary.open('${testDir}/libThermionTextureSwift.dylib'); DynamicLibrary.open('${testDir}/libThermionTextureSwift.dylib');
} }
} }
Future capture(ThermionViewer viewer, String outputFilename, Future capture(ThermionViewer viewer, String outputFilename,
{View? view, SwapChain? swapChain, RenderTarget? renderTarget}) async { {View? view, SwapChain? swapChain, RenderTarget? renderTarget}) async {
await Future.delayed(Duration(milliseconds: 10)); await Future.delayed(Duration(milliseconds: 10));
var outPath = p.join(outDir.path, "$outputFilename.bmp"); var outPath = p.join(outDir.path, "$outputFilename.bmp");
var pixelBuffer = await viewer.capture( var pixelBuffer = await viewer.capture(
view: view, view: view,
swapChain: swapChain ?? this.swapChain, swapChain: swapChain ?? this.swapChain,
renderTarget: renderTarget); renderTarget: renderTarget);
await viewer.render(); await viewer.render();
view ??= await viewer.getViewAt(0); view ??= await viewer.getViewAt(0);
var vp = await view.getViewport(); var vp = await view.getViewport();
await savePixelBufferToBmp(pixelBuffer, vp.width, vp.height, outPath); await savePixelBufferToBmp(pixelBuffer, vp.width, vp.height, outPath);
@@ -101,9 +105,6 @@ class TestHelper {
} }
Future<ThermionTextureSwift> createTexture(int width, int height) async { Future<ThermionTextureSwift> createTexture(int width, int height) async {
final packageUri = findPackageRoot('thermion_dart');
var testDir = Directory("${packageUri.toFilePath()}/test").path;
final object = ThermionTextureSwift.new1(); final object = ThermionTextureSwift.new1();
object.initWithWidth_height_(width, height); object.initWithWidth_height_(width, height);
return object; return object;
@@ -114,24 +115,29 @@ class TestHelper {
Vector3? cameraPosition, Vector3? cameraPosition,
viewportDimensions = (width: 500, height: 500)}) async { viewportDimensions = (width: 500, height: 500)}) async {
final resourceLoader = calloc<ResourceLoaderWrapper>(1); final resourceLoader = calloc<ResourceLoaderWrapper>(1);
print("resourceLoader");
var loadToOut = NativeCallable< var loadToOut = NativeCallable<
Void Function(Pointer<Char>, Void Function(Pointer<Char>,
Pointer<ResourceBuffer>)>.listener(DartResourceLoader.loadResource); Pointer<ResourceBuffer>)>.listener(DartResourceLoader.loadResource);
print("loadToOut");
resourceLoader.ref.loadToOut = loadToOut.nativeFunction; resourceLoader.ref.loadToOut = loadToOut.nativeFunction;
print("set ref");
var freeResource = NativeCallable<Void Function(ResourceBuffer)>.listener( var freeResource = NativeCallable<Void Function(ResourceBuffer)>.listener(
DartResourceLoader.freeResource); DartResourceLoader.freeResource);
print("freeResource");
resourceLoader.ref.freeResource = freeResource.nativeFunction; resourceLoader.ref.freeResource = freeResource.nativeFunction;
print("set freeResource ref");
var viewer = ThermionViewerFFI(resourceLoader: resourceLoader.cast<Void>()); var viewer = ThermionViewerFFI(resourceLoader: resourceLoader.cast<Void>());
print("created viewer");
await viewer.initialized; await viewer.initialized;
swapChain = await viewer.createHeadlessSwapChain( swapChain = await viewer.createHeadlessSwapChain(
viewportDimensions.width, viewportDimensions.height); viewportDimensions.width, viewportDimensions.height);
print("created headless swapchain");
await viewer.updateViewportAndCameraProjection( await viewer.updateViewportAndCameraProjection(
viewportDimensions.width.toDouble(), viewportDimensions.width.toDouble(),
viewportDimensions.height.toDouble()); viewportDimensions.height.toDouble());
print("updated camera");
if (bg != null) { if (bg != null) {
await viewer.setBackgroundColor( await viewer.setBackgroundColor(
bg.r.toDouble(), bg.g.toDouble(), bg.b.toDouble(), bg.a.toDouble()); bg.r.toDouble(), bg.g.toDouble(), bg.b.toDouble(), bg.a.toDouble());
@@ -191,7 +197,7 @@ Future<Uint8List> pixelBufferToBmp(
} }
Future<Uint8List> pixelsToPng(Uint8List pixelBuffer, int width, int height, Future<Uint8List> pixelsToPng(Uint8List pixelBuffer, int width, int height,
{bool linearToSrgb = false}) async { {bool linearToSrgb = false, bool invertAces = false}) async {
final image = img.Image(width: width, height: height); final image = img.Image(width: width, height: height);
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
@@ -203,7 +209,6 @@ Future<Uint8List> pixelsToPng(Uint8List pixelBuffer, int width, int height,
int a = pixelBuffer[pixelIndex + 3]; int a = pixelBuffer[pixelIndex + 3];
// Apply inverse ACES tone mapping // Apply inverse ACES tone mapping
bool invertAces = false;
if (invertAces) { if (invertAces) {
r = _inverseACESToneMapping(r); r = _inverseACESToneMapping(r);
g = _inverseACESToneMapping(g); g = _inverseACESToneMapping(g);
-782
View File
@@ -1,782 +0,0 @@
import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'package:thermion_dart/src/viewer/src/events.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:test/test.dart';
import 'package:vector_math/vector_math_64.dart';
import 'helpers.dart';
void main() async {
final testHelper = TestHelper("integration");
group('background', () {
test('set background color to solid green', () async {
var viewer = await testHelper.createViewer();
await viewer.setBackgroundColor(0.0, 1.0, 0.0, 1.0);
await testHelper.capture(viewer, "set_background_color_to_solid_green");
await viewer.dispose();
});
test('set background color to full transparency', () async {
var viewer = await testHelper.createViewer();
await viewer.setBackgroundColor(0.0, 1.0, 0.0, 0.0);
await testHelper.capture(
viewer, "set_background_color_to_transparent_green");
await viewer.dispose();
});
test('set background image', () async {
var viewer = await testHelper.createViewer();
await viewer.setBackgroundImage(
"file:///${testHelper.testDir}/assets/cube_texture_512x512.png");
await viewer.setPostProcessing(true);
await viewer.setToneMapping(ToneMapper.LINEAR);
await testHelper.capture(viewer, "set_background_image");
await viewer.dispose();
});
});
group("scene update events", () {
test('add light fires SceneUpdateEvent', () async {
var viewer = await testHelper.createViewer();
final success = Completer<bool>();
var light = DirectLight(
type: LightType.POINT,
color: 6500,
intensity: 1000000,
position: Vector3(0, 0.6, 0.6),
direction: Vector3(0, 0, 0),
falloffRadius: 2.0);
late StreamSubscription listener;
listener = viewer.sceneUpdated.listen((updateEvent) {
var wasSuccess = updateEvent.eventType == EventType.EntityAdded &&
updateEvent.addedEntityType == EntityType.DirectLight &&
updateEvent.getDirectLight() == light;
success.complete(wasSuccess);
listener.cancel();
});
await viewer.addDirectLight(light);
expect(await success.future, true);
});
test('remove light fires SceneUpdateEvent', () async {
var viewer = await testHelper.createViewer();
final success = Completer<bool>();
var light = await viewer.addDirectLight(DirectLight.point());
late StreamSubscription listener;
listener = viewer.sceneUpdated.listen((updateEvent) {
var wasSuccess = updateEvent.eventType == EventType.EntityRemoved &&
updateEvent.entity == light;
success.complete(wasSuccess);
listener.cancel();
});
await viewer.removeLight(light);
expect(await success.future, true);
});
test('add geometry fires SceneUpdateEvent', () async {
var viewer = await testHelper.createViewer();
final success = Completer<bool>();
var geometry = GeometryHelper.cube();
late StreamSubscription listener;
listener = viewer.sceneUpdated.listen((updateEvent) {
var wasSuccess = updateEvent.eventType == EventType.EntityAdded &&
updateEvent.addedEntityType == EntityType.Geometry &&
updateEvent.getAsGeometry() == geometry;
success.complete(wasSuccess);
listener.cancel();
});
await viewer.createGeometry(geometry);
expect(await success.future, true);
});
test('remove geometry fires SceneUpdateEvent', () async {
var viewer = await testHelper.createViewer();
var geometry = await viewer.createGeometry(GeometryHelper.cube());
final success = Completer<bool>();
late StreamSubscription listener;
listener = viewer.sceneUpdated.listen((updateEvent) {
var wasSuccess = updateEvent.eventType == EventType.EntityRemoved &&
updateEvent.entity == geometry;
success.complete(wasSuccess);
listener.cancel();
});
await viewer.removeEntity(geometry);
expect(await success.future, true);
});
test('loadGlb fires SceneUpdateEvent', () async {
var viewer = await testHelper.createViewer();
final success = Completer<bool>();
late StreamSubscription listener;
final uri = "${testHelper.testDir}/cube.glb";
listener = viewer.sceneUpdated.listen((updateEvent) {
var wasSuccess = updateEvent.eventType == EventType.EntityAdded &&
updateEvent.addedEntityType == EntityType.Gltf &&
updateEvent.getAsGLTF().uri == uri;
success.complete(wasSuccess);
listener.cancel();
});
await viewer.loadGlb(uri, keepData: false);
expect(await success.future, true);
});
test('remove glb fires SceneUpdateEvent', () async {
var viewer = await testHelper.createViewer();
final uri = "${testHelper.testDir}/cube.glb";
var entity = await viewer.loadGlb(uri, keepData: false);
final success = Completer<bool>();
late StreamSubscription listener;
listener = viewer.sceneUpdated.listen((updateEvent) {
var wasSuccess = updateEvent.eventType == EventType.EntityRemoved &&
updateEvent.entity == entity;
success.complete(wasSuccess);
listener.cancel();
});
await viewer.removeEntity(entity);
expect(await success.future, true);
});
});
group("MaterialInstance", () {
test('disable depth write', () async {
var viewer = await testHelper.createViewer();
await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
await viewer.setCameraPosition(0, 0, 6);
await viewer.addDirectLight(
DirectLight.sun(direction: Vector3(0, 0, -1)..normalize()));
final cube1 = await viewer.createGeometry(GeometryHelper.cube());
var materialInstance = await viewer.getMaterialInstanceAt(cube1, 0);
final cube2 = await viewer.createGeometry(GeometryHelper.cube());
await viewer.setMaterialPropertyFloat4(
cube2, "baseColorFactor", 0, 0, 1, 0, 1);
await viewer.setPosition(cube2, 1.0, 0.0, -1.0);
expect(materialInstance, isNotNull);
// with depth write enabled on both materials, cube2 renders behind the white cube
await testHelper.capture(viewer, "material_instance_depth_write_enabled");
// if we disable depth write on cube1, then cube2 will always appear in front
// (relying on insertion order)
materialInstance!.setDepthWriteEnabled(false);
await testHelper.capture(
viewer, "material_instance_depth_write_disabled");
// set priority for the cube1 cube to 7 (render) last, cube1 renders in front
await viewer.setPriority(cube1, 7);
await testHelper.capture(
viewer, "material_instance_depth_write_disabled_with_priority");
});
});
// test('create instance from glb when keepData is true', () async {
// var model = await viewer.loadGlb("${testHelper.testDir}/cube.glb", keepData: true);
// await viewer.transformToUnitCube(model);
// var instance = await viewer.createInstance(model);
// await viewer.setPosition(instance, 0.5, 0.5, -0.5);
// await viewer.setBackgroundColor(0.0, 0.0, 1.0, 1.0);
// await viewer.setCameraPosition(0, 1, 5);
// await viewer
// .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
// await viewer.setRendering(true);
// await testHelper.capture(viewer, "glb_create_instance");
// await viewer.setRendering(false);
// });
// test('create instance from glb fails when keepData is false', () async {
// var model = await viewer.loadGlb("${testHelper.testDir}/cube.glb", keepData: false);
// bool thrown = false;
// try {
// await viewer.createInstance(model);
// } catch (err) {
// thrown = true;
// }
// expect(thrown, true);
// });
// });
// group('Skinning & animations', () {
// test('get bone names', () async {
// var model = await viewer.loadGlb("${testHelper.testDir}/assets/shapes.glb");
// var names = await viewer.getBoneNames(model);
// expect(names.first, "Bone");
// });
// test('reset bones', () async {
// var model = await viewer.loadGlb("${testHelper.testDir}/assets/shapes.glb");
// await viewer.resetBones(model);
// });
// test('set from BVH', () async {
// var model = await viewer.loadGlb("${testHelper.testDir}/assets/shapes.glb");
// var animation = BVHParser.parse(
// File("${testHelper.testDir}/assets/animation.bvh").readAsStringSync(),
// boneRegex: RegExp(r"Bone$"));
// await viewer.addBoneAnimation(model, animation);
// });
// test('fade in/out', () async {
// var model = await viewer.loadGlb("${testHelper.testDir}/assets/shapes.glb");
// var animation = BVHParser.parse(
// File("${testHelper.testDir}/assets/animation.bvh").readAsStringSync(),
// boneRegex: RegExp(r"Bone$"));
// await viewer.addBoneAnimation(model, animation,
// fadeInInSecs: 0.5, fadeOutInSecs: 0.5);
// await Future.delayed(Duration(seconds: 1));
// });
group("materials", () {
test('set float4 material property for custom geometry', () async {
var viewer = await testHelper.createViewer();
await viewer.setCameraPosition(0, 0, 6);
await viewer.setBackgroundColor(0.0, 0.0, 1.0, 1.0);
var light = await viewer.addLight(
LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);
final cube = await viewer.createGeometry(GeometryHelper.cube());
await testHelper.capture(viewer, "set_material_float4_pre");
await viewer.setMaterialPropertyFloat4(
cube, "baseColorFactor", 0, 0.0, 1.0, 0.0, 1.0);
await testHelper.capture(viewer, "set_material_float4_post");
});
test('set float material property for custom geometry', () async {
var viewer = await testHelper.createViewer();
await viewer.setCameraPosition(0, 0, 6);
await viewer.setBackgroundColor(0.0, 0.0, 1.0, 1.0);
var light = await viewer.addLight(
LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);
final cube = await viewer.createGeometry(GeometryHelper.cube());
// this won't actually do anything because the default ubershader doesn't use specular/glossiness
// but we can at least check that the call succeeds
await testHelper.capture(viewer, "set_material_specular_pre");
await viewer.setMaterialPropertyFloat(cube, "specularFactor", 0, 0.0);
await testHelper.capture(viewer, "set_material_specular_post");
});
test('set float material property (roughness) for custom geometry',
() async {
var viewer = await testHelper.createViewer();
await viewer.setCameraPosition(0, 0, 6);
await viewer.setBackgroundColor(0.0, 0.0, 1.0, 1.0);
var light = await viewer.addLight(
LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);
final cube = await viewer.createGeometry(GeometryHelper.cube());
// this won't actually do anything because the default ubershader doesn't use specular/glossiness
// but we can at least check that the call succeeds
await testHelper.capture(viewer, "set_material_roughness_pre");
await viewer.setMaterialPropertyFloat(cube, "metallicFactor", 0, 0.0);
await viewer.setMaterialPropertyFloat(cube, "roughnessFactor", 0, 0.0);
await testHelper.capture(viewer, "set_material_roughness_post");
});
});
group("transforms & parenting", () {
test('set multiple transforms simultaneously with setTransforms', () async {
var viewer =
await testHelper.createViewer(bg: kRed, cameraPosition: Vector3(0, 0, 5));
final cube1 = await viewer.createGeometry(GeometryHelper.cube());
final cube2 = await viewer.createGeometry(GeometryHelper.cube());
await viewer.queueTransformUpdates([
cube1,
cube2
], [
Matrix4.translation(Vector3(-1, 0, 0)),
Matrix4.translation(Vector3(1, 0, 0))
]);
await viewer.render(testHelper.swapChain);
await testHelper.capture(viewer, "set_multiple_transforms");
});
test('getParent and getAncestor both return null when entity has no parent',
() async {
var viewer = await testHelper.createViewer();
final cube = await viewer.createGeometry(GeometryHelper.cube());
expect(await viewer.getParent(cube), isNull);
expect(await viewer.getAncestor(cube), isNull);
});
test(
'getParent returns the parent entity after one has been set via setParent',
() async {
var viewer = await testHelper.createViewer();
final cube1 = await viewer.createGeometry(GeometryHelper.cube());
final cube2 = await viewer.createGeometry(GeometryHelper.cube());
await viewer.setParent(cube1, cube2);
final parent = await viewer.getParent(cube1);
expect(parent, cube2);
});
test('getAncestor returns the ultimate parent entity', () async {
var viewer = await testHelper.createViewer();
final grandparent = await viewer.createGeometry(GeometryHelper.cube());
final parent = await viewer.createGeometry(GeometryHelper.cube());
final child = await viewer.createGeometry(GeometryHelper.cube());
await viewer.setParent(child, parent);
await viewer.setParent(parent, grandparent);
expect(await viewer.getAncestor(child), grandparent);
});
test('set position based on screenspace coord', () async {
var viewer = await testHelper.createViewer();
print(await viewer.getCameraFov(true));
await viewer.createIbl(1.0, 1.0, 1.0, 1000);
await viewer.setCameraPosition(0, 0, 6);
await viewer.setBackgroundColor(0.0, 0.0, 1.0, 1.0);
// Create the cube geometry
final cube = await viewer.createGeometry(GeometryHelper.cube());
// await viewer.setPosition(cube, -0.05, 0.04, 5.9);
// await viewer.setPosition(cube, -2.54, 2.54, 0);
await viewer.queuePositionUpdateFromViewportCoords(cube, 0, 0);
// we need an explicit render call here to process the transform queue
await viewer.render(testHelper.swapChain);
await testHelper.capture(viewer, "set_position_from_viewport_coords");
});
});
group("layers & overlays", () {
test('enable grid overlay', () async {
var viewer = await testHelper.createViewer();
await viewer.setBackgroundColor(0, 0, 0, 1);
await viewer
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
await viewer.setCameraPosition(0, 2, 0);
await testHelper.capture(viewer, "grid_overlay_default");
await viewer.setLayerVisibility(7, true);
await testHelper.capture(viewer, "grid_overlay_enabled");
await viewer.setLayerVisibility(7, false);
await testHelper.capture(viewer, "grid_overlay_disabled");
});
test('load glb from buffer with layer', () async {
var viewer = await testHelper.createViewer();
await viewer.setBackgroundColor(1, 0, 1, 1);
await viewer.setCameraPosition(0, 2, 5);
await viewer
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
var buffer = File("${testHelper.testDir}/cube.glb").readAsBytesSync();
var model = await viewer.loadGlbFromBuffer(buffer, layer: 1);
await testHelper.capture(
viewer, "load_glb_from_buffer_with_layer_disabled");
await viewer.setLayerVisibility(1, true);
await testHelper.capture(
viewer, "load_glb_from_buffer_with_layer_enabled");
});
test('change layer visibility at runtime', () async {
var viewer = await testHelper.createViewer();
await viewer.setBackgroundColor(1, 0, 1, 1);
await viewer.setCameraPosition(0, 2, 5);
await viewer
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
var cube = await viewer.createGeometry(GeometryHelper.cube());
await testHelper.capture(
viewer, "change_layer_visibility_at_runtime_default");
// all entities set to layer 0 by default, so this should now be invisible
await viewer.setLayerVisibility(0, false);
await testHelper.capture(
viewer, "change_layer_visibility_at_runtime_layer0_invisible");
// now change the visibility layer to 5, should be invisible
await viewer.setVisibilityLayer(cube, 5);
await testHelper.capture(
viewer, "change_layer_visibility_at_runtime_layer5_invisible");
// now toggle layer 5 visibility, cube should now be visible
await viewer.setLayerVisibility(5, true);
await testHelper.capture(
viewer, "change_layer_visibility_at_runtime_layer5_visible");
});
});
// test('point light', () async {
// var model = await viewer.loadGlb("${testHelper.testDir}/cube.glb");
// await viewer.transformToUnitCube(model);
// var light = await viewer.addLight(
// LightType.POINT, 6500, 1000000, 0, 2, 0, 0, -1, 0,
// falloffRadius: 10.0);
// await viewer.setBackgroundColor(0.0, 0.0, 0.0, 1.0);
// await viewer.setCameraPosition(0, 1, 5);
// await viewer
// .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
// await viewer.setRendering(true);
// await testHelper.capture(viewer, "point_light");
// await viewer.setRendering(false);
// });
// test('set point light position', () async {
// var model = await viewer.loadGlb("${testHelper.testDir}/cube.glb");
// await viewer.transformToUnitCube(model);
// var light = await viewer.addLight(
// LightType.POINT, 6500, 1000000, 0, 2, 0, 0, -1, 0,
// falloffRadius: 10.0);
// await viewer.setLightPosition(light, 0.5, 2, 0);
// await viewer.setBackgroundColor(0.0, 0.0, 0.0, 1.0);
// await viewer.setCameraPosition(0, 1, 5);
// await viewer
// .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
// await viewer.setRendering(true);
// await testHelper.capture(viewer, "move_point_light");
// await viewer.setRendering(false);
// });
// test('directional light', () async {
// var model = await viewer.loadGlb("${testHelper.testDir}/cube.glb");
// await viewer.transformToUnitCube(model);
// var light = await viewer.addLight(
// LightType.SUN, 6500, 1000000, 0, 0, 0, 0, -1, 0);
// await viewer.setBackgroundColor(0.0, 0.0, 0.0, 1.0);
// await viewer.setCameraPosition(0, 1, 5);
// await viewer
// .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
// await viewer.setRendering(true);
// await testHelper.capture(viewer, "directional_light");
// await viewer.setRendering(false);
// });
// test('set directional light direction', () async {
// var model = await viewer.loadGlb("${testHelper.testDir}/cube.glb");
// await viewer.transformToUnitCube(model);
// var light = await viewer.addLight(
// LightType.SUN, 6500, 1000000, 0, 0, 0, 0, -1, 0);
// await viewer.setLightDirection(light, Vector3(-1, -1, -1));
// await viewer.setBackgroundColor(0.0, 0.0, 0.0, 1.0);
// await viewer.setCameraPosition(0, 1, 5);
// await viewer
// .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
// await viewer.setRendering(true);
// await testHelper.capture(viewer, "set_directional_light_direction");
// await viewer.setRendering(false);
// });
group("stencil", () {
test('set stencil highlight for glb', () async {
final viewer = await testHelper.createViewer();
var model = await viewer.loadGlb("${testHelper.testDir}/cube.glb", keepData: true);
await viewer.setPostProcessing(true);
var light = await viewer.addLight(
LightType.SUN, 6500, 1000000, 0, 0, 0, 0, -1, 0);
await viewer.setLightDirection(light, Vector3(0, 1, -1));
await viewer.setBackgroundColor(0.0, 1.0, 0.0, 1.0);
await viewer.setCameraPosition(0, -1, 5);
await viewer
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), pi / 8));
await viewer.setStencilHighlight(model);
await testHelper.capture(viewer, "stencil_highlight_glb");
});
test('set stencil highlight for geometry', () async {
var viewer = await testHelper.createViewer();
await viewer.setPostProcessing(true);
await viewer.setBackgroundColor(0.0, 1.0, 0.0, 1.0);
await viewer.setCameraPosition(0, 2, 5);
await viewer
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
var cube = await viewer.createGeometry(GeometryHelper.cube());
await viewer.setStencilHighlight(cube);
await testHelper.capture(viewer, "stencil_highlight_geometry");
await viewer.removeStencilHighlight(cube);
await testHelper.capture(viewer, "stencil_highlight_geometry_remove");
});
test('set stencil highlight for gltf asset', () async {
var viewer = await testHelper.createViewer();
await viewer.setPostProcessing(true);
await viewer.setBackgroundColor(0.0, 1.0, 0.0, 1.0);
await viewer.setCameraPosition(0, 1, 5);
await viewer
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
var cube1 = await viewer.loadGlb("${testHelper.testDir}/cube.glb", keepData: true);
await viewer.transformToUnitCube(cube1);
await viewer.setStencilHighlight(cube1);
await testHelper.capture(viewer, "stencil_highlight_gltf");
await viewer.removeStencilHighlight(cube1);
await testHelper.capture(viewer, "stencil_highlight_gltf_removed");
});
test('set stencil highlight for multiple geometry ', () async {
var viewer = await testHelper.createViewer();
await viewer.setPostProcessing(true);
await viewer.setBackgroundColor(0.0, 1.0, 0.0, 1.0);
await viewer.setCameraPosition(0, 1, 5);
await viewer
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
var cube1 = await viewer.createGeometry(GeometryHelper.cube());
var cube2 = await viewer.createGeometry(GeometryHelper.cube());
await viewer.setPosition(cube2, 0.5, 0.5, 0);
await viewer.setStencilHighlight(cube1);
await viewer.setStencilHighlight(cube2, r: 0.0, g: 0.0, b: 1.0);
await testHelper.capture(viewer, "stencil_highlight_multiple_geometry");
await viewer.removeStencilHighlight(cube1);
await viewer.removeStencilHighlight(cube2);
await testHelper.capture(
viewer, "stencil_highlight_multiple_geometry_removed");
});
test('set stencil highlight for multiple gltf assets ', () async {
var viewer = await testHelper.createViewer();
await viewer.setPostProcessing(true);
await viewer.setBackgroundColor(0.0, 1.0, 0.0, 1.0);
await viewer.setCameraPosition(0, 1, 5);
await viewer
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
var cube1 = await viewer.loadGlb("${testHelper.testDir}/cube.glb", keepData: true);
await viewer.transformToUnitCube(cube1);
var cube2 = await viewer.loadGlb("${testHelper.testDir}/cube.glb", keepData: true);
await viewer.transformToUnitCube(cube2);
await viewer.setPosition(cube2, 0.5, 0.5, 0);
await viewer.setStencilHighlight(cube1);
await viewer.setStencilHighlight(cube2, r: 0.0, g: 0.0, b: 1.0);
await testHelper.capture(viewer, "stencil_highlight_multiple_geometry");
await viewer.removeStencilHighlight(cube1);
await viewer.removeStencilHighlight(cube2);
await testHelper.capture(
viewer, "stencil_highlight_multiple_geometry_removed");
});
});
group("texture", () {
test("create/apply/dispose texture", () async {
var viewer = await testHelper.createViewer();
var textureData =
File("${testHelper.testDir}/assets/cube_texture_512x512.png").readAsBytesSync();
var texture = await viewer.createTexture(textureData);
await viewer.setBackgroundColor(0.0, 0.0, 0.0, 1.0);
await viewer.addDirectLight(
DirectLight.sun(direction: Vector3(0, -10, -1)..normalize()));
await viewer.addDirectLight(DirectLight.spot(
intensity: 1000000,
position: Vector3(0, 0, 1.5),
direction: Vector3(0, 0, -1)..normalize(),
falloffRadius: 10,
spotLightConeInner: 1,
spotLightConeOuter: 1));
await viewer.setCameraPosition(0, 2, 6);
await viewer
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
var materialInstance =
await viewer.createUbershaderMaterialInstance(unlit: true);
var cube = await viewer.createGeometry(GeometryHelper.cube(),
materialInstance: materialInstance);
await viewer.setPostProcessing(true);
await viewer.setToneMapping(ToneMapper.LINEAR);
await viewer.applyTexture(texture, cube,
materialIndex: 0, parameterName: "baseColorMap");
await testHelper.capture(viewer, "texture_applied_to_geometry");
await viewer.removeEntity(cube);
await viewer.destroyTexture(texture);
});
});
// group("unproject", () {
// test("unproject", () async {
// final dimensions = (width: 1280, height: 768);
// var viewer = await testHelper.createViewer(viewportDimensions: dimensions);
// await viewer.setPostProcessing(false);
// // await viewer.setToneMapping(ToneMapper.LINEAR);
// await viewer.setBackgroundColor(1.0, 1.0, 1.0, 1.0);
// // await viewer.createIbl(1.0, 1.0, 1.0, 100000);
// await viewer.addLight(LightType.SUN, 6500, 100000, -2, 0, 0, 1, -1, 0);
// await viewer.addLight(LightType.SPOT, 6500, 500000, 0, 0, 2, 0, 0, -1,
// falloffRadius: 10, spotLightConeInner: 1.0, spotLightConeOuter: 2.0);
// await viewer.setCameraPosition(-3, 4, 6);
// await viewer.setCameraRotation(
// Quaternion.axisAngle(Vector3(0, 1, 0), -pi / 8) *
// Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 6));
// var cube =
// await viewer.createGeometry(GeometryHelper.cube(), keepData: true);
// await viewer.setMaterialPropertyFloat4(
// cube, "baseColorFactor", 0, 1.0, 1.0, 1.0, 1.0);
// var textureData =
// File("${testHelper.testDir}/assets/cube_texture_512x512.png").readAsBytesSync();
// var texture = await viewer.createTexture(textureData);
// await viewer.applyTexture(texture, cube,
// materialIndex: 0, parameterName: "baseColorMap");
// var numFrames = 60;
// // first do the render
// for (int i = 0; i < numFrames; i++) {
// await viewer.setCameraPosition(-3 + (i / numFrames * 2), 4, 6);
// await viewer.setCameraRotation(
// Quaternion.axisAngle(Vector3(0, 1, 0), -pi / 8) *
// Quaternion.axisAngle(
// Vector3(1, 0, 0), -pi / 6 - (i / numFrames * pi / 6)));
// var rendered = await testHelper.capture(viewer, "unproject_render$i");
// var renderPng =
// await pixelsToPng(rendered, dimensions.width, dimensions.height);
// File("${outDir.path}/unproject_render${i}.png")
// .writeAsBytesSync(renderPng);
// }
// // then go off and convert the video
// // now unproject the render back onto the geometry
// final textureSize = (width: 1280, height: 768);
// var pixels = <Uint8List>[];
// // note we skip the first frame
// for (int i = 0; i < numFrames; i++) {
// await viewer.setCameraPosition(-3 + (i / numFrames * 2), 4, 6);
// await viewer.setCameraRotation(
// Quaternion.axisAngle(Vector3(0, 1, 0), -pi / 8) *
// Quaternion.axisAngle(
// Vector3(1, 0, 0), -pi / 6 - (i / numFrames * pi / 6)));
// var input = pngToPixelBuffer(File(
// "${outDir.path}/a8c317af-6081-4848-8a06-f6b69bc57664_${i + 1}.png")
// .readAsBytesSync());
// var pixelBuffer = await (await viewer as ThermionViewerFFI).unproject(
// cube,
// input,
// dimensions.width,
// dimensions.height,
// textureSize.width,
// textureSize.height);
// // var png = await pixelsToPng(Uint8List.fromList(pixelBuffer),
// // dimensions.width, dimensions.height);
// await savePixelBufferToBmp(
// pixelBuffer,
// textureSize.width,
// textureSize.height,
// p.join(outDir.path, "unprojected_texture${i}.bmp"));
// pixels.add(pixelBuffer);
// if (i > 10) {
// break;
// }
// }
// // }
// final aggregatePixelBuffer = medianImages(pixels);
// await savePixelBufferToBmp(aggregatePixelBuffer, textureSize.width,
// textureSize.height, "unproject_texture.bmp");
// var pixelBufferPng = await pixelsToPng(
// Uint8List.fromList(aggregatePixelBuffer),
// dimensions.width,
// dimensions.height);
// File("${outDir.path}/unproject_texture.png")
// .writeAsBytesSync(pixelBufferPng);
// await viewer.setPostProcessing(true);
// await viewer.setToneMapping(ToneMapper.LINEAR);
// final unlit = await viewer.createUnlitMaterialInstance();
// await viewer.removeEntity(cube);
// cube = await viewer.createGeometry(GeometryHelper.cube(),
// materialInstance: unlit);
// var reconstructedTexture = await viewer.createTexture(pixelBufferPng);
// await viewer.applyTexture(reconstructedTexture, cube);
// await viewer.setCameraRotation(
// Quaternion.axisAngle(Vector3(0, 1, 0), -pi / 8) *
// Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 6));
// await testHelper.capture(viewer, "unproject_reconstruct");
// // now re-render
// for (int i = 0; i < numFrames; i++) {
// await viewer.setCameraPosition(-3 + (i / numFrames * 2), 4, 6);
// await viewer.setCameraRotation(
// Quaternion.axisAngle(Vector3(0, 1, 0), -pi / 8) *
// Quaternion.axisAngle(
// Vector3(1, 0, 0), -pi / 6 - (i / numFrames * pi / 6)));
// var rendered = await testHelper.capture(viewer, "unproject_rerender$i");
// var renderPng =
// await pixelsToPng(rendered, dimensions.width, dimensions.height);
// File("${outDir.path}/unproject_rerender${i}.png")
// .writeAsBytesSync(renderPng);
// }
// }, timeout: Timeout(Duration(minutes: 2)));
// });
}
+23
View File
@@ -31,6 +31,29 @@ void main() async {
await viewer.dispose(); await viewer.dispose();
}); });
test('unlit fixed size material', () async {
var viewer = await testHelper.createViewer();
await viewer.setCameraPosition(0, 0, 6);
await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
await viewer.setPostProcessing(true);
await viewer.setToneMapping(ToneMapper.LINEAR);
var materialInstance = await viewer.createUnlitFixedSizeMaterialInstance();
var cube = await viewer.createGeometry(GeometryHelper.cube(),
materialInstance: materialInstance);
await viewer.setMaterialPropertyFloat4(
cube, "baseColorFactor", 0, 0.0, 1.0, 0.0, 1.0);
await testHelper.capture(viewer, "unlit_fixed_size_default_scale");
await materialInstance.setParameterFloat("scale", 10.0);
await testHelper.capture(viewer, "unlit_fixed_size_scale_10");
await viewer.dispose();
});
test('apply texture to custom ubershader material instance', () async { test('apply texture to custom ubershader material instance', () async {
var viewer = await testHelper.createViewer(); var viewer = await testHelper.createViewer();
await viewer.addLight(LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1); await viewer.addLight(LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);
-1
View File
@@ -1,4 +1,3 @@
import 'dart:async';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'helpers.dart'; import 'helpers.dart';
+14 -7
View File
@@ -1,3 +1,5 @@
// ignore_for_file: unused_local_variable
import 'dart:async'; import 'dart:async';
import 'package:test/test.dart'; import 'package:test/test.dart';
@@ -15,7 +17,6 @@ void main() async {
expect(await view.getCamera(), isNotNull); expect(await view.getCamera(), isNotNull);
await viewer.dispose(); await viewer.dispose();
}); });
test('one swapchain, render view to render target', () async { test('one swapchain, render view to render target', () async {
@@ -37,7 +38,6 @@ void main() async {
"default_swapchain_default_view_render_target"); "default_swapchain_default_view_render_target");
await viewer.dispose(); await viewer.dispose();
}); });
test('create secondary view, default swapchain', () async { test('create secondary view, default swapchain', () async {
@@ -113,22 +113,29 @@ void main() async {
test('pick', () async { test('pick', () async {
var viewer = await testHelper.createViewer( var viewer = await testHelper.createViewer(
bg: kRed, cameraPosition: Vector3(0, 0, 5)); bg: kRed, cameraPosition: Vector3(0, 0, 3));
final view = await viewer.getViewAt(0);
await view.setRenderable(true, testHelper.swapChain);
final cube = await viewer.createGeometry(GeometryHelper.cube()); final cube = await viewer.createGeometry(GeometryHelper.cube());
await testHelper.capture(viewer, "view_pick");
final completer = Completer(); final completer = Completer();
late StreamSubscription listener; late StreamSubscription listener;
listener = viewer.pickResult.listen((result) async { listener = viewer.pickResult.listen((result) async {
completer.complete(result.entity); completer.complete(result.entity);
await listener.cancel(); await listener.cancel();
print("Pick result : ${result.fragX} ${result.fragY} ${result.fragZ}");
}); });
viewer.pick(250, 250); await viewer.pick(250, 250);
for (int i = 0; i < 10; i++) { for (int i = 0; i < 3; i++) {
await viewer.requestFrame(); await viewer.render();
await Future.delayed(Duration(milliseconds: 100)); await Future.delayed(Duration(milliseconds: 16));
} }
expect(completer.isCompleted, true); expect(completer.isCompleted, true);
-81
View File
@@ -1,81 +0,0 @@
import 'dart:ffi';
import 'dart:io';
import 'dart:math';
import 'package:ffi/ffi.dart';
import 'package:test/test.dart';
import 'swift/swift_bindings.g.dart';
import 'package:thermion_dart/src/utils/src/dart_resources.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
import 'package:thermion_dart/src/viewer/src/ffi/thermion_viewer_ffi.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart';
/// Test files are run in a variety of ways, find this package root in all.
///
/// Test files can be run from source from any working directory. The Dart SDK
/// `tools/test.py` runs them from the root of the SDK for example.
///
/// Test files can be run from dill from the root of package. `package:test`
/// does this.
Uri findPackageRoot(String packageName) {
final script = Platform.script;
final fileName = script.name;
// We're likely running from source.
var directory = script.resolve('.');
while (true) {
final dirName = directory.name;
if (dirName == packageName) {
return directory;
}
final parent = directory.resolve('..');
if (parent == directory) break;
directory = parent;
}
throw StateError("Could not find package root for package '$packageName'. "
'Tried finding the package root via Platform.script '
"'${Platform.script.toFilePath()}' and Directory.current "
"'${Directory.current.uri.toFilePath()}'.");
}
extension on Uri {
String get name => pathSegments.where((e) => e != '').last;
}
late String testDir;
void main() async {
final packageUri = findPackageRoot('thermion_dart');
testDir = Directory("${packageUri.toFilePath()}/test").path;
final lib = ThermionTexture1(DynamicLibrary.open(
'${packageUri.toFilePath()}/native/lib/macos/swift/libthermion_swift.dylib'));
final object = ThermionTexture.new1(lib);
object.initWithWidth_height_(500, 500);
final resourceLoader = calloc<ResourceLoaderWrapper>(1);
var loadToOut = NativeCallable<
Void Function(Pointer<Char>,
Pointer<ResourceBuffer>)>.listener(DartResourceLoader.loadResource);
resourceLoader.ref.loadToOut = loadToOut.nativeFunction;
var freeResource = NativeCallable<Void Function(ResourceBuffer)>.listener(
DartResourceLoader.freeResource);
resourceLoader.ref.freeResource = freeResource.nativeFunction;
var viewer = ThermionViewerFFI(resourceLoader: resourceLoader.cast<Void>());
await viewer.initialized;
await viewer.createSwapChain(500, 500);
await viewer.createRenderTarget(500, 500, object.metalTextureAddress);
await viewer.updateViewportAndCameraProjection(500, 500);
group('viewport', () {
test('viewport', () async {
var entity = await viewer.createGeometry(GeometryHelper.cube());
await viewer.setCameraPosition(0.0, 0.0, 4.0);
await viewer.setCameraRotation(Quaternion.axisAngle(Vector3(0,0,1), pi/2));
await viewer.queueRelativePositionUpdateWorldAxis(
entity, 250.0, 250.0, 1, 0, 0);
});
});
}
-69
View File
@@ -1,69 +0,0 @@
import 'dart:ffi';
import 'dart:io';
import 'package:ffi/ffi.dart';
import 'swift/swift_bindings.g.dart';
import 'package:thermion_dart/src/utils/src/dart_resources.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
import 'package:thermion_dart/src/viewer/src/ffi/thermion_viewer_ffi.dart';
/// Test files are run in a variety of ways, find this package root in all.
///
/// Test files can be run from source from any working directory. The Dart SDK
/// `tools/test.py` runs them from the root of the SDK for example.
///
/// Test files can be run from dill from the root of package. `package:test`
/// does this.
Uri findPackageRoot(String packageName) {
final script = Platform.script;
final fileName = script.name;
// We're likely running from source.
var directory = script.resolve('.');
while (true) {
final dirName = directory.name;
if (dirName == packageName) {
return directory;
}
final parent = directory.resolve('..');
if (parent == directory) break;
directory = parent;
}
throw StateError("Could not find package root for package '$packageName'. "
'Tried finding the package root via Platform.script '
"'${Platform.script.toFilePath()}' and Directory.current "
"'${Directory.current.uri.toFilePath()}'.");
}
extension on Uri {
String get name => pathSegments.where((e) => e != '').last;
}
late String testDir;
void main() async {
final packageUri = findPackageRoot('thermion_dart');
testDir = Directory("${packageUri.toFilePath()}/test").path;
final lib = ThermionTexture1(DynamicLibrary.open(
'${packageUri.toFilePath()}/native/lib/macos/swift/libthermion_swift.dylib'));
final object = ThermionTexture.new1(lib);
object.initWithWidth_height_(500, 500);
final resourceLoader = calloc<ResourceLoaderWrapper>(1);
var loadToOut = NativeCallable<
Void Function(Pointer<Char>,
Pointer<ResourceBuffer>)>.listener(DartResourceLoader.loadResource);
resourceLoader.ref.loadToOut = loadToOut.nativeFunction;
var freeResource = NativeCallable<Void Function(ResourceBuffer)>.listener(
DartResourceLoader.freeResource);
resourceLoader.ref.freeResource = freeResource.nativeFunction;
var viewer = ThermionViewerFFI(resourceLoader: resourceLoader.cast<Void>());
await viewer.initialized;
await viewer.createSwapChain(500, 500);
await viewer.createRenderTarget(500, 500, object.metalTextureAddress);
await viewer.updateViewportAndCameraProjection(500, 500);
}
@@ -1,12 +0,0 @@
*.a filter=lfs diff=lfs merge=lfs -text
*.lib filter=lfs diff=lfs merge=lfs -text
*.dll filter=lfs diff=lfs merge=lfs -text
*.pdb filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.uberz filter=lfs diff=lfs merge=lfs -text
*.bin filter=lfs diff=lfs merge=lfs -text
*.ktx filter=lfs diff=lfs merge=lfs -text
*.blend filter=lfs diff=lfs merge=lfs -text
*.gltf filter=lfs diff=lfs merge=lfs -text
*.glb filter=lfs diff=lfs merge=lfs -text
@@ -1,3 +1,62 @@
## 0.2.1-dev.16
- Update a dependency to the latest release.
## 0.2.1-dev.15
- **FIX**: multiply coordinates by pixelRatio for scale events.
## 0.2.1-dev.14
- Update a dependency to the latest release.
## 0.2.1-dev.13
- Update a dependency to the latest release.
## 0.2.1-dev.12
- **FIX**: (flutter) (windows) remove deleted source file from Windows CMakeLists.
## 0.2.1-dev.11
- Update a dependency to the latest release.
## 0.2.1-dev.10
> Note: This release has breaking changes.
- **REFACTOR**: continual refactor to support multiple render targets.
- **FIX**: fix all Windows warnings so apps will compile with /WX.
- **FIX**: use internal Set for determining first ThermionTextureWidget to call requestFrame and cleanup destruction logic.
- **FIX**: (flutter) pass ThermionFlutterOptions to ThermionWidget, use dpr for resizeTexture, delete unnecessary TransparencyPainter class.
- **FIX**: (flutter/web) use window.devicePixelRatio for viewport.
- **FIX**: (flutter) desktop gesture detector changes for new Gizmo methods.
- **FEAT**: (flutter) (windows) add DestroyRenderingSurface method.
- **FEAT**: (flutter) (windows) add DestroyRenderingSurface method.
- **FEAT**: (flutter) (windows) add DestroyRenderingSurface method.
- **FEAT**: (flutter) (windows) add Destroy() to BackingWindow.
- **FEAT**: camera and resizing improvements.
- **FEAT**: support multiple ThermionWidget on Android.
- **FEAT**: use imported texture on iOS.
- **FEAT**: working implementation of multiple widgets on macos.
- **FEAT**: add rendering check to ThermionWidget ticker.
- **FEAT**: allow passing null options to ThermionWidget.
- **FEAT**: (flutter) (web) if importCanvasAsWidget is false, render transparency.
- **FEAT**: add createViewerWithOptions to ThermionFlutterPlugin and mark createViewer as deprecated.
- **FEAT**: add createViewerWithOptions to ThermionFlutterPlugin and mark createViewer as deprecated.
- **FEAT**: highlight gizmo on hover.
- **BREAKING** **FIX**: remove EntityControllerMouseWidget (replace with GestureHandler).
- **BREAKING** **FIX**: (flutter) pass pixelRatio to createTexture.
- **BREAKING** **FIX**: (flutter) pass pixelRatio to createTexture.
- **BREAKING** **FEAT**: expose velocity, rotation and timestamp for scale events in listener. accept rotationSensitivity/zoomSensitivity for FixedOrbitRotateInputHandlerDelegate.
- **BREAKING** **FEAT**: (web) (flutter) create canvas when createViewer is called (no longer need to manually add canvas element to web HTML).
- **BREAKING** **FEAT**: resize canvas on web.
- **BREAKING** **CHORE**: remove superseded HardwareKeyboard* classes.
- **BREAKING** **CHORE**: (flutter) cleanup for pub.dev publishing.
- **BREAKING** **CHORE**: remove EntityListWidget - will replace with new Scene.
- **BREAKING** **CHORE**: rename controller to viewer in gesture detector widgets.
## 0.2.1-dev.9 ## 0.2.1-dev.9
> Note: This release has breaking changes. > Note: This release has breaking changes.
+1 -1
View File
@@ -3,7 +3,7 @@
<p align="center"> <p align="center">
<a href="https://thermion.dev/quickstart">Quickstart (Flutter)</a> • <a href="https://thermion.dev/quickstart">Quickstart (Flutter)</a> •
<a href="https://thermion.dev/quickstart">Documentation</a> • <a href="https://thermion.dev/quickstart">Documentation</a> •
<a href="https://thermion.dev/examples">Showcase</a> • <a href="https://thermion.dev/showcase">Showcase</a> •
<a href="https://dartpad.thermion.dev/">Playground</a> • <a href="https://dartpad.thermion.dev/">Playground</a> •
<a href="https://discord.gg/h2VdDK3EAQ">Discord</a> <a href="https://discord.gg/h2VdDK3EAQ">Discord</a>
</p> </p>
@@ -165,19 +165,21 @@ class _MobileListenerWidgetState extends State<_MobileListenerWidget> {
}, },
onScaleStart: (details) async { onScaleStart: (details) async {
await widget.inputHandler.onScaleStart( await widget.inputHandler.onScaleStart(
details.localFocalPoint.toVector2(), details.pointerCount); details.localFocalPoint.toVector2() * widget.pixelRatio, details.pointerCount, details.sourceTimeStamp);
}, },
onScaleUpdate: (ScaleUpdateDetails details) async { onScaleUpdate: (ScaleUpdateDetails details) async {
await widget.inputHandler.onScaleUpdate( await widget.inputHandler.onScaleUpdate(
details.localFocalPoint.toVector2(), details.localFocalPoint.toVector2() * widget.pixelRatio,
details.focalPointDelta.toVector2(), details.focalPointDelta.toVector2() * widget.pixelRatio,
details.horizontalScale, details.horizontalScale,
details.verticalScale, details.verticalScale,
details.scale, details.scale,
details.pointerCount); details.pointerCount,
details.rotation,
details.sourceTimeStamp);
}, },
onScaleEnd: (details) async { onScaleEnd: (details) async {
await widget.inputHandler.onScaleEnd(details.pointerCount); await widget.inputHandler.onScaleEnd(details.pointerCount, details.scaleVelocity);
}, },
child: widget.child); child: widget.child);
} }
@@ -68,12 +68,22 @@ class _ThermionTextureWidgetState extends State<ThermionTextureWidget> {
var dpr = MediaQuery.of(context).devicePixelRatio; var dpr = MediaQuery.of(context).devicePixelRatio;
var size = ((context.findRenderObject()) as RenderBox).size; var size = ((context.findRenderObject()) as RenderBox).size;
_logger.info(
"Widget size in logical pixels ${size} (pixel ratio : $dpr)");
var width = (size.width * dpr).ceil(); var width = (size.width * dpr).ceil();
var height = (size.height * dpr).ceil(); var height = (size.height * dpr).ceil();
_logger.info(
"Target texture dimensions ${width}x${height} (pixel ratio : $dpr)");
_texture = await ThermionFlutterPlatform.instance _texture = await ThermionFlutterPlatform.instance
.createTexture(widget.view, width, height); .createTexture(widget.view, width, height);
_logger.info(
"Actual texture dimensions ${_texture!.width}x${_texture!.height} (pixel ratio : $dpr)");
await widget.view.updateViewport(_texture!.width, _texture!.height); await widget.view.updateViewport(_texture!.width, _texture!.height);
try { try {
@@ -177,6 +187,9 @@ class _ThermionTextureWidgetState extends State<ThermionTextureWidget> {
var newWidth = newSize.width.ceil(); var newWidth = newSize.width.ceil();
var newHeight = newSize.height.ceil(); var newHeight = newSize.height.ceil();
_logger.info(
"Resizing texture to dimensions ${newWidth}x${newHeight} (pixel ratio : $dpr)");
await _texture?.resize( await _texture?.resize(
newWidth, newWidth,
newHeight, newHeight,
@@ -184,6 +197,9 @@ class _ThermionTextureWidgetState extends State<ThermionTextureWidget> {
0, 0,
); );
_logger.info(
"Resized texture to dimensions ${_texture!.width}x${_texture!.height} (pixel ratio : $dpr)");
await widget.view.updateViewport(_texture!.width, _texture!.height); await widget.view.updateViewport(_texture!.width, _texture!.height);
await widget.onResize?.call( await widget.onResize?.call(
@@ -1,6 +1,6 @@
name: thermion_flutter name: thermion_flutter
description: Flutter plugin for 3D rendering with the Thermion toolkit. description: Flutter plugin for 3D rendering with the Thermion toolkit.
version: 0.2.1-dev.9 version: 0.2.1-dev.16
homepage: https://thermion.dev homepage: https://thermion.dev
repository: https://github.com/nmfisher/thermion repository: https://github.com/nmfisher/thermion
@@ -17,10 +17,10 @@ dependencies:
plugin_platform_interface: ^2.0.0 plugin_platform_interface: ^2.0.0
ffi: ^2.1.2 ffi: ^2.1.2
animation_tools_dart: ^0.1.0 animation_tools_dart: ^0.1.0
thermion_dart: ^0.2.1-dev.0.0.10 thermion_dart: ^0.2.1-dev.0.0.16
thermion_flutter_platform_interface: ^0.2.1-dev.9 thermion_flutter_platform_interface: ^0.2.1-dev.16
thermion_flutter_ffi: ^0.2.1-dev.9 thermion_flutter_ffi: ^0.2.1-dev.16
thermion_flutter_web: ^0.2.0 thermion_flutter_web: ^0.2.0+7
logging: ^1.2.0 logging: ^1.2.0
web: ^1.0.0 web: ^1.0.0
@@ -33,7 +33,6 @@ add_library(${PLUGIN_NAME} SHARED
"include/thermion_flutter/thermion_flutter_plugin_c_api.h" "include/thermion_flutter/thermion_flutter_plugin_c_api.h"
"thermion_flutter_plugin_c_api.cpp" "thermion_flutter_plugin_c_api.cpp"
${PLUGIN_SOURCES} ${PLUGIN_SOURCES}
"include/material/image.c"
) )
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
@@ -1,12 +0,0 @@
.global IMAGE_IMAGE_OFFSET;
.global IMAGE_IMAGE_SIZE;
.global IMAGE_PACKAGE
.section .rodata
IMAGE_PACKAGE:
.incbin "image.bin"
IMAGE_IMAGE_OFFSET:
.int 0
IMAGE_IMAGE_SIZE:
.int 13622
@@ -1,12 +0,0 @@
.global _IMAGE_IMAGE_OFFSET;
.global _IMAGE_IMAGE_SIZE;
.global _IMAGE_PACKAGE
.section __TEXT,__const
_IMAGE_PACKAGE:
.incbin "image.bin"
_IMAGE_IMAGE_OFFSET:
.int 0
_IMAGE_IMAGE_SIZE:
.int 13622
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5ad7dec6e1c92a6ee102556217cf7d13363fc4cf9f4b8a9e0f16dbb7208b5ee8
size 13622
@@ -1,691 +0,0 @@
#include <stdint.h>
const uint8_t IMAGE_PACKAGE[] = {
// IMAGE
0x53, 0x52, 0x45, 0x56, 0x5f, 0x54, 0x41, 0x4d, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x54, 0x41, 0x45, 0x46,
0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x45, 0x4d, 0x41, 0x4e, 0x5f, 0x54, 0x41, 0x4d, 0x06, 0x00, 0x00,
0x00, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x00, 0x4c, 0x44, 0x4d, 0x53, 0x5f, 0x54, 0x41, 0x4d, 0x04, 0x00, 0x00, 0x00, 0x06,
0x00, 0x00, 0x00, 0x4e, 0x4d, 0x4f, 0x44, 0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x49, 0x4e, 0x55,
0x5f, 0x54, 0x41, 0x4d, 0x87, 0x00, 0x00, 0x00, 0x08, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72,
0x6d, 0x73, 0x00, 0x00, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x00, 0x01,
0x4c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x00, 0x04, 0x53, 0x68, 0x61, 0x64,
0x6f, 0x77, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x00, 0x05, 0x46, 0x72, 0x6f, 0x78, 0x65, 0x6c, 0x52, 0x65,
0x63, 0x6f, 0x72, 0x64, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x00, 0x06, 0x42, 0x6f, 0x6e, 0x65, 0x73, 0x55,
0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x00, 0x02, 0x4d, 0x6f, 0x72, 0x70, 0x68, 0x69, 0x6e, 0x67, 0x55, 0x6e, 0x69,
0x66, 0x6f, 0x72, 0x6d, 0x73, 0x00, 0x03, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d,
0x73, 0x00, 0x07, 0x50, 0x4d, 0x41, 0x53, 0x5f, 0x54, 0x41, 0x4d, 0xc3, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x07, 0x07,
0x01, 0x02, 0x09, 0x07, 0x01, 0x0a, 0x00, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x4d,
0x61, 0x70, 0x00, 0x01, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x66, 0x72, 0x6f, 0x78, 0x65, 0x6c, 0x73, 0x00, 0x02, 0x6c,
0x69, 0x67, 0x68, 0x74, 0x5f, 0x69, 0x62, 0x6c, 0x44, 0x46, 0x47, 0x00, 0x03, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x69,
0x62, 0x6c, 0x53, 0x70, 0x65, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x00, 0x04, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x73, 0x73,
0x61, 0x6f, 0x00, 0x05, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x73, 0x73, 0x72, 0x00, 0x06, 0x6c, 0x69, 0x67, 0x68, 0x74,
0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x00, 0x07, 0x6d, 0x6f, 0x72, 0x70, 0x68, 0x54, 0x61, 0x72,
0x67, 0x65, 0x74, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x00,
0x08, 0x6d, 0x6f, 0x72, 0x70, 0x68, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x74,
0x61, 0x6e, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x00, 0x09, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72,
0x61, 0x6d, 0x73, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x00, 0x20, 0x42, 0x49, 0x55, 0x5f, 0x54, 0x41, 0x4d, 0x59, 0x00,
0x00, 0x00, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x00, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x11, 0x02, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x73, 0x68, 0x6f, 0x77, 0x49, 0x6d, 0x61, 0x67, 0x65,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x20, 0x42, 0x49, 0x53, 0x5f, 0x54, 0x41, 0x4d, 0x21,
0x00, 0x00, 0x00, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x00, 0x00, 0x02, 0x03, 0x00, 0x53, 0x4e, 0x4f, 0x43,
0x5f, 0x54, 0x41, 0x4d, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x42, 0x55, 0x53,
0x5f, 0x54, 0x41, 0x4d, 0x17, 0x00, 0x00, 0x00, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61,
0x6d, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x53, 0x4f, 0x44, 0x5f, 0x54, 0x41, 0x4d, 0x01,
0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x4f, 0x44, 0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x45, 0x4c,
0x42, 0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x4d, 0x52, 0x54, 0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00,
0x00, 0x00, 0x00, 0x4c, 0x46, 0x45, 0x52, 0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, 0x52, 0x57, 0x43,
0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x53, 0x57, 0x45, 0x44, 0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00, 0x00,
0x00, 0x01, 0x49, 0x52, 0x57, 0x44, 0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x45, 0x54, 0x44, 0x5f,
0x54, 0x41, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x54, 0x53, 0x4e, 0x49, 0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00, 0x00, 0x00,
0x00, 0x53, 0x43, 0x32, 0x41, 0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x43, 0x32, 0x41, 0x5f, 0x54,
0x41, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4d, 0x55, 0x43, 0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x00,
0x50, 0x4f, 0x52, 0x50, 0x5f, 0x54, 0x41, 0x4d, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x44, 0x41, 0x48, 0x53, 0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x4d, 0x48, 0x53, 0x5f, 0x54, 0x41,
0x4d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x46, 0x45, 0x52, 0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54,
0x46, 0x45, 0x52, 0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, 0x4f, 0x49, 0x43, 0x5f, 0x54, 0x41, 0x4d,
0x01, 0x00, 0x00, 0x00, 0x01, 0x41, 0x51, 0x45, 0x52, 0x5f, 0x54, 0x41, 0x4d, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x41, 0x41, 0x50, 0x53, 0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, 0x41, 0x56, 0x53, 0x5f, 0x54,
0x41, 0x4d, 0x04, 0x00, 0x00, 0x00, 0x9a, 0x99, 0x19, 0x3e, 0x52, 0x48, 0x54, 0x53, 0x5f, 0x54, 0x41, 0x4d, 0x04, 0x00,
0x00, 0x00, 0xcd, 0xcc, 0x4c, 0x3e, 0x4f, 0x44, 0x45, 0x56, 0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x03, 0x52,
0x54, 0x4e, 0x49, 0x5f, 0x54, 0x41, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x44, 0x53, 0x43, 0x5f, 0x54, 0x41, 0x4d,
0x01, 0x00, 0x00, 0x00, 0x01, 0x54, 0x58, 0x45, 0x54, 0x5f, 0x43, 0x49, 0x44, 0x69, 0x28, 0x00, 0x00, 0xae, 0x01, 0x00,
0x00, 0x23, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x30, 0x30, 0x20, 0x65, 0x73, 0x00, 0x6c, 0x61, 0x79,
0x6f, 0x75, 0x74, 0x28, 0x73, 0x74, 0x64, 0x31, 0x34, 0x30, 0x29, 0x20, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x00, 0x7b, 0x00, 0x6d, 0x61, 0x74, 0x34,
0x20, 0x61, 0x3b, 0x00, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x62, 0x3b, 0x00, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x63, 0x3b, 0x00,
0x6d, 0x61, 0x74, 0x34, 0x20, 0x64, 0x3b, 0x00, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x65, 0x3b, 0x00, 0x6d, 0x61, 0x74, 0x34,
0x20, 0x66, 0x3b, 0x00, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x67, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x68, 0x3b, 0x00,
0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x69, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61,
0x74, 0x20, 0x6a, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6b, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x6c,
0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x6d, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x32, 0x20, 0x6e, 0x3b, 0x00, 0x76, 0x65,
0x63, 0x32, 0x20, 0x6f, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20,
0x70, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x71, 0x3b, 0x00,
0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x72, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x73, 0x3b, 0x00, 0x6d, 0x65,
0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x74, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74,
0x20, 0x75, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x76, 0x3b,
0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x77, 0x3b, 0x00, 0x6d, 0x65,
0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75,
0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x79, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20,
0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f,
0x61, 0x74, 0x20, 0x61, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20,
0x62, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x75, 0x76, 0x65, 0x63, 0x33, 0x20, 0x63, 0x7a,
0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x7a, 0x3b, 0x00, 0x6d,
0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x65, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69,
0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x66, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d,
0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x67, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20,
0x76, 0x65, 0x63, 0x33, 0x20, 0x68, 0x7a, 0x5b, 0x39, 0x5d, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20,
0x76, 0x65, 0x63, 0x33, 0x20, 0x69, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f,
0x61, 0x74, 0x20, 0x6a, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20,
0x6b, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x6c, 0x7a, 0x3b,
0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x6d, 0x7a, 0x3b, 0x00, 0x6d, 0x65,
0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6e, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75,
0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6f, 0x7a, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x70, 0x7a,
0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x71, 0x7a, 0x3b, 0x00, 0x6d,
0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x72, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64,
0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x73, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75,
0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x74, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70,
0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x75, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66,
0x6c, 0x6f, 0x61, 0x74, 0x20, 0x76, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f,
0x61, 0x74, 0x20, 0x77, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x20,
0x78, 0x7a, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x33, 0x20, 0x79, 0x7a, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x7a,
0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, 0x7a, 0x7a,
0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x62, 0x7a, 0x7a, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x63,
0x7a, 0x7a, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x64, 0x7a, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75,
0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x33, 0x20, 0x65, 0x7a, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70,
0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x66, 0x7a, 0x7a, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x67, 0x7a,
0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x68, 0x7a, 0x7a,
0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x69, 0x7a, 0x7a, 0x3b,
0x00, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6a, 0x7a, 0x7a, 0x3b, 0x00,
0x6d, 0x61, 0x74, 0x34, 0x20, 0x6b, 0x7a, 0x7a, 0x3b, 0x00, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x6c, 0x7a, 0x7a, 0x3b, 0x00,
0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6d, 0x7a, 0x7a, 0x3b, 0x00, 0x6d,
0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6e, 0x7a, 0x7a, 0x3b, 0x00, 0x6d, 0x65,
0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6f, 0x7a, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64,
0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x70, 0x7a, 0x7a, 0x3b, 0x00, 0x6d, 0x65, 0x64, 0x69,
0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x71, 0x7a, 0x7a, 0x5b, 0x36, 0x30, 0x5d, 0x3b, 0x00, 0x7d, 0x20,
0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x3b, 0x00, 0x66, 0x6c, 0x61, 0x74, 0x20,
0x6f, 0x75, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x64,
0x65, 0x78, 0x3b, 0x00, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
0x3d, 0x20, 0x30, 0x29, 0x20, 0x69, 0x6e, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x6d, 0x65, 0x73, 0x68, 0x5f, 0x70, 0x6f,
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x00, 0x6f, 0x75, 0x74, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 0x61, 0x72,
0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x55, 0x56, 0x3b, 0x00, 0x6f, 0x75, 0x74, 0x20, 0x76,
0x65, 0x63, 0x34, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x50, 0x6f, 0x73, 0x69,
0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x00, 0x6f, 0x75, 0x74, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65,
0x78, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x00, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69,
0x6e, 0x28, 0x29, 0x00, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d,
0x20, 0x67, 0x6c, 0x5f, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x44, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34,
0x20, 0x5f, 0x32, 0x39, 0x31, 0x20, 0x3d, 0x20, 0x6d, 0x65, 0x73, 0x68, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
0x6e, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x33, 0x33, 0x33, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x39, 0x31, 0x3b,
0x00, 0x5f, 0x33, 0x33, 0x33, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x39, 0x31, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x28,
0x2d, 0x30, 0x2e, 0x35, 0x29, 0x20, 0x2b, 0x20, 0x30, 0x2e, 0x35, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x32,
0x36, 0x37, 0x20, 0x3d, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x66,
0x20, 0x2a, 0x20, 0x5f, 0x33, 0x33, 0x33, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x5f, 0x32, 0x36, 0x39, 0x20,
0x3d, 0x20, 0x5f, 0x32, 0x36, 0x37, 0x2e, 0x77, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x33, 0x34, 0x33, 0x3b,
0x00, 0x69, 0x66, 0x20, 0x28, 0x61, 0x62, 0x73, 0x28, 0x5f, 0x32, 0x36, 0x39, 0x29, 0x20, 0x3c, 0x20, 0x31, 0x2e, 0x30,
0x38, 0x34, 0x32, 0x30, 0x32, 0x32, 0x65, 0x2d, 0x31, 0x39, 0x29, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x33, 0x33,
0x37, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x36, 0x37, 0x3b, 0x00, 0x5f, 0x33, 0x33, 0x37, 0x2e, 0x77, 0x20, 0x3d, 0x20, 0x28,
0x5f, 0x32, 0x36, 0x39, 0x20, 0x3c, 0x20, 0x30, 0x2e, 0x30, 0x29, 0x20, 0x3f, 0x20, 0x28, 0x2d, 0x31, 0x2e, 0x30, 0x38,
0x34, 0x32, 0x30, 0x32, 0x32, 0x65, 0x2d, 0x31, 0x39, 0x29, 0x20, 0x3a, 0x20, 0x31, 0x2e, 0x30, 0x38, 0x34, 0x32, 0x30,
0x32, 0x32, 0x65, 0x2d, 0x31, 0x39, 0x3b, 0x00, 0x5f, 0x33, 0x34, 0x33, 0x20, 0x3d, 0x20, 0x5f, 0x33, 0x33, 0x37, 0x3b,
0x00, 0x7d, 0x00, 0x65, 0x6c, 0x73, 0x65, 0x00, 0x5f, 0x33, 0x34, 0x33, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x36, 0x37, 0x3b,
0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x32, 0x38, 0x33, 0x20, 0x3d, 0x20, 0x5f, 0x33, 0x34, 0x33, 0x20, 0x2a, 0x20,
0x28, 0x31, 0x2e, 0x30, 0x20, 0x2f, 0x20, 0x5f, 0x33, 0x34, 0x33, 0x2e, 0x77, 0x29, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x32,
0x20, 0x5f, 0x32, 0x39, 0x38, 0x20, 0x3d, 0x20, 0x28, 0x5f, 0x32, 0x39, 0x31, 0x2e, 0x78, 0x79, 0x20, 0x2a, 0x20, 0x30,
0x2e, 0x35, 0x29, 0x20, 0x2b, 0x20, 0x76, 0x65, 0x63, 0x32, 0x28, 0x30, 0x2e, 0x35, 0x29, 0x3b, 0x00, 0x76, 0x65, 0x63,
0x34, 0x20, 0x5f, 0x33, 0x34, 0x30, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x63, 0x34, 0x28, 0x30, 0x2e, 0x30, 0x29, 0x3b, 0x00,
0x5f, 0x33, 0x34, 0x30, 0x2e, 0x78, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x39, 0x38, 0x2e, 0x78, 0x3b, 0x00, 0x5f, 0x33, 0x34,
0x30, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x39, 0x38, 0x2e, 0x79, 0x3b, 0x00, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62,
0x6c, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x55, 0x56, 0x20, 0x3d, 0x20, 0x5f, 0x33, 0x34, 0x30, 0x3b, 0x00, 0x76,
0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
0x78, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x38, 0x33, 0x2e, 0x78, 0x3b, 0x00, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x77,
0x6f, 0x72, 0x6c, 0x64, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x38,
0x33, 0x2e, 0x79, 0x3b, 0x00, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x50, 0x6f, 0x73,
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x38, 0x33, 0x2e, 0x7a, 0x3b, 0x00, 0x67, 0x6c,
0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x39, 0x31, 0x3b, 0x00, 0x67, 0x6c,
0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73,
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x28, 0x2d, 0x30, 0x2e, 0x35, 0x29, 0x20, 0x2b, 0x20, 0x30,
0x2e, 0x35, 0x3b, 0x00, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20,
0x3d, 0x20, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x6f,
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x74, 0x28, 0x67, 0x6c, 0x5f, 0x50, 0x6f,
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x7a, 0x77, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66,
0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x69, 0x29, 0x3b, 0x00, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6d,
0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3b, 0x00, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73,
0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x69, 0x6e, 0x74, 0x3b, 0x00, 0x76, 0x65, 0x63,
0x34, 0x20, 0x5f, 0x35, 0x35, 0x33, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x61,
0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x62, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68,
0x70, 0x20, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x63, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x6d, 0x61, 0x74, 0x34,
0x20, 0x64, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x65, 0x3b, 0x00, 0x68, 0x69,
0x67, 0x68, 0x70, 0x20, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x66, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x6d, 0x61,
0x74, 0x34, 0x20, 0x67, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x68, 0x3b, 0x00,
0x76, 0x65, 0x63, 0x32, 0x20, 0x69, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20,
0x6a, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6b, 0x3b, 0x00, 0x68, 0x69,
0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x6c, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65,
0x63, 0x34, 0x20, 0x6d, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x6e, 0x3b, 0x00,
0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x6f, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20,
0x70, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x71, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c,
0x6f, 0x61, 0x74, 0x20, 0x72, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x73,
0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x74, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f,
0x61, 0x74, 0x20, 0x75, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x76, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74,
0x20, 0x77, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x79,
0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x7a, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, 0x7a, 0x3b,
0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x62, 0x7a, 0x3b, 0x00, 0x75, 0x76, 0x65, 0x63, 0x33, 0x20, 0x63, 0x7a, 0x3b, 0x00,
0x75, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x7a, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x32, 0x20, 0x65, 0x7a, 0x3b, 0x00, 0x66, 0x6c,
0x6f, 0x61, 0x74, 0x20, 0x66, 0x7a, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x67, 0x7a, 0x3b, 0x00, 0x76, 0x65,
0x63, 0x33, 0x20, 0x68, 0x7a, 0x5b, 0x39, 0x5d, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x33, 0x20, 0x69, 0x7a, 0x3b, 0x00, 0x66,
0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6a, 0x7a, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x6b, 0x7a, 0x3b, 0x00, 0x76, 0x65,
0x63, 0x34, 0x20, 0x6c, 0x7a, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x32, 0x20, 0x6d, 0x7a, 0x3b, 0x00, 0x75, 0x69, 0x6e, 0x74,
0x20, 0x6e, 0x7a, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6f, 0x7a, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70,
0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x70, 0x7a, 0x3b, 0x00, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x71, 0x7a, 0x3b, 0x00, 0x66,
0x6c, 0x6f, 0x61, 0x74, 0x20, 0x72, 0x7a, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x73, 0x7a, 0x3b, 0x00, 0x66,
0x6c, 0x6f, 0x61, 0x74, 0x20, 0x74, 0x7a, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x75, 0x7a, 0x3b, 0x00, 0x66,
0x6c, 0x6f, 0x61, 0x74, 0x20, 0x76, 0x7a, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x77, 0x7a, 0x3b, 0x00, 0x75,
0x69, 0x6e, 0x74, 0x20, 0x78, 0x7a, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x33, 0x20, 0x79,
0x7a, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x7a, 0x7a, 0x3b, 0x00, 0x66,
0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, 0x7a, 0x7a, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61,
0x74, 0x20, 0x62, 0x7a, 0x7a, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x63,
0x7a, 0x7a, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x64, 0x7a, 0x7a, 0x3b,
0x00, 0x76, 0x65, 0x63, 0x33, 0x20, 0x65, 0x7a, 0x7a, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x66, 0x7a, 0x7a,
0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x67, 0x7a, 0x7a, 0x3b, 0x00, 0x66,
0x6c, 0x6f, 0x61, 0x74, 0x20, 0x68, 0x7a, 0x7a, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x69, 0x7a, 0x7a, 0x3b,
0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6a, 0x7a, 0x7a, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x6d, 0x61,
0x74, 0x34, 0x20, 0x6b, 0x7a, 0x7a, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x6c,
0x7a, 0x7a, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6d, 0x7a, 0x7a, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74,
0x20, 0x6e, 0x7a, 0x7a, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6f, 0x7a, 0x7a, 0x3b, 0x00, 0x66, 0x6c, 0x6f,
0x61, 0x74, 0x20, 0x70, 0x7a, 0x7a, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x71, 0x7a, 0x7a, 0x5b, 0x36, 0x30, 0x5d,
0x3b, 0x00, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, 0x73, 0x74, 0x64, 0x31, 0x34, 0x30, 0x29, 0x20, 0x75, 0x6e, 0x69,
0x66, 0x6f, 0x72, 0x6d, 0x20, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x00,
0x76, 0x65, 0x63, 0x34, 0x20, 0x62, 0x3b, 0x00, 0x69, 0x6e, 0x74, 0x20, 0x63, 0x3b, 0x00, 0x7d, 0x20, 0x6d, 0x61, 0x74,
0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3b, 0x00, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d,
0x20, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x6d,
0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3b,
0x00, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 0x61, 0x72, 0x69, 0x61,
0x62, 0x6c, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x55, 0x56, 0x3b, 0x00, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28,
0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x76, 0x65,
0x63, 0x34, 0x20, 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20,
0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x34, 0x30, 0x37, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c,
0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x61, 0x20, 0x2a, 0x20, 0x76, 0x65, 0x63, 0x34, 0x28, 0x63, 0x6c, 0x61, 0x6d,
0x70, 0x28, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x55, 0x56, 0x2e, 0x78,
0x79, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x32, 0x28, 0x30, 0x2e, 0x30, 0x29, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x32, 0x28, 0x31,
0x2e, 0x30, 0x29, 0x29, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x29, 0x3b, 0x00, 0x68, 0x69, 0x67,
0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x5f, 0x34, 0x30, 0x38, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x30, 0x37, 0x2e,
0x78, 0x79, 0x3b, 0x00, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x5f, 0x34, 0x31, 0x31, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x74, 0x65,
0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x63, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x3b, 0x00, 0x62,
0x6f, 0x6f, 0x6c, 0x20, 0x5f, 0x34, 0x31, 0x38, 0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x21, 0x5f, 0x34, 0x31, 0x31, 0x29,
0x00, 0x5f, 0x34, 0x31, 0x38, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x30, 0x37, 0x2e, 0x78, 0x20, 0x3e, 0x20, 0x31, 0x2e, 0x30,
0x3b, 0x00, 0x5f, 0x34, 0x31, 0x38, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x31, 0x31, 0x3b, 0x00, 0x62, 0x6f, 0x6f, 0x6c, 0x20,
0x5f, 0x34, 0x32, 0x35, 0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x21, 0x5f, 0x34, 0x31, 0x38, 0x29, 0x00, 0x5f, 0x34, 0x32,
0x35, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x30, 0x37, 0x2e, 0x78, 0x20, 0x3c, 0x20, 0x30, 0x2e, 0x30, 0x3b, 0x00, 0x5f, 0x34,
0x32, 0x35, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x31, 0x38, 0x3b, 0x00, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x5f, 0x34, 0x33, 0x32,
0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x21, 0x5f, 0x34, 0x32, 0x35, 0x29, 0x00, 0x5f, 0x34, 0x33, 0x32, 0x20, 0x3d, 0x20,
0x5f, 0x34, 0x30, 0x37, 0x2e, 0x79, 0x20, 0x3c, 0x20, 0x30, 0x2e, 0x30, 0x3b, 0x00, 0x5f, 0x34, 0x33, 0x32, 0x20, 0x3d,
0x20, 0x5f, 0x34, 0x32, 0x35, 0x3b, 0x00, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x5f, 0x34, 0x33, 0x39, 0x3b, 0x00, 0x69, 0x66,
0x20, 0x28, 0x21, 0x5f, 0x34, 0x33, 0x32, 0x29, 0x00, 0x5f, 0x34, 0x33, 0x39, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x30, 0x37,
0x2e, 0x79, 0x20, 0x3e, 0x20, 0x31, 0x2e, 0x30, 0x3b, 0x00, 0x5f, 0x34, 0x33, 0x39, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x33,
0x32, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x35, 0x34, 0x39, 0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x5f, 0x34,
0x33, 0x39, 0x29, 0x00, 0x5f, 0x35, 0x34, 0x39, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50,
0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x62, 0x3b, 0x00, 0x5f, 0x34, 0x30, 0x38, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x31, 0x2e,
0x30, 0x20, 0x2d, 0x20, 0x5f, 0x34, 0x30, 0x37, 0x2e, 0x79, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x34, 0x35,
0x34, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x78, 0x28, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x28, 0x6d, 0x61, 0x74, 0x65,
0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x5f, 0x34,
0x30, 0x38, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x70, 0x29,
0x2c, 0x20, 0x76, 0x65, 0x63, 0x34, 0x28, 0x30, 0x2e, 0x30, 0x29, 0x29, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20,
0x5f, 0x34, 0x35, 0x36, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x35, 0x34, 0x2e, 0x77, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x33, 0x20,
0x5f, 0x34, 0x35, 0x39, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x35, 0x34, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2a, 0x20, 0x5f, 0x34,
0x35, 0x36, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x35, 0x32, 0x37, 0x3b, 0x00, 0x5f, 0x35, 0x32, 0x37, 0x2e,
0x78, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x35, 0x39, 0x2e, 0x78, 0x3b, 0x00, 0x5f, 0x35, 0x32, 0x37, 0x2e, 0x79, 0x20, 0x3d,
0x20, 0x5f, 0x34, 0x35, 0x39, 0x2e, 0x79, 0x3b, 0x00, 0x5f, 0x35, 0x32, 0x37, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x5f, 0x34,
0x35, 0x39, 0x2e, 0x7a, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x34, 0x37, 0x35, 0x20, 0x3d, 0x20, 0x5f, 0x35,
0x32, 0x37, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2b, 0x20, 0x28, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61,
0x72, 0x61, 0x6d, 0x73, 0x2e, 0x62, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2a, 0x20, 0x28, 0x31, 0x2e, 0x30, 0x20, 0x2d, 0x20,
0x5f, 0x34, 0x35, 0x36, 0x29, 0x29, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x35, 0x33, 0x34, 0x20, 0x3d, 0x20,
0x76, 0x65, 0x63, 0x34, 0x28, 0x31, 0x2e, 0x30, 0x29, 0x3b, 0x00, 0x5f, 0x35, 0x33, 0x34, 0x2e, 0x78, 0x20, 0x3d, 0x20,
0x5f, 0x34, 0x37, 0x35, 0x2e, 0x78, 0x3b, 0x00, 0x5f, 0x35, 0x33, 0x34, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x37,
0x35, 0x2e, 0x79, 0x3b, 0x00, 0x5f, 0x35, 0x33, 0x34, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x37, 0x35, 0x2e, 0x7a,
0x3b, 0x00, 0x5f, 0x35, 0x34, 0x39, 0x20, 0x3d, 0x20, 0x5f, 0x35, 0x33, 0x34, 0x3b, 0x00, 0x66, 0x72, 0x61, 0x67, 0x43,
0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x5f, 0x35, 0x34, 0x39, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x39,
0x32, 0x39, 0x3b, 0x00, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20,
0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x43, 0x75, 0x62, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x69, 0x62,
0x6c, 0x53, 0x70, 0x65, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x3b, 0x00, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20,
0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x50, 0x6f, 0x73,
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x39,
0x30, 0x30, 0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d,
0x73, 0x2e, 0x63, 0x5b, 0x32, 0x5d, 0x2e, 0x77, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x2e, 0x30, 0x29, 0x00, 0x5f, 0x39, 0x30,
0x30, 0x20, 0x3d, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x62, 0x5b,
0x33, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2d, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x77, 0x6f, 0x72, 0x6c,
0x64, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x78, 0x79, 0x7a, 0x3b, 0x00, 0x5f, 0x39, 0x30, 0x30, 0x20,
0x3d, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x62, 0x5b, 0x32, 0x5d,
0x2e, 0x78, 0x79, 0x7a, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x35, 0x36,
0x39, 0x20, 0x3d, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x28, 0x5f, 0x39, 0x30, 0x30, 0x29, 0x3b,
0x00, 0x76, 0x65, 0x63, 0x33, 0x20, 0x6d, 0x70, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x5f, 0x35, 0x36, 0x39, 0x20, 0x3d, 0x20,
0x5f, 0x35, 0x36, 0x39, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x36, 0x30,
0x31, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x61,
0x20, 0x2a, 0x20, 0x76, 0x65, 0x63, 0x34, 0x28, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62,
0x6c, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x55, 0x56, 0x2e, 0x78, 0x79, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x32, 0x28,
0x30, 0x2e, 0x30, 0x29, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x32, 0x28, 0x31, 0x2e, 0x30, 0x29, 0x29, 0x2c, 0x20, 0x31, 0x2e,
0x30, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x29, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20,
0x5f, 0x36, 0x30, 0x32, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x30, 0x31, 0x2e, 0x78, 0x79, 0x3b, 0x00, 0x62, 0x6f, 0x6f, 0x6c,
0x20, 0x5f, 0x36, 0x30, 0x35, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61,
0x6d, 0x73, 0x2e, 0x63, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x3b, 0x00, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x5f, 0x36, 0x31, 0x32,
0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x21, 0x5f, 0x36, 0x30, 0x35, 0x29, 0x00, 0x5f, 0x36, 0x31, 0x32, 0x20, 0x3d, 0x20,
0x5f, 0x36, 0x30, 0x31, 0x2e, 0x78, 0x20, 0x3e, 0x20, 0x31, 0x2e, 0x30, 0x3b, 0x00, 0x5f, 0x36, 0x31, 0x32, 0x20, 0x3d,
0x20, 0x5f, 0x36, 0x30, 0x35, 0x3b, 0x00, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x5f, 0x36, 0x31, 0x39, 0x3b, 0x00, 0x69, 0x66,
0x20, 0x28, 0x21, 0x5f, 0x36, 0x31, 0x32, 0x29, 0x00, 0x5f, 0x36, 0x31, 0x39, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x30, 0x31,
0x2e, 0x78, 0x20, 0x3c, 0x20, 0x30, 0x2e, 0x30, 0x3b, 0x00, 0x5f, 0x36, 0x31, 0x39, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x31,
0x32, 0x3b, 0x00, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x5f, 0x36, 0x32, 0x36, 0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x21, 0x5f,
0x36, 0x31, 0x39, 0x29, 0x00, 0x5f, 0x36, 0x32, 0x36, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x30, 0x31, 0x2e, 0x79, 0x20, 0x3c,
0x20, 0x30, 0x2e, 0x30, 0x3b, 0x00, 0x5f, 0x36, 0x32, 0x36, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x31, 0x39, 0x3b, 0x00, 0x62,
0x6f, 0x6f, 0x6c, 0x20, 0x5f, 0x36, 0x33, 0x33, 0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x21, 0x5f, 0x36, 0x32, 0x36, 0x29,
0x00, 0x5f, 0x36, 0x33, 0x33, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x30, 0x31, 0x2e, 0x79, 0x20, 0x3e, 0x20, 0x31, 0x2e, 0x30,
0x3b, 0x00, 0x5f, 0x36, 0x33, 0x33, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x32, 0x36, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20,
0x5f, 0x39, 0x31, 0x35, 0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x5f, 0x36, 0x33, 0x33, 0x29, 0x00, 0x5f, 0x39, 0x31, 0x35,
0x20, 0x3d, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x62, 0x3b,
0x00, 0x5f, 0x36, 0x30, 0x32, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x20, 0x2d, 0x20, 0x5f, 0x36, 0x30, 0x31,
0x2e, 0x79, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x36, 0x34, 0x38, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x78, 0x28,
0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x28, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61,
0x6d, 0x73, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x5f, 0x36, 0x30, 0x32, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x6d,
0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x70, 0x29, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x34, 0x28, 0x30,
0x2e, 0x30, 0x29, 0x29, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x5f, 0x36, 0x35, 0x30, 0x20, 0x3d, 0x20, 0x5f,
0x36, 0x34, 0x38, 0x2e, 0x77, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x36, 0x35, 0x33, 0x20, 0x3d, 0x20, 0x5f,
0x36, 0x34, 0x38, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2a, 0x20, 0x5f, 0x36, 0x35, 0x30, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34,
0x20, 0x5f, 0x38, 0x37, 0x37, 0x3b, 0x00, 0x5f, 0x38, 0x37, 0x37, 0x2e, 0x78, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x35, 0x33,
0x2e, 0x78, 0x3b, 0x00, 0x5f, 0x38, 0x37, 0x37, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x35, 0x33, 0x2e, 0x79, 0x3b,
0x00, 0x5f, 0x38, 0x37, 0x37, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x35, 0x33, 0x2e, 0x7a, 0x3b, 0x00, 0x76, 0x65,
0x63, 0x33, 0x20, 0x5f, 0x36, 0x36, 0x39, 0x20, 0x3d, 0x20, 0x5f, 0x38, 0x37, 0x37, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2b,
0x20, 0x28, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x62, 0x2e, 0x78,
0x79, 0x7a, 0x20, 0x2a, 0x20, 0x28, 0x31, 0x2e, 0x30, 0x20, 0x2d, 0x20, 0x5f, 0x36, 0x35, 0x30, 0x29, 0x29, 0x3b, 0x00,
0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x38, 0x38, 0x34, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x63, 0x34, 0x28, 0x31, 0x2e, 0x30,
0x29, 0x3b, 0x00, 0x5f, 0x38, 0x38, 0x34, 0x2e, 0x78, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x36, 0x39, 0x2e, 0x78, 0x3b, 0x00,
0x5f, 0x38, 0x38, 0x34, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x36, 0x39, 0x2e, 0x79, 0x3b, 0x00, 0x5f, 0x38, 0x38,
0x34, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x36, 0x39, 0x2e, 0x7a, 0x3b, 0x00, 0x5f, 0x39, 0x31, 0x35, 0x20, 0x3d,
0x20, 0x5f, 0x38, 0x38, 0x34, 0x3b, 0x00, 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x5f,
0x39, 0x31, 0x35, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x34, 0x37, 0x37,
0x20, 0x3d, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x50, 0x6f, 0x73, 0x69, 0x74,
0x69, 0x6f, 0x6e, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2d, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f,
0x72, 0x6d, 0x73, 0x2e, 0x62, 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f,
0x34, 0x37, 0x39, 0x20, 0x3d, 0x20, 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x00, 0x76, 0x65, 0x63,
0x34, 0x20, 0x5f, 0x39, 0x32, 0x33, 0x3b, 0x00, 0x64, 0x6f, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f,
0x61, 0x74, 0x20, 0x5f, 0x37, 0x31, 0x37, 0x20, 0x3d, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x28, 0x5f, 0x34, 0x37,
0x37, 0x29, 0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x5f, 0x37, 0x31, 0x37, 0x20, 0x3e, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65,
0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x64, 0x7a, 0x7a, 0x29, 0x00, 0x5f, 0x39, 0x32, 0x33, 0x20, 0x3d,
0x20, 0x5f, 0x34, 0x37, 0x39, 0x3b, 0x00, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20,
0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x5f, 0x37, 0x33, 0x33, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x37, 0x37, 0x2e, 0x79, 0x3b,
0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x5f, 0x37, 0x33, 0x34, 0x20, 0x3d, 0x20,
0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x63, 0x7a, 0x7a, 0x20, 0x2a, 0x20,
0x5f, 0x37, 0x33, 0x33, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x5f, 0x39,
0x31, 0x36, 0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x61, 0x62, 0x73, 0x28, 0x5f, 0x37, 0x33, 0x34, 0x29, 0x20, 0x3e, 0x20,
0x30, 0x2e, 0x30, 0x30, 0x31, 0x32, 0x35, 0x29, 0x00, 0x5f, 0x39, 0x31, 0x36, 0x20, 0x3d, 0x20, 0x28, 0x28, 0x2d, 0x66,
0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x79, 0x7a, 0x2e, 0x78, 0x29, 0x20, 0x2a,
0x20, 0x65, 0x78, 0x70, 0x28, 0x28, 0x2d, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73,
0x2e, 0x63, 0x7a, 0x7a, 0x29, 0x20, 0x2a, 0x20, 0x5f, 0x37, 0x33, 0x33, 0x20, 0x2b, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65,
0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x79, 0x7a, 0x2e, 0x79, 0x29, 0x20, 0x2b, 0x20, 0x66, 0x72, 0x61,
0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x79, 0x7a, 0x2e, 0x7a, 0x29, 0x20, 0x2f, 0x20, 0x5f,
0x37, 0x33, 0x34, 0x3b, 0x00, 0x5f, 0x39, 0x31, 0x36, 0x20, 0x3d, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69,
0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x79, 0x7a, 0x2e, 0x7a, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c,
0x6f, 0x61, 0x74, 0x20, 0x5f, 0x37, 0x36, 0x32, 0x20, 0x3d, 0x20, 0x65, 0x78, 0x70, 0x28, 0x2d, 0x28, 0x5f, 0x39, 0x31,
0x36, 0x20, 0x2a, 0x20, 0x6d, 0x61, 0x78, 0x28, 0x5f, 0x37, 0x31, 0x37, 0x20, 0x2d, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65,
0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x7a, 0x7a, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x29, 0x29, 0x29, 0x3b,
0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6d, 0x70, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x5f, 0x37, 0x36, 0x32, 0x20, 0x3d,
0x20, 0x5f, 0x37, 0x36, 0x32, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x5f, 0x37, 0x36, 0x37, 0x20, 0x3d, 0x20,
0x6d, 0x69, 0x6e, 0x28, 0x31, 0x2e, 0x30, 0x20, 0x2d, 0x20, 0x6d, 0x70, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x5f, 0x37, 0x36,
0x32, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x61, 0x7a, 0x7a,
0x29, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x39, 0x31, 0x37, 0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x66, 0x72,
0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x66, 0x7a, 0x7a, 0x20, 0x3e, 0x20, 0x30, 0x2e,
0x30, 0x29, 0x00, 0x5f, 0x39, 0x31, 0x37, 0x20, 0x3d, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f,
0x72, 0x6d, 0x73, 0x2e, 0x65, 0x7a, 0x7a, 0x20, 0x2a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x4c, 0x6f, 0x64,
0x28, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x69, 0x62, 0x6c, 0x53, 0x70, 0x65, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x2c, 0x20,
0x5f, 0x34, 0x37, 0x37, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e,
0x67, 0x7a, 0x29, 0x2e, 0x78, 0x79, 0x7a, 0x3b, 0x00, 0x5f, 0x39, 0x31, 0x37, 0x20, 0x3d, 0x20, 0x66, 0x72, 0x61, 0x6d,
0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x65, 0x7a, 0x7a, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x33, 0x20,
0x5f, 0x37, 0x38, 0x39, 0x20, 0x3d, 0x20, 0x5f, 0x39, 0x31, 0x37, 0x20, 0x2a, 0x20, 0x28, 0x66, 0x72, 0x61, 0x6d, 0x65,
0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x66, 0x7a, 0x20, 0x2a, 0x20, 0x5f, 0x37, 0x36, 0x37, 0x29, 0x3b,
0x00, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x39, 0x32, 0x32, 0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x66, 0x72, 0x61, 0x6d,
0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x68, 0x7a, 0x7a, 0x20, 0x3e, 0x20, 0x30, 0x2e, 0x30, 0x29,
0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x5f, 0x38, 0x30, 0x33, 0x20, 0x3d, 0x20,
0x65, 0x78, 0x70, 0x28, 0x2d, 0x28, 0x5f, 0x39, 0x31, 0x36, 0x20, 0x2a, 0x20, 0x6d, 0x61, 0x78, 0x28, 0x5f, 0x37, 0x31,
0x37, 0x20, 0x2d, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x67, 0x7a,
0x7a, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x29, 0x29, 0x29, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6d, 0x70, 0x5f,
0x63, 0x6f, 0x70, 0x79, 0x5f, 0x38, 0x30, 0x33, 0x20, 0x3d, 0x20, 0x5f, 0x38, 0x30, 0x33, 0x3b, 0x00, 0x5f, 0x39, 0x32,
0x32, 0x20, 0x3d, 0x20, 0x5f, 0x37, 0x38, 0x39, 0x20, 0x2b, 0x20, 0x28, 0x28, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e,
0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x6b, 0x7a, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2a, 0x20, 0x66, 0x72, 0x61, 0x6d,
0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x6b, 0x7a, 0x2e, 0x77, 0x29, 0x20, 0x2a, 0x20, 0x28, 0x70,
0x6f, 0x77, 0x28, 0x6d, 0x61, 0x78, 0x28, 0x64, 0x6f, 0x74, 0x28, 0x2d, 0x6d, 0x70, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x5f,
0x35, 0x36, 0x39, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x69,
0x7a, 0x29, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x29, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f,
0x72, 0x6d, 0x73, 0x2e, 0x68, 0x7a, 0x7a, 0x29, 0x20, 0x2a, 0x20, 0x28, 0x31, 0x2e, 0x30, 0x20, 0x2d, 0x20, 0x6d, 0x70,
0x5f, 0x63, 0x6f, 0x70, 0x79, 0x5f, 0x38, 0x30, 0x33, 0x29, 0x29, 0x29, 0x3b, 0x00, 0x5f, 0x39, 0x32, 0x32, 0x20, 0x3d,
0x20, 0x5f, 0x37, 0x38, 0x39, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x38, 0x33, 0x35, 0x20, 0x3d, 0x20, 0x28,
0x5f, 0x34, 0x37, 0x39, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2a, 0x20, 0x28, 0x31, 0x2e, 0x30, 0x20, 0x2d, 0x20, 0x5f, 0x37,
0x36, 0x37, 0x29, 0x29, 0x20, 0x2b, 0x20, 0x5f, 0x39, 0x32, 0x32, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x38,
0x39, 0x35, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x37, 0x39, 0x3b, 0x00, 0x5f, 0x38, 0x39, 0x35, 0x2e, 0x78, 0x20, 0x3d, 0x20,
0x5f, 0x38, 0x33, 0x35, 0x2e, 0x78, 0x3b, 0x00, 0x5f, 0x38, 0x39, 0x35, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x5f, 0x38, 0x33,
0x35, 0x2e, 0x79, 0x3b, 0x00, 0x5f, 0x38, 0x39, 0x35, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x5f, 0x38, 0x33, 0x35, 0x2e, 0x7a,
0x3b, 0x00, 0x5f, 0x39, 0x32, 0x33, 0x20, 0x3d, 0x20, 0x5f, 0x38, 0x39, 0x35, 0x3b, 0x00, 0x7d, 0x20, 0x77, 0x68, 0x69,
0x6c, 0x65, 0x28, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x00, 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72,
0x20, 0x3d, 0x20, 0x5f, 0x39, 0x32, 0x33, 0x3b, 0x00, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x50, 0x65, 0x72, 0x52,
0x65, 0x6e, 0x64, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x61, 0x74, 0x61, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20,
0x6d, 0x61, 0x74, 0x34, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x4d,
0x61, 0x74, 0x72, 0x69, 0x78, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x6d, 0x61, 0x74, 0x33, 0x20, 0x77, 0x6f,
0x72, 0x6c, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x4d, 0x61,
0x74, 0x72, 0x69, 0x78, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6d, 0x6f, 0x72,
0x70, 0x68, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70,
0x20, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x3b,
0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64,
0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x75, 0x73, 0x65, 0x72, 0x44, 0x61,
0x74, 0x61, 0x3b, 0x00, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x72, 0x65, 0x73, 0x65, 0x72,
0x76, 0x65, 0x64, 0x5b, 0x38, 0x5d, 0x3b, 0x00, 0x7d, 0x3b, 0x00, 0x23, 0x69, 0x66, 0x6e, 0x64, 0x65, 0x66, 0x20, 0x53,
0x50, 0x49, 0x52, 0x56, 0x5f, 0x43, 0x52, 0x4f, 0x53, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x54, 0x41, 0x4e, 0x54, 0x5f,
0x49, 0x44, 0x5f, 0x31, 0x00, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x53, 0x50, 0x49, 0x52, 0x56, 0x5f, 0x43,
0x52, 0x4f, 0x53, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x54, 0x41, 0x4e, 0x54, 0x5f, 0x49, 0x44, 0x5f, 0x31, 0x20, 0x36,
0x34, 0x00, 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x00, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x43,
0x4f, 0x4e, 0x46, 0x49, 0x47, 0x5f, 0x4d, 0x41, 0x58, 0x5f, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, 0x43, 0x45, 0x53, 0x20,
0x3d, 0x20, 0x53, 0x50, 0x49, 0x52, 0x56, 0x5f, 0x43, 0x52, 0x4f, 0x53, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x54, 0x41,
0x4e, 0x54, 0x5f, 0x49, 0x44, 0x5f, 0x31, 0x3b, 0x00, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, 0x73, 0x74, 0x64, 0x31,
0x34, 0x30, 0x29, 0x20, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x6e,
0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x00, 0x50, 0x65, 0x72, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65,
0x44, 0x61, 0x74, 0x61, 0x20, 0x61, 0x5b, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x5f, 0x4d, 0x41, 0x58, 0x5f, 0x49, 0x4e,
0x53, 0x54, 0x41, 0x4e, 0x43, 0x45, 0x53, 0x5d, 0x3b, 0x00, 0x7d, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x6e,
0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x3b, 0x00, 0x66, 0x6c, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x67, 0x68,
0x70, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78,
0x3b, 0x00, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20,
0x30, 0x29, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x75, 0x76, 0x65, 0x63, 0x32, 0x20, 0x6f,
0x75, 0x74, 0x50, 0x69, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3b, 0x00, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20,
0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
0x3b, 0x00, 0x6f, 0x75, 0x74, 0x50, 0x69, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x78, 0x20, 0x3d, 0x20, 0x6f, 0x62, 0x6a,
0x65, 0x63, 0x74, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x61, 0x5b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e,
0x63, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x3b, 0x00,
0x6f, 0x75, 0x74, 0x50, 0x69, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74,
0x42, 0x69, 0x74, 0x73, 0x54, 0x6f, 0x55, 0x69, 0x6e, 0x74, 0x28, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x70, 0x6f,
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x7a, 0x20, 0x2f, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x70, 0x6f,
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x77, 0x29, 0x3b, 0x00, 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72,
0x20, 0x3d, 0x20, 0x76, 0x65, 0x63, 0x34, 0x28, 0x30, 0x2e, 0x30, 0x29, 0x3b, 0x00, 0x23, 0x76, 0x65, 0x72, 0x73, 0x69,
0x6f, 0x6e, 0x20, 0x34, 0x31, 0x30, 0x00, 0x23, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x47, 0x4c,
0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73, 0x68, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67,
0x65, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x3a, 0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x6c,
0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x38, 0x29, 0x20,
0x66, 0x6c, 0x61, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3b, 0x00, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, 0x6c, 0x6f, 0x63, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76,
0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x55, 0x56, 0x3b, 0x00, 0x6c, 0x61, 0x79,
0x6f, 0x75, 0x74, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x34, 0x29, 0x20, 0x6f, 0x75,
0x74, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x50,
0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x00, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, 0x6c, 0x6f, 0x63, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x37, 0x29, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76,
0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34,
0x20, 0x5f, 0x32, 0x39, 0x32, 0x20, 0x3d, 0x20, 0x6d, 0x65, 0x73, 0x68, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
0x6e, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x33, 0x33, 0x34, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x39, 0x32, 0x3b,
0x00, 0x5f, 0x33, 0x33, 0x34, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x66, 0x6d, 0x61, 0x28, 0x5f, 0x32, 0x39, 0x32, 0x2e, 0x7a,
0x2c, 0x20, 0x2d, 0x30, 0x2e, 0x35, 0x2c, 0x20, 0x30, 0x2e, 0x35, 0x29, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f,
0x32, 0x36, 0x38, 0x20, 0x3d, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e,
0x66, 0x20, 0x2a, 0x20, 0x5f, 0x33, 0x33, 0x34, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x5f, 0x32, 0x37, 0x30,
0x20, 0x3d, 0x20, 0x5f, 0x32, 0x36, 0x38, 0x2e, 0x77, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x33, 0x34, 0x34,
0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x61, 0x62, 0x73, 0x28, 0x5f, 0x32, 0x37, 0x30, 0x29, 0x20, 0x3c, 0x20, 0x31, 0x2e,
0x30, 0x38, 0x34, 0x32, 0x30, 0x32, 0x32, 0x65, 0x2d, 0x31, 0x39, 0x29, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x33,
0x33, 0x38, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x36, 0x38, 0x3b, 0x00, 0x5f, 0x33, 0x33, 0x38, 0x2e, 0x77, 0x20, 0x3d, 0x20,
0x28, 0x5f, 0x32, 0x37, 0x30, 0x20, 0x3c, 0x20, 0x30, 0x2e, 0x30, 0x29, 0x20, 0x3f, 0x20, 0x28, 0x2d, 0x31, 0x2e, 0x30,
0x38, 0x34, 0x32, 0x30, 0x32, 0x32, 0x65, 0x2d, 0x31, 0x39, 0x29, 0x20, 0x3a, 0x20, 0x31, 0x2e, 0x30, 0x38, 0x34, 0x32,
0x30, 0x32, 0x32, 0x65, 0x2d, 0x31, 0x39, 0x3b, 0x00, 0x5f, 0x33, 0x34, 0x34, 0x20, 0x3d, 0x20, 0x5f, 0x33, 0x33, 0x38,
0x3b, 0x00, 0x5f, 0x33, 0x34, 0x34, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x36, 0x38, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20,
0x5f, 0x32, 0x38, 0x34, 0x20, 0x3d, 0x20, 0x5f, 0x33, 0x34, 0x34, 0x20, 0x2a, 0x20, 0x28, 0x31, 0x2e, 0x30, 0x20, 0x2f,
0x20, 0x5f, 0x33, 0x34, 0x34, 0x2e, 0x77, 0x29, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x32, 0x20, 0x5f, 0x32, 0x39, 0x39, 0x20,
0x3d, 0x20, 0x28, 0x5f, 0x32, 0x39, 0x32, 0x2e, 0x78, 0x79, 0x20, 0x2a, 0x20, 0x30, 0x2e, 0x35, 0x29, 0x20, 0x2b, 0x20,
0x76, 0x65, 0x63, 0x32, 0x28, 0x30, 0x2e, 0x35, 0x29, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x33, 0x34, 0x31,
0x20, 0x3d, 0x20, 0x76, 0x65, 0x63, 0x34, 0x28, 0x30, 0x2e, 0x30, 0x29, 0x3b, 0x00, 0x5f, 0x33, 0x34, 0x31, 0x2e, 0x78,
0x20, 0x3d, 0x20, 0x5f, 0x32, 0x39, 0x39, 0x2e, 0x78, 0x3b, 0x00, 0x5f, 0x33, 0x34, 0x31, 0x2e, 0x79, 0x20, 0x3d, 0x20,
0x5f, 0x32, 0x39, 0x39, 0x2e, 0x79, 0x3b, 0x00, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x69, 0x6d, 0x61,
0x67, 0x65, 0x55, 0x56, 0x20, 0x3d, 0x20, 0x5f, 0x33, 0x34, 0x31, 0x3b, 0x00, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f,
0x77, 0x6f, 0x72, 0x6c, 0x64, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x78, 0x20, 0x3d, 0x20, 0x5f, 0x32,
0x38, 0x34, 0x2e, 0x78, 0x3b, 0x00, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x50, 0x6f,
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x38, 0x34, 0x2e, 0x79, 0x3b, 0x00, 0x76,
0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
0x7a, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x38, 0x34, 0x2e, 0x7a, 0x3b, 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74,
0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x39, 0x32, 0x3b, 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74,
0x69, 0x6f, 0x6e, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x66, 0x6d, 0x61, 0x28, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74,
0x69, 0x6f, 0x6e, 0x2e, 0x7a, 0x2c, 0x20, 0x2d, 0x30, 0x2e, 0x35, 0x2c, 0x20, 0x30, 0x2e, 0x35, 0x29, 0x3b, 0x00, 0x75,
0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x6d, 0x61, 0x74,
0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3b, 0x00, 0x6c,
0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x30, 0x29, 0x20,
0x69, 0x6e, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x69, 0x6d, 0x61,
0x67, 0x65, 0x55, 0x56, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x34, 0x30, 0x37, 0x20, 0x3d, 0x20, 0x6d, 0x61,
0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x61, 0x20, 0x2a, 0x20, 0x76, 0x65, 0x63,
0x34, 0x28, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x69, 0x6d, 0x61,
0x67, 0x65, 0x55, 0x56, 0x2e, 0x78, 0x79, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x32, 0x28, 0x30, 0x2e, 0x30, 0x29, 0x2c, 0x20,
0x76, 0x65, 0x63, 0x32, 0x28, 0x31, 0x2e, 0x30, 0x29, 0x29, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x2c, 0x20, 0x31, 0x2e, 0x30,
0x29, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x32, 0x20, 0x5f, 0x34, 0x30, 0x38, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x30, 0x37, 0x2e,
0x78, 0x79, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x37, 0x36, 0x32, 0x3b, 0x00, 0x75, 0x6e, 0x69, 0x66, 0x6f,
0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x43, 0x75, 0x62, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
0x5f, 0x69, 0x62, 0x6c, 0x53, 0x70, 0x65, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x3b, 0x00, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74,
0x28, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x34, 0x29, 0x20, 0x69, 0x6e, 0x20, 0x76, 0x65,
0x63, 0x34, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x50, 0x6f, 0x73, 0x69, 0x74,
0x69, 0x6f, 0x6e, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x33, 0x20, 0x73, 0x68, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x69,
0x65, 0x77, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x66, 0x6f, 0x67, 0x28, 0x69, 0x6e, 0x6f, 0x75, 0x74, 0x20, 0x76,
0x65, 0x63, 0x34, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x33, 0x20, 0x76, 0x69, 0x65, 0x77,
0x29, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x5f, 0x31, 0x37, 0x37, 0x20, 0x3d, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74,
0x68, 0x28, 0x76, 0x69, 0x65, 0x77, 0x29, 0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x5f, 0x31, 0x37, 0x37, 0x20, 0x3e, 0x20,
0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x64, 0x7a, 0x7a, 0x29, 0x00, 0x72,
0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x5f,
0x32, 0x30, 0x35, 0x20, 0x3d, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e,
0x63, 0x7a, 0x7a, 0x20, 0x2a, 0x20, 0x76, 0x69, 0x65, 0x77, 0x2e, 0x79, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20,
0x5f, 0x37, 0x35, 0x33, 0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x61, 0x62, 0x73, 0x28, 0x5f, 0x32, 0x30, 0x35, 0x29, 0x20,
0x3e, 0x20, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x32, 0x35, 0x29, 0x00, 0x5f, 0x37, 0x35, 0x33, 0x20, 0x3d, 0x20, 0x66, 0x6d,
0x61, 0x28, 0x2d, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x79, 0x7a, 0x2e,
0x78, 0x2c, 0x20, 0x65, 0x78, 0x70, 0x28, 0x66, 0x6d, 0x61, 0x28, 0x2d, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69,
0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x63, 0x7a, 0x7a, 0x2c, 0x20, 0x76, 0x69, 0x65, 0x77, 0x2e, 0x79, 0x2c, 0x20, 0x66,
0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x79, 0x7a, 0x2e, 0x79, 0x29, 0x29, 0x2c,
0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x79, 0x7a, 0x2e, 0x7a, 0x29,
0x20, 0x2f, 0x20, 0x5f, 0x32, 0x30, 0x35, 0x3b, 0x00, 0x5f, 0x37, 0x35, 0x33, 0x20, 0x3d, 0x20, 0x66, 0x72, 0x61, 0x6d,
0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x79, 0x7a, 0x2e, 0x7a, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61,
0x74, 0x20, 0x5f, 0x32, 0x34, 0x35, 0x20, 0x3d, 0x20, 0x6d, 0x69, 0x6e, 0x28, 0x31, 0x2e, 0x30, 0x20, 0x2d, 0x20, 0x65,
0x78, 0x70, 0x28, 0x2d, 0x28, 0x5f, 0x37, 0x35, 0x33, 0x20, 0x2a, 0x20, 0x6d, 0x61, 0x78, 0x28, 0x5f, 0x31, 0x37, 0x37,
0x20, 0x2d, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x7a, 0x7a, 0x2c,
0x20, 0x30, 0x2e, 0x30, 0x29, 0x29, 0x29, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72,
0x6d, 0x73, 0x2e, 0x61, 0x7a, 0x7a, 0x29, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x37, 0x35, 0x34, 0x3b, 0x00,
0x5f, 0x37, 0x35, 0x34, 0x20, 0x3d, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73,
0x2e, 0x65, 0x7a, 0x7a, 0x20, 0x2a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x4c, 0x6f, 0x64, 0x28, 0x6c, 0x69,
0x67, 0x68, 0x74, 0x5f, 0x69, 0x62, 0x6c, 0x53, 0x70, 0x65, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x2c, 0x20, 0x76, 0x69, 0x65,
0x77, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x67, 0x7a, 0x29,
0x2e, 0x78, 0x79, 0x7a, 0x3b, 0x00, 0x5f, 0x37, 0x35, 0x34, 0x20, 0x3d, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e,
0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x65, 0x7a, 0x7a, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x32, 0x37,
0x37, 0x20, 0x3d, 0x20, 0x5f, 0x37, 0x35, 0x34, 0x20, 0x2a, 0x20, 0x28, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69,
0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x66, 0x7a, 0x20, 0x2a, 0x20, 0x5f, 0x32, 0x34, 0x35, 0x29, 0x3b, 0x00, 0x76, 0x65,
0x63, 0x33, 0x20, 0x5f, 0x37, 0x35, 0x36, 0x3b, 0x00, 0x5f, 0x37, 0x35, 0x36, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x37, 0x37,
0x20, 0x2b, 0x20, 0x28, 0x28, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x6b,
0x7a, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2a, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d,
0x73, 0x2e, 0x6b, 0x7a, 0x2e, 0x77, 0x29, 0x20, 0x2a, 0x20, 0x28, 0x70, 0x6f, 0x77, 0x28, 0x6d, 0x61, 0x78, 0x28, 0x64,
0x6f, 0x74, 0x28, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x2c, 0x20, 0x66, 0x72,
0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x69, 0x7a, 0x29, 0x2c, 0x20, 0x30, 0x2e, 0x30,
0x29, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x68, 0x7a, 0x7a,
0x29, 0x20, 0x2a, 0x20, 0x28, 0x31, 0x2e, 0x30, 0x20, 0x2d, 0x20, 0x65, 0x78, 0x70, 0x28, 0x2d, 0x28, 0x5f, 0x37, 0x35,
0x33, 0x20, 0x2a, 0x20, 0x6d, 0x61, 0x78, 0x28, 0x5f, 0x31, 0x37, 0x37, 0x20, 0x2d, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65,
0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x67, 0x7a, 0x7a, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x29, 0x29, 0x29,
0x29, 0x29, 0x29, 0x3b, 0x00, 0x5f, 0x37, 0x35, 0x36, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x37, 0x37, 0x3b, 0x00, 0x76, 0x65,
0x63, 0x34, 0x20, 0x5f, 0x33, 0x32, 0x36, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x00, 0x76, 0x65, 0x63,
0x33, 0x20, 0x5f, 0x33, 0x33, 0x32, 0x20, 0x3d, 0x20, 0x28, 0x5f, 0x33, 0x32, 0x36, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2a,
0x20, 0x28, 0x31, 0x2e, 0x30, 0x20, 0x2d, 0x20, 0x5f, 0x32, 0x34, 0x35, 0x29, 0x29, 0x20, 0x2b, 0x20, 0x5f, 0x37, 0x35,
0x36, 0x3b, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x78, 0x20, 0x3d, 0x20, 0x5f, 0x33, 0x33, 0x32, 0x2e, 0x78, 0x3b,
0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x5f, 0x33, 0x33, 0x32, 0x2e, 0x79, 0x3b, 0x00, 0x63,
0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x5f, 0x33, 0x33, 0x32, 0x2e, 0x7a, 0x3b, 0x00, 0x76, 0x65, 0x63,
0x33, 0x20, 0x5f, 0x37, 0x33, 0x37, 0x3b, 0x00, 0x5f, 0x37, 0x33, 0x37, 0x20, 0x3d, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65,
0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x62, 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2d, 0x20,
0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
0x2e, 0x78, 0x79, 0x7a, 0x3b, 0x00, 0x5f, 0x37, 0x33, 0x37, 0x20, 0x3d, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e,
0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x62, 0x5b, 0x32, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x3b, 0x00, 0x73, 0x68, 0x61,
0x64, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x20, 0x3d, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a,
0x65, 0x28, 0x5f, 0x37, 0x33, 0x37, 0x29, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x35, 0x39, 0x34, 0x20, 0x3d,
0x20, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x61, 0x20, 0x2a, 0x20,
0x76, 0x65, 0x63, 0x34, 0x28, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f,
0x69, 0x6d, 0x61, 0x67, 0x65, 0x55, 0x56, 0x2e, 0x78, 0x79, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x32, 0x28, 0x30, 0x2e, 0x30,
0x29, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x32, 0x28, 0x31, 0x2e, 0x30, 0x29, 0x29, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x2c, 0x20,
0x31, 0x2e, 0x30, 0x29, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x32, 0x20, 0x5f, 0x35, 0x39, 0x35, 0x20, 0x3d, 0x20, 0x5f, 0x35,
0x39, 0x34, 0x2e, 0x78, 0x79, 0x3b, 0x00, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x5f, 0x35, 0x39, 0x38, 0x20, 0x3d, 0x20, 0x6d,
0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x63, 0x20, 0x3d, 0x3d, 0x20, 0x30,
0x3b, 0x00, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x5f, 0x36, 0x30, 0x35, 0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x21, 0x5f, 0x35,
0x39, 0x38, 0x29, 0x00, 0x5f, 0x36, 0x30, 0x35, 0x20, 0x3d, 0x20, 0x5f, 0x35, 0x39, 0x34, 0x2e, 0x78, 0x20, 0x3e, 0x20,
0x31, 0x2e, 0x30, 0x3b, 0x00, 0x5f, 0x36, 0x30, 0x35, 0x20, 0x3d, 0x20, 0x5f, 0x35, 0x39, 0x38, 0x3b, 0x00, 0x5f, 0x36,
0x31, 0x32, 0x20, 0x3d, 0x20, 0x5f, 0x35, 0x39, 0x34, 0x2e, 0x78, 0x20, 0x3c, 0x20, 0x30, 0x2e, 0x30, 0x3b, 0x00, 0x5f,
0x36, 0x31, 0x39, 0x20, 0x3d, 0x20, 0x5f, 0x35, 0x39, 0x34, 0x2e, 0x79, 0x20, 0x3c, 0x20, 0x30, 0x2e, 0x30, 0x3b, 0x00,
0x5f, 0x36, 0x32, 0x36, 0x20, 0x3d, 0x20, 0x5f, 0x35, 0x39, 0x34, 0x2e, 0x79, 0x20, 0x3e, 0x20, 0x31, 0x2e, 0x30, 0x3b,
0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x37, 0x35, 0x32, 0x3b, 0x00, 0x69, 0x66, 0x20, 0x28, 0x5f, 0x36, 0x32, 0x36,
0x29, 0x00, 0x5f, 0x37, 0x35, 0x32, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72,
0x61, 0x6d, 0x73, 0x2e, 0x62, 0x3b, 0x00, 0x5f, 0x35, 0x39, 0x35, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x20,
0x2d, 0x20, 0x5f, 0x35, 0x39, 0x34, 0x2e, 0x79, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x36, 0x34, 0x31, 0x20,
0x3d, 0x20, 0x6d, 0x61, 0x78, 0x28, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x28, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69,
0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x5f, 0x35, 0x39, 0x35,
0x2c, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x70, 0x29, 0x2c, 0x20,
0x76, 0x65, 0x63, 0x34, 0x28, 0x30, 0x2e, 0x30, 0x29, 0x29, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x5f, 0x36,
0x34, 0x33, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x34, 0x31, 0x2e, 0x77, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x36,
0x34, 0x36, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x34, 0x31, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2a, 0x20, 0x5f, 0x36, 0x34, 0x33,
0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x37, 0x32, 0x31, 0x3b, 0x00, 0x5f, 0x37, 0x32, 0x31, 0x2e, 0x78, 0x20,
0x3d, 0x20, 0x5f, 0x36, 0x34, 0x36, 0x2e, 0x78, 0x3b, 0x00, 0x5f, 0x37, 0x32, 0x31, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x5f,
0x36, 0x34, 0x36, 0x2e, 0x79, 0x3b, 0x00, 0x5f, 0x37, 0x32, 0x31, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x34, 0x36,
0x2e, 0x7a, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x36, 0x36, 0x32, 0x20, 0x3d, 0x20, 0x5f, 0x37, 0x32, 0x31,
0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2b, 0x20, 0x28, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61,
0x6d, 0x73, 0x2e, 0x62, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2a, 0x20, 0x28, 0x31, 0x2e, 0x30, 0x20, 0x2d, 0x20, 0x5f, 0x36,
0x34, 0x33, 0x29, 0x29, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x37, 0x32, 0x38, 0x20, 0x3d, 0x20, 0x76, 0x65,
0x63, 0x34, 0x28, 0x31, 0x2e, 0x30, 0x29, 0x3b, 0x00, 0x5f, 0x37, 0x32, 0x38, 0x2e, 0x78, 0x20, 0x3d, 0x20, 0x5f, 0x36,
0x36, 0x32, 0x2e, 0x78, 0x3b, 0x00, 0x5f, 0x37, 0x32, 0x38, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x36, 0x32, 0x2e,
0x79, 0x3b, 0x00, 0x5f, 0x37, 0x32, 0x38, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x5f, 0x36, 0x36, 0x32, 0x2e, 0x7a, 0x3b, 0x00,
0x5f, 0x37, 0x35, 0x32, 0x20, 0x3d, 0x20, 0x5f, 0x37, 0x32, 0x38, 0x3b, 0x00, 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c,
0x6f, 0x72, 0x20, 0x3d, 0x20, 0x5f, 0x37, 0x35, 0x32, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x70, 0x61, 0x72, 0x61,
0x6d, 0x20, 0x3d, 0x20, 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x33, 0x20,
0x70, 0x61, 0x72, 0x61, 0x6d, 0x5f, 0x31, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x77, 0x6f, 0x72,
0x6c, 0x64, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2d, 0x20, 0x66, 0x72, 0x61,
0x6d, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x62, 0x5b, 0x33, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x3b,
0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x5f, 0x34, 0x38, 0x32, 0x20, 0x3d, 0x20, 0x66, 0x6f, 0x67, 0x28, 0x70, 0x61, 0x72,
0x61, 0x6d, 0x2c, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x5f, 0x31, 0x29, 0x3b, 0x00, 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f,
0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x38, 0x32, 0x3b, 0x00, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x77, 0x6f, 0x72,
0x6c, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x3b, 0x00, 0x6d,
0x61, 0x74, 0x33, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x4e, 0x6f,
0x72, 0x6d, 0x61, 0x6c, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x3b, 0x00, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x6d, 0x6f, 0x72,
0x70, 0x68, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x3b, 0x00, 0x75, 0x69, 0x6e, 0x74, 0x20,
0x66, 0x6c, 0x61, 0x67, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x3b, 0x00, 0x75, 0x69, 0x6e, 0x74, 0x20,
0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x3b, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x75, 0x73, 0x65, 0x72,
0x44, 0x61, 0x74, 0x61, 0x3b, 0x00, 0x76, 0x65, 0x63, 0x34, 0x20, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5b,
0x38, 0x5d, 0x3b, 0x00, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
0x3d, 0x20, 0x38, 0x29, 0x20, 0x66, 0x6c, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x73,
0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3b, 0x00, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28,
0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x75, 0x76,
0x65, 0x63, 0x32, 0x20, 0x6f, 0x75, 0x74, 0x50, 0x69, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3b, 0x00, 0x6c, 0x61, 0x79, 0x6f,
0x75, 0x74, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x37, 0x29, 0x20, 0x69, 0x6e, 0x20,
0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
0x3b, 0x00, 0x4c, 0x53, 0x4c, 0x47, 0x5f, 0x54, 0x41, 0x4d, 0xdc, 0x08, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x50, 0x01, 0x00, 0x00, 0x01, 0x10, 0x00, 0x6a,
0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x84, 0x02, 0x00, 0x00, 0x01, 0x20, 0x01, 0x98, 0x02, 0x00, 0x00, 0x01, 0x30, 0x01,
0x54, 0x04, 0x00, 0x00, 0x01, 0x44, 0x01, 0x96, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0xae, 0x04, 0x00, 0x00, 0x02, 0x00,
0x01, 0x96, 0x05, 0x00, 0x00, 0x02, 0x10, 0x00, 0xae, 0x04, 0x00, 0x00, 0x02, 0x10, 0x01, 0xc8, 0x06, 0x00, 0x00, 0x02,
0x20, 0x01, 0xda, 0x06, 0x00, 0x00, 0x02, 0x30, 0x01, 0x86, 0x08, 0x00, 0x00, 0x02, 0x44, 0x01, 0xc6, 0x08, 0x00, 0x00,
0xbb, 0x07, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00,
0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00,
0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00,
0x1a, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x1d, 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00,
0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x28, 0x00, 0x29, 0x00, 0x2a, 0x00, 0x2b, 0x00, 0x2c, 0x00, 0x2d, 0x00,
0x2e, 0x00, 0x2f, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00,
0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x40, 0x00, 0x41, 0x00,
0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4a, 0x00, 0x4b, 0x00,
0x4c, 0x00, 0x4d, 0x00, 0x4e, 0x00, 0x02, 0x00, 0x4f, 0x00, 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00,
0x55, 0x00, 0x56, 0x00, 0x02, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0x5c, 0x00,
0x5a, 0x00, 0x5d, 0x00, 0x5e, 0x00, 0x5f, 0x00, 0x60, 0x00, 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0x64, 0x00, 0x65, 0x00,
0x66, 0x00, 0x67, 0x00, 0x68, 0x00, 0x69, 0x00, 0x5a, 0x00, 0x06, 0x08, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00,
0x6a, 0x00, 0x6b, 0x00, 0x6c, 0x00, 0x01, 0x00, 0x02, 0x00, 0x6d, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x71, 0x00,
0x72, 0x00, 0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 0x76, 0x00, 0x77, 0x00, 0x78, 0x00, 0x79, 0x00, 0x7a, 0x00, 0x7b, 0x00,
0x7c, 0x00, 0x7d, 0x00, 0x7e, 0x00, 0x7f, 0x00, 0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85, 0x00,
0x86, 0x00, 0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x8a, 0x00, 0x8b, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8e, 0x00, 0x8f, 0x00,
0x90, 0x00, 0x91, 0x00, 0x92, 0x00, 0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, 0x98, 0x00, 0x99, 0x00,
0x9a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x9e, 0x00, 0x9f, 0x00, 0xa0, 0x00, 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00,
0xa4, 0x00, 0xa5, 0x00, 0xa6, 0x00, 0xa7, 0x00, 0xa8, 0x00, 0xa9, 0x00, 0xaa, 0x00, 0xab, 0x00, 0xac, 0x00, 0xad, 0x00,
0xae, 0x00, 0xaf, 0x00, 0xb0, 0x00, 0xb1, 0x00, 0x48, 0x00, 0xb2, 0x00, 0x02, 0x00, 0x6d, 0x00, 0xb3, 0x00, 0xb4, 0x00,
0xb5, 0x00, 0xb6, 0x00, 0xb7, 0x00, 0xb8, 0x00, 0x4e, 0x00, 0x02, 0x00, 0xb9, 0x00, 0xba, 0x00, 0xbb, 0x00, 0xbc, 0x00,
0xbd, 0x00, 0x02, 0x00, 0xbe, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0xbf, 0x00, 0x5a, 0x00, 0xc0, 0x00, 0xc1, 0x00,
0x02, 0x00, 0xc2, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x5a, 0x00, 0xc4, 0x00, 0xc5, 0x00, 0x02, 0x00,
0xc6, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0xc7, 0x00, 0x5a, 0x00, 0xc8, 0x00, 0xc9, 0x00, 0x02, 0x00, 0xca, 0x00,
0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0xcb, 0x00, 0x5a, 0x00, 0xcc, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xce, 0x00, 0x5a, 0x00,
0x5b, 0x00, 0x02, 0x00, 0xcf, 0x00, 0xd0, 0x00, 0xd1, 0x00, 0xd2, 0x00, 0xd3, 0x00, 0xd4, 0x00, 0xd5, 0x00, 0xd6, 0x00,
0xd7, 0x00, 0xd8, 0x00, 0xd9, 0x00, 0xda, 0x00, 0xdb, 0x00, 0xdc, 0x00, 0x5a, 0x00, 0xdd, 0x00, 0x5a, 0x00, 0x51, 0x00,
0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x02, 0x00, 0x5a, 0x00, 0x51, 0x0e,
0x00, 0x00, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x6b, 0x00, 0xde, 0x00, 0x01, 0x00, 0x02, 0x00, 0x6d, 0x00,
0x6e, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x71, 0x00, 0x72, 0x00, 0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 0x76, 0x00, 0x77, 0x00,
0x78, 0x00, 0x79, 0x00, 0x7a, 0x00, 0x7b, 0x00, 0x7c, 0x00, 0x7d, 0x00, 0x7e, 0x00, 0x7f, 0x00, 0x80, 0x00, 0x81, 0x00,
0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x8a, 0x00, 0x8b, 0x00,
0x8c, 0x00, 0x8d, 0x00, 0x8e, 0x00, 0x8f, 0x00, 0x90, 0x00, 0x91, 0x00, 0x92, 0x00, 0x93, 0x00, 0x94, 0x00, 0x95, 0x00,
0x96, 0x00, 0x97, 0x00, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x9e, 0x00, 0x9f, 0x00,
0xa0, 0x00, 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa5, 0x00, 0xa6, 0x00, 0xa7, 0x00, 0xa8, 0x00, 0xa9, 0x00,
0xaa, 0x00, 0xab, 0x00, 0xac, 0x00, 0xad, 0x00, 0xae, 0x00, 0xaf, 0x00, 0xb0, 0x00, 0xb1, 0x00, 0x48, 0x00, 0xb2, 0x00,
0x02, 0x00, 0x6d, 0x00, 0xb3, 0x00, 0xb4, 0x00, 0xb5, 0x00, 0xdf, 0x00, 0xb6, 0x00, 0xe0, 0x00, 0xb7, 0x00, 0xb8, 0x00,
0x4e, 0x00, 0x02, 0x00, 0xe1, 0x00, 0xe2, 0x00, 0x02, 0x00, 0xe3, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0xe4, 0x00,
0x5a, 0x00, 0xe5, 0x00, 0xe6, 0x00, 0xe7, 0x00, 0xe8, 0x00, 0xe9, 0x00, 0xea, 0x00, 0xeb, 0x00, 0x02, 0x00, 0xec, 0x00,
0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0xed, 0x00, 0x5a, 0x00, 0xee, 0x00, 0xef, 0x00, 0x02, 0x00, 0xf0, 0x00, 0x5a, 0x00,
0x5b, 0x00, 0x02, 0x00, 0xf1, 0x00, 0x5a, 0x00, 0xf2, 0x00, 0xf3, 0x00, 0x02, 0x00, 0xf4, 0x00, 0x5a, 0x00, 0x5b, 0x00,
0x02, 0x00, 0xf5, 0x00, 0x5a, 0x00, 0xf6, 0x00, 0xf7, 0x00, 0x02, 0x00, 0xf8, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00,
0xf9, 0x00, 0x5a, 0x00, 0xfa, 0x00, 0xfb, 0x00, 0x02, 0x00, 0xfc, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0xfd, 0x00,
0xfe, 0x00, 0xff, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x03, 0x01, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x07, 0x01,
0x08, 0x01, 0x09, 0x01, 0x0a, 0x01, 0x5a, 0x00, 0x0b, 0x01, 0x0c, 0x01, 0x0d, 0x01, 0x0e, 0x01, 0x0f, 0x01, 0x02, 0x00,
0x10, 0x01, 0x11, 0x01, 0x02, 0x00, 0x12, 0x01, 0x13, 0x01, 0x5a, 0x00, 0x14, 0x01, 0x15, 0x01, 0x16, 0x01, 0x17, 0x01,
0x02, 0x00, 0x18, 0x01, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0x19, 0x01, 0x5a, 0x00, 0x1a, 0x01, 0x1b, 0x01, 0x1c, 0x01,
0x1d, 0x01, 0x1e, 0x01, 0x02, 0x00, 0x1f, 0x01, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0x20, 0x01, 0x5a, 0x00, 0x21, 0x01,
0x22, 0x01, 0x23, 0x01, 0x02, 0x00, 0x24, 0x01, 0x25, 0x01, 0x26, 0x01, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0x27, 0x01,
0x5a, 0x00, 0x28, 0x01, 0x29, 0x01, 0x2a, 0x01, 0x2b, 0x01, 0x2c, 0x01, 0x2d, 0x01, 0x13, 0x01, 0x2e, 0x01, 0x2f, 0x01,
0x5a, 0x00, 0x13, 0x03, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x6b, 0x00, 0x30, 0x01, 0x02, 0x00,
0x31, 0x01, 0x32, 0x01, 0x33, 0x01, 0x34, 0x01, 0x35, 0x01, 0x36, 0x01, 0x37, 0x01, 0x38, 0x01, 0x39, 0x01, 0x3a, 0x01,
0x3b, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0x02, 0x00, 0x3e, 0x01, 0x3f, 0x01, 0x40, 0x01, 0x41, 0x01, 0x42, 0x01, 0x4e, 0x00,
0x02, 0x00, 0x43, 0x01, 0x44, 0x01, 0x5a, 0x00, 0x91, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x00,
0x6b, 0x00, 0xb8, 0x00, 0x4e, 0x00, 0x02, 0x00, 0x45, 0x01, 0x5a, 0x00, 0xea, 0x06, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
0x46, 0x01, 0x47, 0x01, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00,
0x09, 0x00, 0x0a, 0x00, 0x75, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x7c, 0x00,
0x7d, 0x00, 0x14, 0x00, 0x15, 0x00, 0x80, 0x00, 0x17, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85, 0x00, 0x86, 0x00,
0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x8a, 0x00, 0x8b, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8e, 0x00, 0x8f, 0x00, 0x90, 0x00,
0x91, 0x00, 0x92, 0x00, 0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x2c, 0x00, 0x97, 0x00, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00,
0x9b, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x9e, 0x00, 0x35, 0x00, 0x36, 0x00, 0xa1, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00,
0xa5, 0x00, 0xa6, 0x00, 0x3d, 0x00, 0xa8, 0x00, 0xa9, 0x00, 0xaa, 0x00, 0x41, 0x00, 0x42, 0x00, 0xad, 0x00, 0xae, 0x00,
0xaf, 0x00, 0xb0, 0x00, 0xb1, 0x00, 0x48, 0x00, 0x48, 0x01, 0x4a, 0x00, 0x49, 0x01, 0x4a, 0x01, 0x4b, 0x01, 0x4e, 0x00,
0x02, 0x00, 0x4f, 0x00, 0x4c, 0x01, 0x4d, 0x01, 0x4e, 0x01, 0x4f, 0x01, 0x50, 0x01, 0x51, 0x01, 0x52, 0x01, 0x02, 0x00,
0x53, 0x01, 0x54, 0x01, 0x55, 0x01, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0x56, 0x01, 0x5a, 0x00, 0x57, 0x01, 0x58, 0x01,
0x59, 0x01, 0x5a, 0x01, 0x5b, 0x01, 0x5c, 0x01, 0x5d, 0x01, 0x5e, 0x01, 0x5f, 0x01, 0x60, 0x01, 0x61, 0x01, 0x68, 0x00,
0x69, 0x00, 0x5a, 0x00, 0x60, 0x07, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x46, 0x01, 0x47, 0x01, 0x6c, 0x00, 0x01, 0x00,
0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x75, 0x00,
0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x7c, 0x00, 0x7d, 0x00, 0x14, 0x00, 0x15, 0x00,
0x80, 0x00, 0x17, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x87, 0x00, 0x88, 0x00, 0x89, 0x00,
0x8a, 0x00, 0x8b, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8e, 0x00, 0x8f, 0x00, 0x90, 0x00, 0x91, 0x00, 0x92, 0x00, 0x93, 0x00,
0x94, 0x00, 0x95, 0x00, 0x2c, 0x00, 0x97, 0x00, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0x9d, 0x00,
0x9e, 0x00, 0x35, 0x00, 0x36, 0x00, 0xa1, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0xa5, 0x00, 0xa6, 0x00, 0x3d, 0x00,
0xa8, 0x00, 0xa9, 0x00, 0xaa, 0x00, 0x41, 0x00, 0x42, 0x00, 0xad, 0x00, 0xae, 0x00, 0xaf, 0x00, 0xb0, 0x00, 0xb1, 0x00,
0x48, 0x00, 0xb2, 0x00, 0x02, 0x00, 0x03, 0x00, 0xb3, 0x00, 0xb4, 0x00, 0xb5, 0x00, 0x62, 0x01, 0x63, 0x01, 0xb8, 0x00,
0x4e, 0x00, 0x02, 0x00, 0x64, 0x01, 0x65, 0x01, 0xbb, 0x00, 0xbc, 0x00, 0xbd, 0x00, 0x02, 0x00, 0xbe, 0x00, 0x5a, 0x00,
0x5b, 0x00, 0x02, 0x00, 0xbf, 0x00, 0x5a, 0x00, 0xc0, 0x00, 0xc1, 0x00, 0x02, 0x00, 0xc2, 0x00, 0x5a, 0x00, 0x5b, 0x00,
0x02, 0x00, 0xc3, 0x00, 0x5a, 0x00, 0xc4, 0x00, 0xc5, 0x00, 0x02, 0x00, 0xc6, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00,
0xc7, 0x00, 0x5a, 0x00, 0xc8, 0x00, 0xc9, 0x00, 0x02, 0x00, 0xca, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0xcb, 0x00,
0x5a, 0x00, 0xcc, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xce, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0xcf, 0x00, 0xd0, 0x00,
0xd1, 0x00, 0xd2, 0x00, 0xd3, 0x00, 0xd4, 0x00, 0xd5, 0x00, 0xd6, 0x00, 0xd7, 0x00, 0xd8, 0x00, 0xd9, 0x00, 0xda, 0x00,
0xdb, 0x00, 0xdc, 0x00, 0x5a, 0x00, 0xdd, 0x00, 0x5a, 0x00, 0x52, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46, 0x01,
0x47, 0x01, 0x4e, 0x00, 0x02, 0x00, 0x5a, 0x00, 0x28, 0x0d, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x46, 0x01, 0x47, 0x01,
0x66, 0x01, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00,
0x0a, 0x00, 0x75, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x7c, 0x00, 0x7d, 0x00,
0x14, 0x00, 0x15, 0x00, 0x80, 0x00, 0x17, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x87, 0x00,
0x88, 0x00, 0x89, 0x00, 0x8a, 0x00, 0x8b, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8e, 0x00, 0x8f, 0x00, 0x90, 0x00, 0x91, 0x00,
0x92, 0x00, 0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x2c, 0x00, 0x97, 0x00, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b, 0x00,
0x9c, 0x00, 0x9d, 0x00, 0x9e, 0x00, 0x35, 0x00, 0x36, 0x00, 0xa1, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0xa5, 0x00,
0xa6, 0x00, 0x3d, 0x00, 0xa8, 0x00, 0xa9, 0x00, 0xaa, 0x00, 0x41, 0x00, 0x42, 0x00, 0xad, 0x00, 0xae, 0x00, 0xaf, 0x00,
0xb0, 0x00, 0xb1, 0x00, 0x48, 0x00, 0xb2, 0x00, 0x02, 0x00, 0x03, 0x00, 0xb3, 0x00, 0xb4, 0x00, 0xb5, 0x00, 0x67, 0x01,
0x62, 0x01, 0x68, 0x01, 0x63, 0x01, 0xb8, 0x00, 0x69, 0x01, 0x6a, 0x01, 0x02, 0x00, 0x6b, 0x01, 0x6c, 0x01, 0x02, 0x00,
0x6d, 0x01, 0x5a, 0x00, 0x6e, 0x01, 0x6f, 0x01, 0x70, 0x01, 0x02, 0x00, 0x71, 0x01, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00,
0x72, 0x01, 0x5a, 0x00, 0x73, 0x01, 0x74, 0x01, 0x1e, 0x01, 0x02, 0x00, 0x75, 0x01, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00,
0x76, 0x01, 0x5a, 0x00, 0x77, 0x01, 0x78, 0x01, 0x23, 0x01, 0x02, 0x00, 0x79, 0x01, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00,
0x7a, 0x01, 0x5a, 0x00, 0x7b, 0x01, 0x7c, 0x01, 0x7d, 0x01, 0x7e, 0x01, 0x7f, 0x01, 0x6d, 0x01, 0x5a, 0x00, 0x4e, 0x00,
0x02, 0x00, 0x80, 0x01, 0xe2, 0x00, 0x02, 0x00, 0x81, 0x01, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0x82, 0x01, 0x5a, 0x00,
0x83, 0x01, 0x84, 0x01, 0x85, 0x01, 0x86, 0x01, 0x87, 0x01, 0x88, 0x01, 0x02, 0x00, 0x89, 0x01, 0x5a, 0x00, 0x5b, 0x00,
0x02, 0x00, 0x8a, 0x01, 0x5a, 0x00, 0xea, 0x00, 0xeb, 0x00, 0x02, 0x00, 0x8b, 0x01, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00,
0xed, 0x00, 0x5a, 0x00, 0xee, 0x00, 0xef, 0x00, 0x02, 0x00, 0x8c, 0x01, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0xf1, 0x00,
0x5a, 0x00, 0xf2, 0x00, 0xf3, 0x00, 0x02, 0x00, 0x8d, 0x01, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0xf5, 0x00, 0x5a, 0x00,
0x8e, 0x01, 0x8f, 0x01, 0x02, 0x00, 0x90, 0x01, 0x5a, 0x00, 0x5b, 0x00, 0x02, 0x00, 0x91, 0x01, 0x92, 0x01, 0x93, 0x01,
0x94, 0x01, 0x95, 0x01, 0x96, 0x01, 0x97, 0x01, 0x98, 0x01, 0x99, 0x01, 0x9a, 0x01, 0x9b, 0x01, 0x9c, 0x01, 0x9d, 0x01,
0x9e, 0x01, 0x5a, 0x00, 0x9f, 0x01, 0xa0, 0x01, 0xa1, 0x01, 0xa2, 0x01, 0xa3, 0x01, 0x5a, 0x00, 0x02, 0x03, 0x00, 0x00,
0x1c, 0x00, 0x00, 0x00, 0x46, 0x01, 0x47, 0x01, 0x30, 0x01, 0x02, 0x00, 0xa4, 0x01, 0xa5, 0x01, 0xa6, 0x01, 0xa7, 0x01,
0xa8, 0x01, 0xa9, 0x01, 0xaa, 0x01, 0x38, 0x01, 0x39, 0x01, 0x3a, 0x01, 0x3b, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0x02, 0x00,
0x3e, 0x01, 0x3f, 0x01, 0xab, 0x01, 0xac, 0x01, 0xad, 0x01, 0x4e, 0x00, 0x02, 0x00, 0x43, 0x01, 0x44, 0x01, 0x5a, 0x00,
0x92, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x46, 0x01, 0x47, 0x01, 0xb8, 0x00, 0x4e, 0x00, 0x02, 0x00, 0x45, 0x01,
0x5a, 0x00,
};
int IMAGE_IMAGE_OFFSET = 0;
int IMAGE_IMAGE_SIZE = 13622;
@@ -1,13 +0,0 @@
#ifndef IMAGE_H_
#define IMAGE_H_
#include <stdint.h>
extern "C" {
extern const uint8_t IMAGE_PACKAGE[];
extern int IMAGE_IMAGE_OFFSET;
extern int IMAGE_IMAGE_SIZE;
}
#define IMAGE_IMAGE_DATA (IMAGE_PACKAGE + IMAGE_IMAGE_OFFSET)
#endif
@@ -1,3 +1,31 @@
## 0.2.1-dev.16
- Update a dependency to the latest release.
## 0.2.1-dev.15
- Update a dependency to the latest release.
## 0.2.1-dev.14
- Update a dependency to the latest release.
## 0.2.1-dev.13
- Update a dependency to the latest release.
## 0.2.1-dev.12
- Update a dependency to the latest release.
## 0.2.1-dev.11
- Update a dependency to the latest release.
## 0.2.1-dev.10
- Update a dependency to the latest release.
## 0.2.1-dev.9 ## 0.2.1-dev.9
> Note: This release has breaking changes. > Note: This release has breaking changes.
@@ -1,7 +1,7 @@
name: thermion_flutter_ffi name: thermion_flutter_ffi
description: An FFI implementation for thermion_flutter (i.e. all platforms except web). description: An FFI implementation for thermion_flutter (i.e. all platforms except web).
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
version: 0.2.1-dev.9 version: 0.2.1-dev.16
environment: environment:
sdk: ">=3.3.0 <4.0.0" sdk: ">=3.3.0 <4.0.0"
@@ -23,8 +23,8 @@ dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
plugin_platform_interface: ^2.1.0 plugin_platform_interface: ^2.1.0
thermion_flutter_platform_interface: ^0.2.1-dev.9 thermion_flutter_platform_interface: ^0.2.1-dev.16
thermion_dart: ^0.2.1-dev.0.0.10 thermion_dart: ^0.2.1-dev.0.0.16
logging: ^1.2.0 logging: ^1.2.0
dev_dependencies: dev_dependencies:
@@ -1,3 +1,31 @@
## 0.2.1-dev.16
- Update a dependency to the latest release.
## 0.2.1-dev.15
- Update a dependency to the latest release.
## 0.2.1-dev.14
- Update a dependency to the latest release.
## 0.2.1-dev.13
- Update a dependency to the latest release.
## 0.2.1-dev.12
- Update a dependency to the latest release.
## 0.2.1-dev.11
- Update a dependency to the latest release.
## 0.2.1-dev.10
- Update a dependency to the latest release.
## 0.2.1-dev.9 ## 0.2.1-dev.9
> Note: This release has breaking changes. > Note: This release has breaking changes.
@@ -1,7 +1,7 @@
name: thermion_flutter_platform_interface name: thermion_flutter_platform_interface
description: A common platform interface for the thermion_flutter plugin. description: A common platform interface for the thermion_flutter plugin.
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
version: 0.2.1-dev.9 version: 0.2.1-dev.16
environment: environment:
sdk: ">=3.3.0 <4.0.0" sdk: ">=3.3.0 <4.0.0"
@@ -11,7 +11,7 @@ dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
plugin_platform_interface: ^2.1.0 plugin_platform_interface: ^2.1.0
thermion_dart: ^0.2.1-dev.0.0.10 thermion_dart: ^0.2.1-dev.0.0.16
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
@@ -1,3 +1,31 @@
## 0.2.0+7
- Update a dependency to the latest release.
## 0.2.0+6
- Update a dependency to the latest release.
## 0.2.0+5
- Update a dependency to the latest release.
## 0.2.0+4
- Update a dependency to the latest release.
## 0.2.0+3
- Update a dependency to the latest release.
## 0.2.0+2
- Update a dependency to the latest release.
## 0.2.0+1
- Update a dependency to the latest release.
## 0.2.0 ## 0.2.0
> Note: This release has breaking changes. > Note: This release has breaking changes.
@@ -1,7 +1,7 @@
name: thermion_flutter_web name: thermion_flutter_web
description: A web platform interface for the thermion_flutter plugin. description: A web platform interface for the thermion_flutter plugin.
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
version: 0.2.0 version: 0.2.0+7
environment: environment:
sdk: ">=3.3.0 <4.0.0" sdk: ">=3.3.0 <4.0.0"
@@ -20,8 +20,8 @@ dependencies:
sdk: flutter sdk: flutter
plugin_platform_interface: ^2.1.0 plugin_platform_interface: ^2.1.0
web: ^1.0.0 web: ^1.0.0
thermion_dart: ^0.2.1-dev.0.0.10 thermion_dart: ^0.2.1-dev.0.0.16
thermion_flutter_platform_interface: ^0.2.1-dev.9 thermion_flutter_platform_interface: ^0.2.1-dev.16
flutter_web_plugins: flutter_web_plugins:
sdk: flutter sdk: flutter