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

View File

@@ -2,7 +2,6 @@
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
name: Dart
on:
@@ -12,31 +11,96 @@ on:
branches: [ "develop" ]
jobs:
build:
runs-on: macos-13
thermion_dart:
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:
- 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.
# You can specify other versions if desired, see documentation here:
# https://github.com/dart-lang/setup-dart/blob/main/README.md
# - uses: dart-lang/setup-dart@v1
- uses: dart-lang/setup-dart@9a04e6d73cca37bd455e0608d7e5092f881fd603
# Setup Visual Studio environment
- name: Setup MSVC
uses: ilammy/msvc-dev-cmd@v1
with:
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
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.
# - name: Verify formatting
# run: dart format --output=none --set-exit-if-changed .
# Consider passing '--fatal-infos' for slightly stricter analysis.
- name: Analyze project source
run: dart analyze
#- name: Analyze project source
# run: dart analyze
# Your project will need to have tests in test/ and a dependency on
# package:test for this step to succeed. Note that Flutter projects will
# want to change this to 'flutter test'.
- name: Run tests
run: dart --enable-experiment=native-assets test
- name: Build and Test
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
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

View File

@@ -3,6 +3,294 @@
All notable changes to this project will be documented in this file.
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
### Changes

View File

@@ -23,7 +23,7 @@ bindings:
#
materials: FORCE
@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)/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; \

View File

@@ -3,7 +3,7 @@
<p align="center">
<a href="https://thermion.dev/quickstart">Quickstart (Flutter)</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://discord.gg/h2VdDK3EAQ">Discord</a>
</p>
@@ -24,13 +24,17 @@
### Quickstart (Flutter)
```
From the command line:
```bash
flutter channel master
flutter upgrade
flutter config --enable-native-assets
```
```
In your Flutter app:
```dart
_thermionViewer = await ThermionFlutterPlugin.createViewer();
// 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);
```
and then in your Flutter application:
```
and then in your widget tree:
```dart
@override
Widget build(BuildContext context) {
return Stack(children: [

View File

@@ -7,7 +7,8 @@
"Getting Started",
[
["Overview", "/"],
["Quick Start", "/quickstart"]
["Quick Start", "/quickstart"],
["Camera Manipulation", "/camera_manipulation"]
]
],
["Misc.", [

View File

@@ -0,0 +1 @@
../../assets

View File

@@ -1 +0,0 @@
../../../assets/cube.glb

View File

@@ -1 +0,0 @@
../../../assets/default_env_ibl.ktx

View File

@@ -1 +0,0 @@
../../../assets/default_env_skybox.ktx

View File

@@ -15,13 +15,23 @@ dependencies:
win32: 5.5.1
web: 1.0.0
thermion_flutter: ^0.2.1-dev.8
thermion_flutter: ^0.2.1-dev.9
dev_dependencies:
flutter_test:
sdk: flutter
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:
uses-material-design: true
assets:

View File

@@ -0,0 +1 @@
../../assets

View File

@@ -1 +0,0 @@
../../../assets/cube.glb

View File

@@ -1 +0,0 @@
../../../assets/default_env_ibl.ktx

View File

@@ -1 +0,0 @@
../../../assets/default_env_skybox.ktx

View File

@@ -87,6 +87,7 @@
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; };
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>"; };
/* End PBXFileReference section */
@@ -188,6 +189,7 @@
33FAB671232836740065AC1E /* Runner */ = {
isa = PBXGroup;
children = (
DB0270912CD09BDD00E05CE4 /* RunnerDebug.entitlements */,
33CC10F02044A3C60003C045 /* AppDelegate.swift */,
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
33E51913231747F40026EE4D /* DebugProfile.entitlements */,
@@ -703,7 +705,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
CODE_SIGN_ENTITLEMENTS = Runner/RunnerDebug.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = Runner/Info.plist;

View File

@@ -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>

View File

@@ -16,6 +16,16 @@ dependencies:
web: 1.0.0
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:
flutter_test:
sdk: flutter

View File

@@ -1,3 +1,178 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bca5e20d7fa68fbc2bb7fa3cd65b07e0ac35c8cf961686cfaa267a941ab96d8f
size 7393
material {
name : unlit_fade,
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}
}
}

View File

@@ -1,5 +1,5 @@
material {
name : Gizmo,
name : UnlitFixedSize,
parameters : [
{
type : mat4,
@@ -8,8 +8,13 @@
},
{
type : float4,
name : color,
name : baseColorFactor,
precision : low
},
{
type: float, // the number of world-space units between the camera and the (unscaled) gizmo
name: scale,
precision: low
}
],
depthWrite : true,
@@ -24,14 +29,13 @@
vertex {
void materialVertex(inout MaterialVertexInputs material) {
// we want to ensure the gizmo has the same size (in screen-space), no matter the distance from the camera
// we do this by scaling the model-space vertex positions by the distance from the camera
// the object should have 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
vec4 modelSpace = getPosition();
vec4 worldSpace = getWorldFromModelMatrix() * modelSpace;
vec4 viewSpace = getViewFromWorldMatrix() * worldSpace;
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;
material.worldPosition = worldSpace;
@@ -44,7 +48,7 @@
fragment {
void material(inout MaterialInputs material) {
prepareMaterial(material);
material.baseColor = materialParams.color;
material.baseColor = materialParams.baseColorFactor;
}
}

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
> Note: This release has breaking changes.

View File

@@ -3,7 +3,7 @@
<p align="center">
<a href="https://thermion.dev/quickstart">Quickstart (Flutter)</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://discord.gg/h2VdDK3EAQ">Discord</a>
</p>

View File

@@ -3,11 +3,15 @@ import 'package:archive/archive.dart';
import 'package:logging/logging.dart';
import 'package:native_assets_cli/native_assets_cli.dart';
import 'package:native_toolchain_c/native_toolchain_c.dart';
import 'package:path/path.dart' as path;
void main(List<String> args) 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()) {
logFile.parent.createSync(recursive: true);
}
@@ -50,16 +54,16 @@ void main(List<String> args) async {
final packageName = config.packageName;
final sources = Directory("${config.packageRoot.toFilePath()}/native/src")
final sources = Directory(path.join(pkgRootFilePath, "native", "src"))
.listSync(recursive: true)
.whereType<File>()
.map((f) => f.path)
.toList();
sources.addAll([
"${config.packageRoot.toFilePath()}/native/include/material/gizmo_material.c",
"${config.packageRoot.toFilePath()}/native/include/material/image.c",
"${config.packageRoot.toFilePath()}/native/include/material/grid.c",
"${config.packageRoot.toFilePath()}/native/include/material/unlit.c",
path.join(pkgRootFilePath, "native", "include", "material", "unlit_fixed_size.c"),
path.join(pkgRootFilePath, "native", "include", "material", "image.c"),
path.join(pkgRootFilePath, "native", "include", "material", "grid.c"),
path.join(pkgRootFilePath, "native", "include", "material", "unlit.c"),
]);
var libs = [
@@ -91,9 +95,9 @@ void main(List<String> args) async {
];
if (platform == "windows") {
libDir = Directory(libDir).uri.toFilePath();
libs = libs.map((lib) => "${libDir}${lib}.lib").toList();
libs.addAll(["${libDir}bluevk.lib", "${libDir}bluegl.lib"]);
libDir = Directory(libDir).uri.toFilePath(windows: config.targetOS == OS.windows);
libs = libs.map((lib) => path.join(libDir, "${lib}.lib")).toList();
libs.addAll([path.join(libDir,"bluevk.lib"), path.join(libDir,"bluegl.lib")]);
libs.addAll([
"gdi32.lib",
"user32.lib",
@@ -172,8 +176,8 @@ void main(List<String> args) async {
if (platform != "windows") ...libs.map((lib) => "-l$lib"),
if (platform != "windows") "-L$libDir",
if (platform == "windows") ...[
"/I${config.packageRoot.toFilePath()}\\native\\include",
"/I${config.packageRoot.toFilePath()}native\\include\\filament",
"/I${path.join(pkgRootFilePath, "native", "include")}",
"/I${path.join(pkgRootFilePath, "native", "include", "filament")}",
...sources,
'/link',
"/LIBPATH:$libDir",
@@ -232,8 +236,7 @@ void main(List<String> args) async {
name: "thermion_dart.dll",
linkMode: DynamicLoadingBundled(),
os: config.targetOS,
file: Uri.file(
config.outputDirectory.toFilePath() + "/thermion_dart.dll"),
file: Uri.file(path.join(pkgRootFilePath, "thermion_dart.dll")),
architecture: config.targetArchitecture),
linkInPackage: config.packageName);
}
@@ -263,9 +266,9 @@ Future<Directory> getLibDir(BuildConfig config, Logger logger) async {
if (platform == "windows") {
mode = config.buildMode == BuildMode.debug ? "debug" : "release";
}
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") {
final archExtension = switch (config.targetArchitecture) {
@@ -275,7 +278,7 @@ Future<Directory> getLibDir(BuildConfig config, Logger logger) async {
Architecture.ia32 => "x86",
_ => throw FormatException('Invalid')
};
libDir = Directory("${libDir.path}/$archExtension/");
libDir = Directory(path.join(libDir.path, archExtension));
} else if (platform == "windows") {
if (config.targetArchitecture != Architecture.x64) {
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.
// If this file already exists, we assume everything has been successfully extracted and skip
final unzipDir = platform == "android" ? libDir.parent.path : libDir.path;
final successToken = File("$unzipDir/success");
final libraryZip = File("$unzipDir/$filename");
final successToken = File(path.join(unzipDir, "success"));
final libraryZip = File(path.join(unzipDir, filename));
if (!successToken.existsSync()) {
if (libraryZip.existsSync()) {

View File

@@ -82,6 +82,7 @@ class DelegateInputHandler implements InputHandler {
{PickDelegate? pickDelegate,
bool freeLook = false,
double panSensitivity = 0.1,
double zoomSensitivity = 0.1,
double movementSensitivity = 0.1,
double rotateSensitivity = 0.01,
double? clampY,
@@ -93,6 +94,7 @@ class DelegateInputHandler implements InputHandler {
clampY: clampY,
entity: entity,
rotationSensitivity: rotateSensitivity,
zoomSensitivity:zoomSensitivity,
panSensitivity: panSensitivity,
movementSensitivity: movementSensitivity),
actions: {
@@ -260,10 +262,10 @@ class DelegateInputHandler implements InputHandler {
}
@override
Future<void> onScaleEnd(int pointerCount) async {}
Future<void> onScaleEnd(int pointerCount, double velocity) async {}
@override
Future<void> onScaleStart(Vector2 localPosition, int pointerCount) async {
Future<void> onScaleStart(Vector2 localPosition, int pointerCount, Duration? sourceTimestamp ) async {
// noop
}
@@ -276,7 +278,9 @@ class DelegateInputHandler implements InputHandler {
double horizontalScale,
double verticalScale,
double scale,
int pointerCount) async {
int pointerCount,
double rotation,
Duration? sourceTimestamp) async {
if (pointerCount == 1) {
_inputDeltas[InputType.SCALE1] =
Vector3(focalPointDelta.x, focalPointDelta.y, 0);

View File

@@ -14,6 +14,9 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
late Future<Camera> _camera;
final double minimumDistance;
late final Vector3 target;
final double rotationSensitivity;
final double zoomSensitivity;
Vector2 _queuedRotationDelta = Vector2.zero();
double _queuedZoomDelta = 0.0;
@@ -24,6 +27,8 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
this.viewer, {
Vector3? target,
this.minimumDistance = 10.0,
this.rotationSensitivity = 0.01,
this.zoomSensitivity = 0.1,
}) {
this.target = target ?? Vector3.zero();
_camera = viewer.getMainCamera().then((Camera cam) async {
@@ -95,7 +100,7 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
// Zoom
if (_queuedZoomDelta != 0.0) {
var newPosition = currentPosition +
(currentPosition - target).scaled(_queuedZoomDelta * 0.1);
(currentPosition - target).scaled(_queuedZoomDelta * zoomSensitivity);
var distToTarget = (newPosition - target).length;
@@ -113,8 +118,8 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
await (await _camera).setModelMatrix(newViewMatrix);
}
} else if (_queuedRotationDelta.length != 0) {
double rotateX = _queuedRotationDelta.x * 0.01;
double rotateY = _queuedRotationDelta.y * 0.01;
double rotateX = _queuedRotationDelta.x * rotationSensitivity;
double rotateY = _queuedRotationDelta.y * rotationSensitivity;
var modelMatrix = await viewer.getCameraModelMatrix();
@@ -126,9 +131,8 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
var rot2 = Matrix4.identity()
..setRotation(Quaternion.axisAngle(modelMatrix.right, rotateY)
.asRotationMatrix());
modelMatrix = rot1 *
rot2 * modelMatrix;
modelMatrix = rot1 * rot2 * modelMatrix;
await (await _camera).setModelMatrix(modelMatrix);
}

View File

@@ -13,7 +13,9 @@ enum InputType {
MMB_UP,
MMB_HOVER,
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,
POINTER_MOVE,
KEYDOWN_W,
@@ -35,9 +37,9 @@ abstract class InputHandler {
Future<void> onPointerMove(
Vector2 localPosition, Vector2 delta, bool isMiddle);
Future<void> onPointerUp(bool isMiddle);
Future<void> onScaleStart(Vector2 focalPoint, int pointerCount);
Future<void> onScaleUpdate(Vector2 focalPoint, Vector2 focalPointDelta, double horizontalScale, double verticalScale, double scale, int pointerCount);
Future<void> onScaleEnd(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, double rotation, Duration? sourceTimestamp);
Future<void> onScaleEnd(int pointerCount, double velocity);
Future<bool> get initialized;
Future dispose();

View File

@@ -29,7 +29,7 @@ class FFIGizmo extends BaseGizmo {
}
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));
}
///

View File

@@ -150,8 +150,15 @@ external void Viewer_setViewRenderable(
ffi.Int,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(EntityId entityId, ffi.Int x, ffi.Int y,
ffi.Pointer<TView> tView)>>)>(isLeaf: true)
ffi.Void Function(
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(
ffi.Pointer<TViewer> viewer,
ffi.Pointer<TView> tView,
@@ -159,11 +166,24 @@ external void Viewer_pick(
int y,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(EntityId entityId, ffi.Int x, ffi.Int y,
ffi.Pointer<TView> tView)>>
ffi.Void Function(
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,
);
@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)
external ffi.Pointer<TEngine> Viewer_getEngine(
ffi.Pointer<TViewer> viewer,
@@ -418,23 +438,6 @@ external ffi.Pointer<TMaterialInstance> create_material_instance(
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.Void Function(ffi.Pointer<TSceneManager>,
ffi.Pointer<TMaterialInstance>)>(isLeaf: true)
@@ -618,6 +621,60 @@ external int get_bone(
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.Bool Function(ffi.Pointer<TSceneManager>, EntityId,
ffi.Pointer<ffi.Double>)>(isLeaf: true)
@@ -956,35 +1013,6 @@ external void remove_animation_component(
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)>(
isLeaf: true)
external int get_parent(
@@ -1195,6 +1223,15 @@ external void MaterialInstance_setParameterFloat2(
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)
external TViewport View_getViewport(
ffi.Pointer<TView> view,
@@ -1527,6 +1564,38 @@ external void remove_skybox_render_thread(
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.Void Function(
ffi.Pointer<TSceneManager>,
@@ -1551,6 +1620,34 @@ external void SceneManager_loadGlbFromBufferRenderThread(
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.Void Function(
ffi.Pointer<TSceneManager>,
@@ -1751,38 +1848,6 @@ external void reset_to_rest_pose_render_thread(
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.Void Function(
ffi.Pointer<TViewer>,
@@ -2003,15 +2068,6 @@ void Camera_setProjection(
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.Void Function(ffi.Pointer<TGizmo>, ffi.Uint32, ffi.Uint32,
GizmoPickCallback)>(isLeaf: true)

View File

@@ -84,7 +84,7 @@ class ThermionViewerFFI extends ThermionViewer {
_onPickResultCallable = NativeCallable<
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();
}
@@ -1509,26 +1509,26 @@ class ThermionViewerFFI extends ThermionViewer {
}
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 viewport = await view.getViewport();
_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<
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;
///
///
///
@override
void pick(int x, int y) async {
Future pick(int x, int y) async {
final view = (await getViewAt(0)) as FFIView;
var viewport = await view.getViewport();
y = (viewport.height - y).ceil();
y = viewport.height - y;
Viewer_pick(
_viewer!, view.view, x, y, _onPickResultCallable.nativeFunction);
}
@@ -2035,6 +2035,9 @@ class ThermionViewerFFI extends ThermionViewer {
destroy_material_instance(_sceneManager!, materialInstance._pointer);
}
///
///
///
Future<ThermionFFIMaterialInstance> createUnlitMaterialInstance() async {
var instance = await withPointerCallback<TMaterialInstance>((cb) {
SceneManager_createUnlitMaterialInstanceRenderThread(_sceneManager!, cb);
@@ -2045,6 +2048,19 @@ class ThermionViewerFFI extends ThermionViewer {
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
Future setMaterialPropertyInt(ThermionEntity entity, String propertyName,
int materialIndex, int value) {
@@ -2163,7 +2179,7 @@ class ThermionViewerFFI extends ThermionViewer {
Future<Gizmo> createGizmo(FFIView view) async {
var view = (await getViewAt(0)) as FFIView;
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);
}
}
@@ -2194,6 +2210,12 @@ class ThermionFFIMaterialInstance extends MaterialInstance {
MaterialInstance_setParameterFloat2(
_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 {

View File

@@ -2,6 +2,7 @@ abstract class MaterialInstance {
Future setDepthWriteEnabled(bool enabled);
Future setDepthCullingEnabled(bool enabled);
Future setParameterFloat2(String name, double x, double y);
Future setParameterFloat(String name, double x);
}
enum AlphaMode { OPAQUE, MASK, BLEND }

View File

@@ -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';
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;

View File

@@ -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.
/// [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).
@@ -796,14 +796,23 @@ abstract class ThermionViewer {
Future<Aabb2> getViewportBoundingBox(ThermionEntity entity);
///
/// Filament assigns renderables to a numeric 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.
/// Toggles the visibility of the respective layer.
///
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);
@@ -886,6 +895,11 @@ abstract class ThermionViewer {
///
Future<MaterialInstance> createUnlitMaterialInstance();
///
///
///
Future<MaterialInstance> createUnlitFixedSizeMaterialInstance();
///
///
///

View File

@@ -21,4 +21,10 @@ class ThermionWasmMaterialInstance extends MaterialInstance {
// TODO: implement setParameterFloat2
throw UnimplementedError();
}
@override
Future setParameterFloat(String name, double x) {
// TODO: implement setParameterFloat
throw UnimplementedError();
}
}

View File

View File

@@ -98,7 +98,15 @@ namespace thermion
void clearBackgroundImage();
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() {
return _engine;
}

View File

@@ -17,8 +17,6 @@
#include <filament/IndexBuffer.h>
#include <filament/InstanceBuffer.h>
#include "material/gizmo.h"
#include "ThermionDartApi.h"
namespace thermion {
@@ -31,7 +29,7 @@ class Gizmo {
enum Axis { X, Y, Z};
public:
Gizmo(Engine *engine, View *view, Scene *scene);
Gizmo(Engine *engine, View *view, Scene *scene, Material* material);
~Gizmo();
typedef void (*PickCallback)(EntityId entityId, uint32_t x, uint32_t y, View *view);
@@ -91,8 +89,10 @@ class Gizmo {
Engine *_engine;
Scene *_scene;
View *_view;
utils::Entity _entities[7] = { utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity() };
Material* _material;
utils::Entity _entities[7] = { utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity() };
MaterialInstance* _materialInstances[7];
math::float4 inactiveColors[3] {
math::float4 { 1.0f, 0.0f, 0.0f, 0.5f },

View File

@@ -19,9 +19,6 @@
#include <filament/IndexBuffer.h>
#include <filament/InstanceBuffer.h>
#include "material/gizmo.h"
namespace thermion {
using namespace filament;

View File

@@ -19,16 +19,17 @@
#include <filament/InstanceBuffer.h>
#include <utils/NameComponentManager.h>
#include "CustomGeometry.hpp"
#include "tsl/robin_map.h"
#include "APIBoundaryTypes.h"
#include "CustomGeometry.hpp"
#include "Gizmo.hpp"
#include "GridOverlay.hpp"
#include "ResourceBuffer.hpp"
#include "components/CollisionComponentManager.hpp"
#include "components/AnimationComponentManager.hpp"
#include "tsl/robin_map.h"
namespace thermion
{
@@ -287,6 +288,8 @@ namespace thermion
return _ubershaderProvider;
}
MaterialInstance* createUnlitFixedSizeMaterialInstance();
MaterialInstance* createUnlitMaterialInstance();
void setVisibilityLayer(EntityId entityId, int layer);
@@ -298,6 +301,8 @@ namespace thermion
size_t getCameraCount();
Camera* getCameraAt(size_t index);
Gizmo *createGizmo(View *view, Scene *scene);
bool isGizmoEntity(utils::Entity entity);
@@ -321,6 +326,8 @@ namespace thermion
std::mutex _stencilMutex;
std::vector<MaterialInstance*> _materialInstances;
Material* _gizmoMaterial = nullptr;
utils::NameComponentManager *_ncm;
tsl::robin_map<

View File

@@ -10,7 +10,6 @@ extern "C"
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_setVisibility(TGizmo *tGizmo, bool visible);

View File

@@ -85,7 +85,8 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void Viewer_setMainCamera(TViewer *tViewer, TView *tView);
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_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
EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer* viewer);
@@ -197,6 +198,7 @@ extern "C"
int skinIndex,
int boneIndex);
EMSCRIPTEN_KEEPALIVE TGizmo* SceneManager_createGizmo(TSceneManager *tSceneManager, TView *tView, TScene *tScene);
EMSCRIPTEN_KEEPALIVE EntityId SceneManager_createGeometry(
TSceneManager *sceneManager,
float *vertices,
@@ -211,6 +213,7 @@ extern "C"
TMaterialInstance *materialInstance,
bool keepData);
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 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);
@@ -294,6 +297,7 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthWrite(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_setParameterFloat(TMaterialInstance* materialInstance, const char* name, double value);
#ifdef __cplusplus

View File

@@ -67,6 +67,7 @@ extern "C"
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_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_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));

View File

@@ -11,8 +11,6 @@
#pragma comment(lib, "bluevk.lib")
#pragma comment(lib, "bluegl.lib")
#pragma comment(lib, "backend.lib")
#pragma comment(lib, "filameshio.lib")
#pragma comment(lib, "viewer.lib")
#pragma comment(lib, "filamat.lib")
#pragma comment(lib, "geometry.lib")
#pragma comment(lib, "utils.lib")

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1191,23 +1191,16 @@ namespace thermion
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) {
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);
} });
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);
});
}
void FilamentViewer::unprojectTexture(EntityId entityId, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight)

View File

@@ -7,31 +7,26 @@
#include <filament/TransformManager.h>
#include <gltfio/math.h>
#include "SceneManager.hpp"
#include "material/gizmo.h"
#include "material/unlit_fixed_size.h"
#include "Log.hpp"
namespace thermion {
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 &transformManager = _engine->getTransformManager();
_material =
Material::Builder()
.package(GIZMO_GIZMO_DATA, GIZMO_GIZMO_SIZE)
.build(*_engine);
// First, create the black cube at the center
// The axes widgets will be parented to this entity
_entities[3] = entityManager.create();
_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
float centerCubeSize = 0.01f;
@@ -160,7 +155,7 @@ Gizmo::Gizmo(Engine *engine, View *view, Scene* scene) : _engine(engine), _view(
break;
}
_materialInstances[i]->setParameter("color", baseColor);
_materialInstances[i]->setParameter("baseColorFactor", baseColor);
RenderableManager::Builder(1)
.boundingBox({{-arrowWidth, -arrowWidth, 0},

View File

@@ -33,9 +33,12 @@
#include "CustomGeometry.hpp"
#include "UnprojectTexture.hpp"
#include "Gizmo.hpp"
extern "C"
{
#include "material/image.h"
#include "material/unlit_fixed_size.h"
}
namespace thermion
@@ -52,9 +55,8 @@ namespace thermion
Engine *engine,
Scene *scene,
const char *uberArchivePath,
Camera *mainCamera)
:
_resourceLoaderWrapper(resourceLoaderWrapper),
Camera *mainCamera)
: _resourceLoaderWrapper(resourceLoaderWrapper),
_engine(engine),
_scene(scene),
_mainCamera(mainCamera)
@@ -103,17 +105,22 @@ namespace thermion
_scene->addEntity(_gridOverlay->sphere());
_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()
{
for(auto camera : _cameras) {
for (auto camera : _cameras)
{
auto entity = camera->getEntity();
_engine->destroyCameraComponent(entity);
_engine->getEntityManager().destroy(entity);
}
_cameras.clear();
_gridOverlay->destroy();
destroyAll();
@@ -131,8 +138,14 @@ namespace thermion
AssetLoader::destroy(&_assetLoader);
}
bool SceneManager::isGizmoEntity(Entity entity) {
return false; // TODO
Gizmo *SceneManager::createGizmo(View *view, Scene *scene)
{
return new Gizmo(_engine, view, scene, _gizmoMaterial);
}
bool SceneManager::isGizmoEntity(Entity entity)
{
return false; // TODO
}
int SceneManager::getInstanceCount(EntityId entityId)
@@ -246,15 +259,16 @@ namespace thermion
return eid;
}
void SceneManager::setVisibilityLayer(EntityId entityId, int layer) {
auto& rm = _engine->getRenderableManager();
void SceneManager::setVisibilityLayer(EntityId entityId, int layer)
{
auto &rm = _engine->getRenderableManager();
auto renderable = rm.getInstance(utils::Entity::import(entityId));
if(!renderable.isValid()) {
if (!renderable.isValid())
{
Log("Warning: no renderable found");
}
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)
@@ -281,11 +295,13 @@ namespace thermion
_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]);
if(!instance.isValid()) {
if (!instance.isValid())
{
Log("No valid renderable for entity");
continue;
}
@@ -304,13 +320,16 @@ namespace thermion
_gltfResourceLoader->asyncUpdateLoad();
}
#else
if(loadResourcesAsync) {
if (loadResourcesAsync)
{
if (!_gltfResourceLoader->asyncBeginLoad(asset))
{
Log("Unknown error loading glb asset");
return 0;
}
} else {
}
else
{
if (!_gltfResourceLoader->loadResources(asset))
{
Log("Unknown error loading glb asset");
@@ -539,11 +558,13 @@ namespace thermion
asset.second->getLightEntityCount());
_assetLoader->destroyAsset(asset.second);
}
for(auto *texture : _textures) {
for (auto *texture : _textures)
{
_engine->destroy(texture);
}
for(auto *materialInstance : _materialInstances) {
for (auto *materialInstance : _materialInstances)
{
_engine->destroy(materialInstance);
}
@@ -661,7 +682,6 @@ namespace thermion
auto entity = Entity::import(entityId);
if (_animationComponentManager->hasComponent(entity))
{
_animationComponentManager->removeComponent(entity);
@@ -674,7 +694,8 @@ namespace thermion
_scene->remove(entity);
if(isGeometryEntity(entityId)) {
if (isGeometryEntity(entityId))
{
return;
}
@@ -1412,7 +1433,7 @@ namespace thermion
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);
@@ -1446,10 +1467,12 @@ namespace thermion
return true;
}
void SceneManager::destroyTexture(Texture* texture) {
if(_textures.find(texture) == _textures.end()) {
void SceneManager::destroyTexture(Texture *texture)
{
if (_textures.find(texture) == _textures.end())
{
Log("Warning: couldn't find texture");
}
}
_textures.erase(texture);
_engine->destroy(texture);
}
@@ -1904,7 +1927,7 @@ namespace thermion
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
const auto &camera = view->getCamera();
@@ -1941,14 +1964,14 @@ namespace thermion
auto entityPlaneInWorldSpace = camera.getModelMatrix() * entityPlaneInCameraSpace;
// 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);
for(int i= 0; i < numEntities; i++) {
for (int i = 0; i < numEntities; i++)
{
auto entity = entities[i];
const auto &pos = _transformUpdates.find(entity);
if (pos == _transformUpdates.end())
@@ -2279,112 +2302,117 @@ namespace thermion
}
}
EntityId SceneManager::createGeometry(
float *vertices,
uint32_t numVertices,
float *normals,
uint32_t numNormals,
float *uvs,
uint32_t numUvs,
uint16_t *indices,
uint32_t numIndices,
filament::RenderableManager::PrimitiveType primitiveType,
filament::MaterialInstance* materialInstance,
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)
EntityId SceneManager::createGeometry(
float *vertices,
uint32_t numVertices,
float *normals,
uint32_t numNormals,
float *uvs,
uint32_t numUvs,
uint16_t *indices,
uint32_t numIndices,
filament::RenderableManager::PrimitiveType primitiveType,
filament::MaterialInstance *materialInstance,
bool keepData)
{
// 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);
auto geometry = std::make_unique<CustomGeometry>(vertices, numVertices, normals, numNormals, uvs, numUvs, indices, numIndices, primitiveType, _engine);
_textures.insert(texture);
filament::backend::PixelBufferDescriptor pbd(&white, 4, Texture::Format::RGBA, Texture::Type::UBYTE);
texture->setImage(*_engine, 0, std::move(pbd));
auto entity = utils::EntityManager::get().create();
RenderableManager::Builder builder(1);
// Create a sampler
TextureSampler sampler(TextureSampler::MinFilter::NEAREST, TextureSampler::MagFilter::NEAREST);
sampler.setWrapModeS(TextureSampler::WrapMode::REPEAT);
sampler.setWrapModeT(TextureSampler::WrapMode::REPEAT);
builder.boundingBox(geometry->getBoundingBox())
.geometry(0, primitiveType, geometry->vertexBuffer(), geometry->indexBuffer(), 0, numIndices)
.culling(true)
.receiveShadows(true)
.castShadows(true);
// Set the texture and sampler to the material instance
materialInstance->setParameter("baseColorMap", texture, sampler);
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)
{
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);
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) {
MaterialInstance *SceneManager::getMaterialInstanceAt(EntityId entityId, int materialIndex)
{
auto entity = Entity::import(entityId);
const auto &rm = _engine->getRenderableManager();
auto renderableInstance = rm.getInstance(entity);
@@ -2436,7 +2464,7 @@ EntityId SceneManager::createGeometry(
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);
const auto &rm = _engine->getRenderableManager();
@@ -2453,17 +2481,20 @@ EntityId SceneManager::createGeometry(
Log("Parameter %s not found", property);
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);
}
MaterialInstance* SceneManager::createUbershaderMaterialInstance(filament::gltfio::MaterialKey config) {
filament::gltfio::UvMap uvmap {};
auto * materialInstance = _ubershaderProvider->createMaterialInstance(&config, &uvmap);
if(!materialInstance) {
MaterialInstance *SceneManager::createUbershaderMaterialInstance(filament::gltfio::MaterialKey config)
{
filament::gltfio::UvMap uvmap{};
auto *materialInstance = _ubershaderProvider->createMaterialInstance(&config, &uvmap);
if (!materialInstance)
{
Log("Invalid material configuration");
return nullptr;
}
@@ -2473,44 +2504,58 @@ EntityId SceneManager::createGeometry(
return materialInstance;
}
MaterialInstance* SceneManager::createUnlitMaterialInstance() {
MaterialInstance *SceneManager::createUnlitFixedSizeMaterialInstance()
{
auto instance = _gizmoMaterial->createInstance();
instance->setParameter("scale", 1.0f);
return instance;
}
MaterialInstance *SceneManager::createUnlitMaterialInstance()
{
UvMap 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);
return instance;
}
Camera* SceneManager::createCamera() {
Camera *SceneManager::createCamera()
{
auto entity = EntityManager::get().create();
auto camera = _engine->createCamera(entity);
_cameras.push_back(camera);
return camera;
}
void SceneManager::destroyCamera(Camera* camera) {
void SceneManager::destroyCamera(Camera *camera)
{
auto entity = camera->getEntity();
_engine->destroyCameraComponent(entity);
_engine->getEntityManager().destroy(entity);
auto it = std::find(_cameras.begin(), _cameras.end(), camera);
if(it != _cameras.end()) {
if (it != _cameras.end())
{
_cameras.erase(it);
}
}
size_t SceneManager::getCameraCount() {
size_t SceneManager::getCameraCount()
{
return _cameras.size() + 1;
}
Camera* SceneManager::getCameraAt(size_t index) {
if(index == 0) {
Camera *SceneManager::getCameraAt(size_t index)
{
if (index == 0)
{
return _mainCamera;
}
if(index - 1 > _cameras.size() - 1) {
if (index - 1 > _cameras.size() - 1)
{
return nullptr;
}
return _cameras[index-1];
return _cameras[index - 1];
}
} // namespace thermion

View File

@@ -14,15 +14,6 @@ extern "C"
using namespace filament;
#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)
{
auto *gizmo = reinterpret_cast<Gizmo*>(tGizmo);

View File

@@ -49,11 +49,16 @@ extern "C"
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 *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)
@@ -168,9 +173,17 @@ extern "C"
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)
{
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)
@@ -1021,6 +1034,12 @@ extern "C"
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)
{
((SceneManager *)sceneManager)->destroy(reinterpret_cast<MaterialInstance *>(instance));
@@ -1042,6 +1061,10 @@ extern "C"
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)
{

View File

@@ -371,6 +371,16 @@ extern "C"
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,
const uint8_t *const data,
size_t length,

View File

@@ -62,7 +62,7 @@ add_executable(${MODULE_NAME}
"${CMAKE_CURRENT_SOURCE_DIR}/../src/camutils/Manipulator.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../src/camutils/Bookmark.cpp"
"${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"
)
set_target_properties(${MODULE_NAME} PROPERTIES

View File

@@ -1,6 +1,6 @@
name: thermion_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
repository: https://github.com/nmfisher/thermion
@@ -18,6 +18,7 @@ dependencies:
web: ^1.0.0
logging: ^1.2.0
http: ^1.2.2
path: ^1.9.0
dev_dependencies:
ffigen: ^13.0.0

View File

@@ -1,10 +1,6 @@
import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
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:vector_math/vector_math_64.dart';
import 'helpers.dart';

View File

@@ -1,3 +1,7 @@
// ignore_for_file: unused_local_variable
import 'dart:math';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:test/test.dart';
import 'package:vector_math/vector_math_64.dart';
@@ -7,7 +11,6 @@ void main() async {
final testHelper = TestHelper("integration");
group('camera', () {
test('getCameraModelMatrix, getCameraPosition, rotation', () async {
var viewer = await testHelper.createViewer();
var matrix = await viewer.getCameraModelMatrix();
@@ -24,7 +27,7 @@ void main() async {
expect(position.x, 2.0);
expect(position.y, 2.0);
expect(position.z, 2.0);
await viewer.dispose();
});
@@ -50,7 +53,6 @@ void main() async {
expect(position.y, closeTo(4.0, 1e-6));
expect(position.z, closeTo(5.0, 1e-6));
await viewer.dispose();
});
test('getCameraProjectionMatrix', () async {
@@ -62,11 +64,11 @@ void main() async {
test('getCameraCullingProjectionMatrix', () async {
throw Exception("TODO");
// ignore: dead_code
var viewer = await testHelper.createViewer();
var matrix = await viewer.getCameraCullingProjectionMatrix();
print(matrix);
await viewer.dispose();
});
test('getCameraFrustum', () async {
@@ -92,24 +94,48 @@ void main() async {
var camera = await viewer.getMainCamera();
await viewer.createGeometry(GeometryHelper.cube());
await camera.setProjection(Projection.Orthographic, -0.05, 0.05, -0.05, 0.05, 0.05, 10000);
await testHelper.capture(
viewer, "camera_set_orthographic_projection");
await camera.setProjection(
Projection.Orthographic, -0.05, 0.05, -0.05, 0.05, 0.05, 10000);
await testHelper.capture(viewer, "camera_set_orthographic_projection");
await viewer.dispose();
});
test('set custom projection/culling matrix', () async {
test('set perspective projection/culling matrix', () 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());
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
var projectionMatrix =
makeOrthographicMatrix(-10.0, 10.0, -10.0, 10.0, 0.05, 10000);
await camera.setProjectionMatrixWithCulling(
projectionMatrix, 0.05, 10000);
await testHelper.capture(
viewer, "camera_projection_culling_matrix_object_in_frustum");
@@ -119,7 +145,7 @@ void main() async {
await camera.setProjectionMatrixWithCulling(projectionMatrix, 0.05, 1);
await testHelper.capture(
viewer, "camera_projection_culling_matrix_object_outside_frustum");
await viewer.dispose();
});

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);
});
});
}

View File

@@ -1,3 +1,5 @@
// ignore_for_file: unused_local_variable
import 'dart:io';
import 'dart:math';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';

View File

@@ -1,3 +1,5 @@
// ignore_for_file: unused_local_variable
import 'package:test/test.dart';
import 'helpers.dart';

View File

@@ -1,3 +1,5 @@
// ignore_for_file: unused_local_variable
import 'dart:io';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:test/test.dart';

View File

@@ -1,3 +1,5 @@
// ignore_for_file: unused_local_variable
import 'dart:ffi';
import 'dart:io';
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_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:vector_math/vector_math_64.dart';
import 'package:path/path.dart' as p;
@@ -72,28 +73,31 @@ class TestHelper {
TestHelper(String dir) {
final packageUri = findPackageRoot('thermion_dart');
print("Package URIL $packageUri");
testDir = Directory("${packageUri.toFilePath()}/test").path;
print("Test dir : $packageUri");
outDir = Directory("$testDir/output/${dir}");
print("Out dir : $packageUri");
// outDir.deleteSync(recursive: true);
outDir.createSync(recursive: true);
if(Platform.isMacOS) {
print("Created out dir : $packageUri");
if (Platform.isMacOS) {
DynamicLibrary.open('${testDir}/libThermionTextureSwift.dylib');
}
}
Future capture(ThermionViewer viewer, String outputFilename,
{View? view, SwapChain? swapChain, RenderTarget? renderTarget}) async {
await Future.delayed(Duration(milliseconds: 10));
var outPath = p.join(outDir.path, "$outputFilename.bmp");
var pixelBuffer = await viewer.capture(
view: view,
swapChain: swapChain ?? this.swapChain,
renderTarget: renderTarget);
await viewer.render();
view ??= await viewer.getViewAt(0);
var vp = await view.getViewport();
await savePixelBufferToBmp(pixelBuffer, vp.width, vp.height, outPath);
@@ -101,9 +105,6 @@ class TestHelper {
}
Future<ThermionTextureSwift> createTexture(int width, int height) async {
final packageUri = findPackageRoot('thermion_dart');
var testDir = Directory("${packageUri.toFilePath()}/test").path;
final object = ThermionTextureSwift.new1();
object.initWithWidth_height_(width, height);
return object;
@@ -114,24 +115,29 @@ class TestHelper {
Vector3? cameraPosition,
viewportDimensions = (width: 500, height: 500)}) async {
final resourceLoader = calloc<ResourceLoaderWrapper>(1);
print("resourceLoader");
var loadToOut = NativeCallable<
Void Function(Pointer<Char>,
Pointer<ResourceBuffer>)>.listener(DartResourceLoader.loadResource);
print("loadToOut");
resourceLoader.ref.loadToOut = loadToOut.nativeFunction;
print("set ref");
var freeResource = NativeCallable<Void Function(ResourceBuffer)>.listener(
DartResourceLoader.freeResource);
print("freeResource");
resourceLoader.ref.freeResource = freeResource.nativeFunction;
print("set freeResource ref");
var viewer = ThermionViewerFFI(resourceLoader: resourceLoader.cast<Void>());
print("created viewer");
await viewer.initialized;
swapChain = await viewer.createHeadlessSwapChain(
viewportDimensions.width, viewportDimensions.height);
print("created headless swapchain");
await viewer.updateViewportAndCameraProjection(
viewportDimensions.width.toDouble(),
viewportDimensions.height.toDouble());
print("updated camera");
if (bg != null) {
await viewer.setBackgroundColor(
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,
{bool linearToSrgb = false}) async {
{bool linearToSrgb = false, bool invertAces = false}) async {
final image = img.Image(width: width, height: height);
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];
// Apply inverse ACES tone mapping
bool invertAces = false;
if (invertAces) {
r = _inverseACESToneMapping(r);
g = _inverseACESToneMapping(g);

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)));
// });
}

View File

@@ -31,6 +31,29 @@ void main() async {
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 {
var viewer = await testHelper.createViewer();
await viewer.addLight(LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);

View File

@@ -1,4 +1,3 @@
import 'dart:async';
import 'package:test/test.dart';
import 'helpers.dart';

View File

@@ -1,3 +1,5 @@
// ignore_for_file: unused_local_variable
import 'dart:async';
import 'package:test/test.dart';
@@ -15,7 +17,6 @@ void main() async {
expect(await view.getCamera(), isNotNull);
await viewer.dispose();
});
test('one swapchain, render view to render target', () async {
@@ -37,7 +38,6 @@ void main() async {
"default_swapchain_default_view_render_target");
await viewer.dispose();
});
test('create secondary view, default swapchain', () async {
@@ -113,22 +113,29 @@ void main() async {
test('pick', () async {
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());
await testHelper.capture(viewer, "view_pick");
final completer = Completer();
late StreamSubscription listener;
listener = viewer.pickResult.listen((result) async {
completer.complete(result.entity);
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++) {
await viewer.requestFrame();
await Future.delayed(Duration(milliseconds: 100));
for (int i = 0; i < 3; i++) {
await viewer.render();
await Future.delayed(Duration(milliseconds: 16));
}
expect(completer.isCompleted, true);

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);
});
});
}

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);
}

View File

@@ -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

View File

@@ -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
> Note: This release has breaking changes.

View File

@@ -3,7 +3,7 @@
<p align="center">
<a href="https://thermion.dev/quickstart">Quickstart (Flutter)</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://discord.gg/h2VdDK3EAQ">Discord</a>
</p>

View File

@@ -165,19 +165,21 @@ class _MobileListenerWidgetState extends State<_MobileListenerWidget> {
},
onScaleStart: (details) async {
await widget.inputHandler.onScaleStart(
details.localFocalPoint.toVector2(), details.pointerCount);
details.localFocalPoint.toVector2() * widget.pixelRatio, details.pointerCount, details.sourceTimeStamp);
},
onScaleUpdate: (ScaleUpdateDetails details) async {
await widget.inputHandler.onScaleUpdate(
details.localFocalPoint.toVector2(),
details.focalPointDelta.toVector2(),
details.localFocalPoint.toVector2() * widget.pixelRatio,
details.focalPointDelta.toVector2() * widget.pixelRatio,
details.horizontalScale,
details.verticalScale,
details.scale,
details.pointerCount);
details.pointerCount,
details.rotation,
details.sourceTimeStamp);
},
onScaleEnd: (details) async {
await widget.inputHandler.onScaleEnd(details.pointerCount);
await widget.inputHandler.onScaleEnd(details.pointerCount, details.scaleVelocity);
},
child: widget.child);
}

View File

@@ -68,12 +68,22 @@ class _ThermionTextureWidgetState extends State<ThermionTextureWidget> {
var dpr = MediaQuery.of(context).devicePixelRatio;
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 height = (size.height * dpr).ceil();
_logger.info(
"Target texture dimensions ${width}x${height} (pixel ratio : $dpr)");
_texture = await ThermionFlutterPlatform.instance
.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);
try {
@@ -177,6 +187,9 @@ class _ThermionTextureWidgetState extends State<ThermionTextureWidget> {
var newWidth = newSize.width.ceil();
var newHeight = newSize.height.ceil();
_logger.info(
"Resizing texture to dimensions ${newWidth}x${newHeight} (pixel ratio : $dpr)");
await _texture?.resize(
newWidth,
newHeight,
@@ -184,6 +197,9 @@ class _ThermionTextureWidgetState extends State<ThermionTextureWidget> {
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.onResize?.call(

View File

@@ -1,6 +1,6 @@
name: thermion_flutter
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
repository: https://github.com/nmfisher/thermion
@@ -17,10 +17,10 @@ dependencies:
plugin_platform_interface: ^2.0.0
ffi: ^2.1.2
animation_tools_dart: ^0.1.0
thermion_dart: ^0.2.1-dev.0.0.10
thermion_flutter_platform_interface: ^0.2.1-dev.9
thermion_flutter_ffi: ^0.2.1-dev.9
thermion_flutter_web: ^0.2.0
thermion_dart: ^0.2.1-dev.0.0.16
thermion_flutter_platform_interface: ^0.2.1-dev.16
thermion_flutter_ffi: ^0.2.1-dev.16
thermion_flutter_web: ^0.2.0+7
logging: ^1.2.0
web: ^1.0.0

View File

@@ -33,7 +33,6 @@ add_library(${PLUGIN_NAME} SHARED
"include/thermion_flutter/thermion_flutter_plugin_c_api.h"
"thermion_flutter_plugin_c_api.cpp"
${PLUGIN_SOURCES}
"include/material/image.c"
)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)

View File

@@ -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

View File

@@ -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

View File

@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5ad7dec6e1c92a6ee102556217cf7d13363fc4cf9f4b8a9e0f16dbb7208b5ee8
size 13622

View File

@@ -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;

View File

@@ -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

View File

@@ -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
> Note: This release has breaking changes.

View File

@@ -1,7 +1,7 @@
name: thermion_flutter_ffi
description: An FFI implementation for thermion_flutter (i.e. all platforms except web).
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
version: 0.2.1-dev.9
version: 0.2.1-dev.16
environment:
sdk: ">=3.3.0 <4.0.0"
@@ -23,8 +23,8 @@ dependencies:
flutter:
sdk: flutter
plugin_platform_interface: ^2.1.0
thermion_flutter_platform_interface: ^0.2.1-dev.9
thermion_dart: ^0.2.1-dev.0.0.10
thermion_flutter_platform_interface: ^0.2.1-dev.16
thermion_dart: ^0.2.1-dev.0.0.16
logging: ^1.2.0
dev_dependencies:

View File

@@ -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
> Note: This release has breaking changes.

View File

@@ -1,7 +1,7 @@
name: thermion_flutter_platform_interface
description: A common platform interface for the thermion_flutter plugin.
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
version: 0.2.1-dev.9
version: 0.2.1-dev.16
environment:
sdk: ">=3.3.0 <4.0.0"
@@ -11,7 +11,7 @@ dependencies:
flutter:
sdk: flutter
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:
flutter_test:

View File

@@ -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
> Note: This release has breaking changes.

View File

@@ -1,7 +1,7 @@
name: thermion_flutter_web
description: A web platform interface for the thermion_flutter plugin.
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
version: 0.2.0
version: 0.2.0+7
environment:
sdk: ">=3.3.0 <4.0.0"
@@ -20,8 +20,8 @@ dependencies:
sdk: flutter
plugin_platform_interface: ^2.1.0
web: ^1.0.0
thermion_dart: ^0.2.1-dev.0.0.10
thermion_flutter_platform_interface: ^0.2.1-dev.9
thermion_dart: ^0.2.1-dev.0.0.16
thermion_flutter_platform_interface: ^0.2.1-dev.16
flutter_web_plugins:
sdk: flutter