瀏覽代碼

上传 Unity 项目文件

“Yuu-Wgit config --global user.email “yuw.nancy@gmail.com 3 月之前
當前提交
526819751f
共有 100 個文件被更改,包括 14913 次插入0 次删除
  1. 二進制
      .DS_Store
  2. 二進制
      Assets/.DS_Store
  3. 8 0
      Assets/ARLocation.meta
  4. 14 0
      Assets/ARLocation/ARLocationConfig.asset
  5. 8 0
      Assets/ARLocation/ARLocationConfig.asset.meta
  6. 273 0
      Assets/ARLocation/CHANGELOG.md
  7. 7 0
      Assets/ARLocation/CHANGELOG.md.meta
  8. 8 0
      Assets/ARLocation/Data.meta
  9. 18 0
      Assets/ARLocation/Data/PrefabDb.asset
  10. 8 0
      Assets/ARLocation/Data/PrefabDb.asset.meta
  11. 1 0
      Assets/ARLocation/Data/data.xml
  12. 7 0
      Assets/ARLocation/Data/data.xml.meta
  13. 8 0
      Assets/ARLocation/Editor.meta
  14. 197 0
      Assets/ARLocation/Editor/ARLocationConfigInspector.cs
  15. 11 0
      Assets/ARLocation/Editor/ARLocationConfigInspector.cs.meta
  16. 38 0
      Assets/ARLocation/Editor/ARLocationEditorConfigManager.cs
  17. 11 0
      Assets/ARLocation/Editor/ARLocationEditorConfigManager.cs.meta
  18. 19 0
      Assets/ARLocation/Editor/ARLocationManagerInspector.cs
  19. 11 0
      Assets/ARLocation/Editor/ARLocationManagerInspector.cs.meta
  20. 19 0
      Assets/ARLocation/Editor/ARLocationOrientationInspector.cs
  21. 11 0
      Assets/ARLocation/Editor/ARLocationOrientationInspector.cs.meta
  22. 19 0
      Assets/ARLocation/Editor/ARLocationProviderInspector.cs
  23. 11 0
      Assets/ARLocation/Editor/ARLocationProviderInspector.cs.meta
  24. 26 0
      Assets/ARLocation/Editor/ConditionalPropertyDrawer.cs
  25. 11 0
      Assets/ARLocation/Editor/ConditionalPropertyDrawer.cs.meta
  26. 42 0
      Assets/ARLocation/Editor/DefineSymbols.cs
  27. 11 0
      Assets/ARLocation/Editor/DefineSymbols.cs.meta
  28. 82 0
      Assets/ARLocation/Editor/DefineSymbolsManager.cs
  29. 11 0
      Assets/ARLocation/Editor/DefineSymbolsManager.cs.meta
  30. 103 0
      Assets/ARLocation/Editor/GameObjectMenuItems.cs
  31. 11 0
      Assets/ARLocation/Editor/GameObjectMenuItems.cs.meta
  32. 224 0
      Assets/ARLocation/Editor/LocationPathInspector.cs
  33. 11 0
      Assets/ARLocation/Editor/LocationPathInspector.cs.meta
  34. 64 0
      Assets/ARLocation/Editor/LocationPropertyDataDrawer.cs
  35. 11 0
      Assets/ARLocation/Editor/LocationPropertyDataDrawer.cs.meta
  36. 67 0
      Assets/ARLocation/Editor/OverrideAltitudeDataDrawer.cs
  37. 11 0
      Assets/ARLocation/Editor/OverrideAltitudeDataDrawer.cs.meta
  38. 8 0
      Assets/ARLocation/Experimental.meta
  39. 78 0
      Assets/ARLocation/Experimental/NewPathLineRenderer.cs
  40. 11 0
      Assets/ARLocation/Experimental/NewPathLineRenderer.cs.meta
  41. 8 0
      Assets/ARLocation/Experimental/World Builder.meta
  42. 3138 0
      Assets/ARLocation/Experimental/World Builder/AR+GPS Location World Builder.unity
  43. 7 0
      Assets/ARLocation/Experimental/World Builder/AR+GPS Location World Builder.unity.meta
  44. 93 0
      Assets/ARLocation/Experimental/World Builder/Cube.prefab
  45. 7 0
      Assets/ARLocation/Experimental/World Builder/Cube.prefab.meta
  46. 94 0
      Assets/ARLocation/Experimental/World Builder/Cylinder.prefab
  47. 7 0
      Assets/ARLocation/Experimental/World Builder/Cylinder.prefab.meta
  48. 24 0
      Assets/ARLocation/Experimental/World Builder/PrefabDb.asset
  49. 8 0
      Assets/ARLocation/Experimental/World Builder/PrefabDb.asset.meta
  50. 73 0
      Assets/ARLocation/Experimental/World Builder/Readme.txt
  51. 7 0
      Assets/ARLocation/Experimental/World Builder/Readme.txt.meta
  52. 200 0
      Assets/ARLocation/Experimental/World Builder/WorldBuilder.cs
  53. 11 0
      Assets/ARLocation/Experimental/World Builder/WorldBuilder.cs.meta
  54. 417 0
      Assets/ARLocation/Experimental/World Builder/WorldBuilderApplicationController.cs
  55. 11 0
      Assets/ARLocation/Experimental/World Builder/WorldBuilderApplicationController.cs.meta
  56. 8 0
      Assets/ARLocation/Experimental/World Voxel Craft.meta
  57. 2278 0
      Assets/ARLocation/Experimental/World Voxel Craft/AR+GPS Location World Voxel.unity
  58. 7 0
      Assets/ARLocation/Experimental/World Voxel Craft/AR+GPS Location World Voxel.unity.meta
  59. 4758 0
      Assets/ARLocation/Experimental/World Voxel Craft/Brick Particle System.prefab
  60. 7 0
      Assets/ARLocation/Experimental/World Voxel Craft/Brick Particle System.prefab.meta
  61. 二進制
      Assets/ARLocation/Experimental/World Voxel Craft/Brick.wav
  62. 22 0
      Assets/ARLocation/Experimental/World Voxel Craft/Brick.wav.meta
  63. 94 0
      Assets/ARLocation/Experimental/World Voxel Craft/Chunk Plane.prefab
  64. 7 0
      Assets/ARLocation/Experimental/World Voxel Craft/Chunk Plane.prefab.meta
  65. 78 0
      Assets/ARLocation/Experimental/World Voxel Craft/ChunkIndicator.mat
  66. 8 0
      Assets/ARLocation/Experimental/World Voxel Craft/ChunkIndicator.mat.meta
  67. 93 0
      Assets/ARLocation/Experimental/World Voxel Craft/CubeBrick.prefab
  68. 7 0
      Assets/ARLocation/Experimental/World Voxel Craft/CubeBrick.prefab.meta
  69. 77 0
      Assets/ARLocation/Experimental/World Voxel Craft/CubeBrickMaterial.mat
  70. 8 0
      Assets/ARLocation/Experimental/World Voxel Craft/CubeBrickMaterial.mat.meta
  71. 93 0
      Assets/ARLocation/Experimental/World Voxel Craft/CubeGold.prefab
  72. 7 0
      Assets/ARLocation/Experimental/World Voxel Craft/CubeGold.prefab.meta
  73. 77 0
      Assets/ARLocation/Experimental/World Voxel Craft/CubeGoldMaterial.mat
  74. 8 0
      Assets/ARLocation/Experimental/World Voxel Craft/CubeGoldMaterial.mat.meta
  75. 93 0
      Assets/ARLocation/Experimental/World Voxel Craft/CubeStone.prefab
  76. 7 0
      Assets/ARLocation/Experimental/World Voxel Craft/CubeStone.prefab.meta
  77. 77 0
      Assets/ARLocation/Experimental/World Voxel Craft/CubeStoneMaterial.mat
  78. 8 0
      Assets/ARLocation/Experimental/World Voxel Craft/CubeStoneMaterial.mat.meta
  79. 94 0
      Assets/ARLocation/Experimental/World Voxel Craft/Indicator Plane.prefab
  80. 7 0
      Assets/ARLocation/Experimental/World Voxel Craft/Indicator Plane.prefab.meta
  81. 78 0
      Assets/ARLocation/Experimental/World Voxel Craft/Indicator.mat
  82. 8 0
      Assets/ARLocation/Experimental/World Voxel Craft/Indicator.mat.meta
  83. 二進制
      Assets/ARLocation/Experimental/World Voxel Craft/Pickaxe.png
  84. 88 0
      Assets/ARLocation/Experimental/World Voxel Craft/Pickaxe.png.meta
  85. 24 0
      Assets/ARLocation/Experimental/World Voxel Craft/PrefabDb.asset
  86. 8 0
      Assets/ARLocation/Experimental/World Voxel Craft/PrefabDb.asset.meta
  87. 739 0
      Assets/ARLocation/Experimental/World Voxel Craft/WorldVoxelController.cs
  88. 11 0
      Assets/ARLocation/Experimental/World Voxel Craft/WorldVoxelController.cs.meta
  89. 二進制
      Assets/ARLocation/Experimental/World Voxel Craft/brick_mixed 1.png
  90. 88 0
      Assets/ARLocation/Experimental/World Voxel Craft/brick_mixed 1.png.meta
  91. 二進制
      Assets/ARLocation/Experimental/World Voxel Craft/brick_mixed.png
  92. 88 0
      Assets/ARLocation/Experimental/World Voxel Craft/brick_mixed.png.meta
  93. 二進制
      Assets/ARLocation/Experimental/World Voxel Craft/rect12.png
  94. 88 0
      Assets/ARLocation/Experimental/World Voxel Craft/rect12.png.meta
  95. 二進制
      Assets/ARLocation/Experimental/World Voxel Craft/stone_granite_brick 1.png
  96. 88 0
      Assets/ARLocation/Experimental/World Voxel Craft/stone_granite_brick 1.png.meta
  97. 二進制
      Assets/ARLocation/Experimental/World Voxel Craft/stone_granite_brick.png
  98. 88 0
      Assets/ARLocation/Experimental/World Voxel Craft/stone_granite_brick.png.meta
  99. 二進制
      Assets/ARLocation/Experimental/World Voxel Craft/topaz_brick 1.png
  100. 0 0
      Assets/ARLocation/Experimental/World Voxel Craft/topaz_brick 1.png.meta

二進制
.DS_Store


二進制
Assets/.DS_Store


+ 8 - 0
Assets/ARLocation.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 10e4dc634c095458d9c3accf316fff38
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 14 - 0
Assets/ARLocation/ARLocationConfig.asset

@@ -0,0 +1,14 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 9fdf1fc4a89fb2243b47ffffdffcc69e, type: 3}
+  m_Name: ARLocationConfig
+  m_EditorClassIdentifier: 
+  EarthRadiusInKM: 6372.8

+ 8 - 0
Assets/ARLocation/ARLocationConfig.asset.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 6a964cb8537badb4392eada7083e66c0
+NativeFormatImporter:
+  externalObjects: {}
+  mainObjectFileID: 11400000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 273 - 0
Assets/ARLocation/CHANGELOG.md

@@ -0,0 +1,273 @@
+# 3.7.1
+- Added: `RenderPathLine.SetLocationPath` method.
+- Fixed: Route path renderer not working
+
+# 3.7.0
+- Added `DeactivateOnLeave` property to reset the hotspot on leave.
+- Fixed error with `ARPlaneManager.requestedDetectionMode` in Unity 2019.4.
+
+# 3.6.1
+- Fixed "GameObject -> AR+GPS -> Mapbox Route" game object context menu item not setting the on-screen indicator arrow sprite.
+- Fixed "GameObject -> AR+GPS -> Mapbox Route" game object context menu item not setting the path route renderere "Line Material".
+- Fixed "Can't calculate tangents, because mesh 'Widget' doesn't contain normals." warning.
+- Fixed corrupted "jet.mp3" file.
+
+# 3.6.0
+- New Major Feature: Routes and Navigation powered by the Mapbox Directions API! Check our [documentation pages](https://docs.unity-ar-gps-location.com/routes/) for more information on this feature.
+- Fixed "'UnityWebRequest.isNetworkError' is obsolete:..." warnings.
+- Fixed "SceneDistance" now returns the 2D distance (that is, the distance on the xz plane).
+- Fixed "Assets/ARLocation/Scripts/Utils/Misc.cs(37,13) warning CS0618 'ARPlaneManager.detectionMode' is obsolete 'Use requestedDetectionMode or currentDetectionMode instead" warnings.
+
+# 3.5.5
+- Fixed warnings and compatibility issues with Unity 2020.3 and AR Foundation 4.
+
+# 3.5.4
+- Hability to use both raw and filtered GPS data in the `Hotspot` component.
+
+# 3.5.2
+- Experimental feature "World Builder": Allows the user to place objects on locations interactivelly that will perstist between sessions.
+- Experimental feature "World Voxels": Persistent GPS-based voxel sandbox experiment.
+- Fixed error in `GetLocationForWorldPosition` calculations
+- Fixed issue when using `PlaceAtLocation.CreatePlacedInstance`
+
+# 3.5.1
+- New feature: calculate geographical location from Unity world-position.
+- Fixed bug when using `PlaceAtLocation` in prefabs.
+
+# 3.5.0
+- Fixed bug in "ARLocationDevCamera". 
+- Genaral improved geo-location calculation methods, specially long-distance objects.
+- Added possibility of using user-provided, custom geo-calculation methods.
+
+# 3.4.1
+- Fixed corrupted 'GO Map Integration.zip'file.
+
+# 3.4.0
+- Fixed object orientation issue when placing objects at runtime.
+- Fixed possible crash in `ARLocationOrientation#Restart`.
+- Added integration with "GO Map 3D" asset, with sample scene.
+- Added `Show Objects After This Many Updates` option so you can control how many location updates to wait before showing the placed object.
+- Added `Instances` getter to `PlaceAtLocations` so you can access created instances.
+- Added `OnHotspotLeave`  event to `Hotspot`.
+- Ground-plane detection on ARFoundation now listens for plane changes.
+
+
+# 3.3.2
+- Fixed xml-parsing issue in "Web Map Loader" component.
+- Fixed issue with "GroundHeight" mode when using movement smoothing.
+- Added "Speed" property getter for the "MoveAlongPath" component.
+
+# 3.3.1
+- Fixed `AR Floor` prefab not rendering correctly on 2019.2+.
+- Fixed erros when running on Unity 2019.3b.
+
+# 3.3.0
+- Added `Web Map Loader` component to load data from the Web Map Editor (https://editor.unity-ar-gps-location.com). For
+  details check the docs (https://docs.unity-ar-gps-location.com/map/).
+
+# 3.2.1
+- Fixed bug in `PlaceAtLocation#Location` setter.
+- Fixed event listeners not properly cleaned-up on some components.
+	
+# 3.2.0
+- Improved the Debug Mode for the `PlaceAtLocation` component.
+
+  Now, when Debug Mode is enabled, a line is rendered from the camera to
+  the object, indicating it's position, and the current distance from the
+  user to the object is displayed as a TextMesh.
+  
+ - Added the `ARLocationManager#CurrentGroundY` variable, which returns the Y coordinate
+   of the detected plane which is nearest to the user/camera. 
+
+# 3.1.1
+- Fixed `mainCamera` null reference on Vuforia `GroundHeight`
+
+# 3.1.0
+- Implemented native tilt-compensated compass on Android
+- Fixed coroutines not being stopped in SmoothMove
+- Fixed PlaceAtLocation#Location setter not updating sometimes
+
+# 3.0.4
+- Fixed null reference error when switching scenes
+- Fixed ground relative altitude issue
+
+# 3.0.3
+- Moved `MagneticDeclination.jar` to ARLocation plugins folder
+
+# 3.0.2
+- Changed AltitudeMode on sample scene
+
+# 3.0.1
+- Fixed `3D Text` sample scene
+
+# 3.0.0
+- Added `HelpURL` linking to documentation in components
+- Added `Walking Zombie` prefab
+- Improved AR Floor's `FollowCameraPosition` script
+- Adjusted default values of properties
+
+# 3.0.0-beta.4
+- Fixed warnings on multiple Unity versions
+- Fixed positioning issue on `MoveAlongPath`
+- Fixed ground height issue on `MoveAlongPath`
+- Refactored `MoveAlongPath` and `PathLineRenderer`
+- Added `PlaceAlongPath#AltitudeMode` property
+
+# 3.0.0-beta.3
+- Improved restart methods
+- PlaceAtLocation restarts with LocationProvider
+- Added `ARLocationProvider#OnProviderRestartEvent`
+- Fixed `PlaceAtLocation#Location` setter to work before `Start` is called
+- Fixed bug on initial placement on `PlaceAtLocation`
+- Added `SmoothMove#Precision` property
+
+
+
+# 3.0.0-beta.2
+- Added `ARLocationOrientation#OnBeforeOrientationUpdated` event
+- Added custom location providers via ARGPS_CUSTOM_PROVIDER define symbol
+- Added `Hotspot#CurrentDistance` property
+- Updated documentation
+
+# 3.0.0-beta.1
+- Added `ISessionManager` class to manage the ARSession, with implementations for Vuforia and ARFoundation.
+- Added `Restart` methods to ARLocationProvider, ARLocationOrientation and ARLocationManager. They will reset
+the components to their initial state. In particular, calling `ARLocationManager#Restart` will restart the location
+and orientation, and update all the objects positions.
+- Added `ARLocationManager#WaitForARTrackingToStart` property. When this is enabled, any location and orientation 
+updates will only happen when the AR tracking has started.
+- Added `ARLocationManager#RestartWhenARTrackingIsRestored`. This will restart the AR+GPS system whenever the AR 
+tracking is lost and regained.
+- Added `OnTrackingStarted`, `OnTrackingLost` and `OnTrackingRestarted` unity events to `ARLocationManager`
+- Added `ARLocationManager#ResetARSession` to reset both the ARSession and the AR+GPS system.
+
+# 3.0.0-alpha.3
+- Added `PlaceAtLocation#Restart`
+- Added debug mode to `Hotspot`
+- Added `DebugMode` to `PlaceAlongPath`
+- Added `DebugMode` to MoveAlongPath
+- Added `DebugMode` to `PlaceAtLocations`
+- Added debug mode to `PlaceAtLocation`
+- Added `MoveAlongPath#Reset` method
+- Added `DisallowMultipleComponent` to components
+- Added ground height to MoveAlongPath
+- Removed Object button on ARLocationInfo
+- Small changes on RenderPathLine
+- Minor refactoring on PlaceAlongPath
+- Refactor state fields on `MoveAlongPath`
+- Refactored Properties on MoveAlongPath
+- Fixed property names on `LocationPathInspector`
+- Fixed bug with LocationPathInspector
+- Fixed MaxNumberOfUpdates issue in MoveAlongPath
+
+# 3.0.0-alpha.2
+- Added `Hotspot` component feature
+- Major refactoring to remove warnings
+- Added native Android module to calculate true north/magnetic declination
+- Major improvements on PlateAtLocation and PlaceAtLocations
+- Added Events to PlaceAtLocation, Hotspot, ARLocationProvider, and ARLocationOrientation
+- Added Hotspot sample scene
+- Added easier interface to create PlaceAt objects via code
+- Changed how SmoothMove works; now all Smooth Factors go from 0 to 1
+
+# 2.7.0
+- Fixed error due to wrong constructor name on `PlaneManager` when using Vuforia
+
+# 2.6.0
+
+- Updated samples to work with AR Foundation 1.5
+
+# 2.5.0
+
+- AR Foundation 1.5/2.0 compability. Not compatible with AR Foundation 1.0 anymore
+- Removed automatic session reset
+- Added null check for arLocationPlaneManager
+
+# 2.4.0
+
+- Added automatic height/altitude setting via plane detection (`UseNearestDetectedPlaneHeight` option)
+- Added a public `enabled` flag to enable/disable positioning in ARLocationPlaceAtLocation enhancement
+- Added ARLocationManager#Remove(entry)
+- Added enabled/disabled flag do ARLocationManager Entry
+- Added `offset` option to `ARLocationMoveAlongCurve` enhancement
+- Added exponential weighted moving average filtering enhancement
+- Added `LocationData` scriptable object to store geo locations enhancement
+- Added `MaxNumberOfMeasurements` option to `ARLocationProvider` enhancement
+- Added `Pause` and `Resume` methods for `ILocationProvider` enhancement
+- Added default value to location in `ARLocationPlaceAtLocation`
+- Added `Distance` and `GPSHorizontalDistance` methods `ARLocationManagerEntry`
+- Added `ARLocationManager#UpdatePositions`
+- Added `ARLocationManager#Clear`
+- Modified `ARLocationManager` to use System.Guuid as entry IDs
+- Modified `ARLocationManager#Restart` to be public
+- Modified `Manager#Remove` to destroy instances when `createInstance` is true
+- Fixed Reloading scene issues with Singletons bug
+- Removed native location modules for now
+- Fixed `ARLocationPlaceAtLocation#SetLocation` bug
+- Fixed `ARLocationDebugInfo` bug on entry removal
+- Fixed `ARLocationManager` setting position of `ARLocationRoot` instead of entry
+- Fixed `MaxNumberOfMeasurements` behaviour on `ARLocationProvider`
+
+# 2.3.0
+
+- Fixed wrong compass rotation pivot point 
+
+# 2.2.0
+
+- Fixed mock location and dev-mode camera for in-editor development
+- Moved LocationProvider instantiation to `Awake`
+- Changed `ARLocationManager` and `ARLocationProvider` to be singleton classes
+- Added Linear spline interpolation for paths
+- Fixed compass rotation in ARLocationInfo component
+
+
+# 2.1.0
+
+- Fixed issue where location authorization was not being requested on Android
+- Fixed issue where location was only enabled after request the next time the application
+  was executed
+- Fixed issue where ARLocationPlateAtLocation#SetLocation was not updating positions
+
+# 2.0.0
+
+- Added native GPS module for Android
+- Added native GPS module for iOS
+- Added global package configuration in resources folder
+- Added easy Vuforia setup by clicking a checkbox in configuration
+- Added option for custom magnetic declination/offset
+- Added option for custom earth radius
+- Added option selecting distance functions
+- Added more filtering options for ARLocationProvider
+- Fixed compass tilt bug on iOS native GPS module
+- Added Vuforia samples package
+
+# 1.2.0
+
+- Added support for using Vuforia as the AR framework
+
+  - With this Vuforia can be used instead of AR Foundation. For that
+	it is necessary to add am entry `ARGPS_USE_VUFORIA` in the 'Player
+	Settings' -> 'Scripting Define Symbols' list.
+
+  - As far as the scene structure is concerned, we don't have a 'AR
+	Session Origin' from AR Foundation, anymore so the
+	'ARLocationRoot' object is placed directly in the root of the
+	scene in this cas.e
+
+- Fixed NullReferenceException throw when creating/editing an empty ARLocationPath
+
+
+# 1.1.0
+
+- Fixed error when there is no debug canvas.
+- Improved error handling and debug logging when searching for objects and components.
+
+# 1.0.1
+
+- Fixed ShaderDrawer shader not working on Unity-2018.1.0.
+- Added API Reference and Guide PDF files.
+- Cleaned up unused variables in some classes.
+
+# 1.0.0
+
+Initial Release 🎉

+ 7 - 0
Assets/ARLocation/CHANGELOG.md.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: d7efeac44ba82b041b454f5048569bcc
+TextScriptImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/ARLocation/Data.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ff535e1943aaaa64494f667dc3d3fefb
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 18 - 0
Assets/ARLocation/Data/PrefabDb.asset

@@ -0,0 +1,18 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 4d58c52ff9f122a49a289c83a1611436, type: 3}
+  m_Name: PrefabDb
+  m_EditorClassIdentifier: 
+  Entries:
+  - MeshId: Cube
+    Prefab: {fileID: 2198125378339800612, guid: 987dd04d41b1fcf4a9ed5ade4d053c88,
+      type: 3}

+ 8 - 0
Assets/ARLocation/Data/PrefabDb.asset.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5938ca4a639db8b448becdaee8d18567
+NativeFormatImporter:
+  externalObjects: {}
+  mainObjectFileID: 11400000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

文件差異過大導致無法顯示
+ 1 - 0
Assets/ARLocation/Data/data.xml


+ 7 - 0
Assets/ARLocation/Data/data.xml.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 83f9141ce219b4f46837872d48ea29c9
+TextScriptImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/ARLocation/Editor.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 49bcc89784be54e82b73403dffd654d9
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 197 - 0
Assets/ARLocation/Editor/ARLocationConfigInspector.cs

@@ -0,0 +1,197 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+// ReSharper disable InconsistentNaming
+
+namespace ARLocation
+{
+
+    /// <summary>
+    /// Inspector for the ARLocationConfig. This inspector is the main configuration
+    /// interface for the AR+GPS Location plugin.
+    /// </summary>
+    [CustomEditor(typeof(ARLocationConfig))]
+    public class ARLocationConfigInspector : Editor
+    {
+
+        SerializedProperty p_EarthRadiusInKM;
+        SerializedProperty p_EarthEquatorialRadius;
+        SerializedProperty p_EarthFirstEccentricitySquared;
+        SerializedProperty p_UseVuforia;
+        SerializedProperty p_UseCustomGeoCalculator;
+        SerializedProperty p_InitialGroundHeightGuess;
+        SerializedProperty p_VuforiaGroundHitTestDistance;
+        private SerializedProperty p_MinGroundHeight;
+        private SerializedProperty p_MaxGroundHeight;
+        private SerializedProperty p_GroundHeightSmoothingFactor;
+
+        DefineSymbolsManager defineSymbolsManager;
+
+        const string ARGPS_USE_VUFORIA = "ARGPS_USE_VUFORIA";
+        const string ARGPS_USE_NATIVE_LOCATION = "ARGPS_USE_NATIVE_LOCATION";
+        const string ARGPS_USE_CUSTOM_GEO_CALC = "ARGPS_USE_CUSTOM_GEO_CALC";
+
+        Dictionary<string, string> defineSymbolProps = new Dictionary<string, string> {
+        {ARGPS_USE_VUFORIA, "UseVuforia"},
+        {ARGPS_USE_NATIVE_LOCATION, "UseNativeLocationModule"}
+    };
+
+        private void OnEnable()
+        {
+            p_EarthRadiusInKM = serializedObject.FindProperty("EarthMeanRadiusInKM");
+            p_EarthEquatorialRadius = serializedObject.FindProperty("EarthEquatorialRadiusInKM");
+            p_EarthFirstEccentricitySquared = serializedObject.FindProperty("EarthFirstEccentricitySquared");
+            p_UseVuforia = serializedObject.FindProperty("UseVuforia");
+            p_UseCustomGeoCalculator = serializedObject.FindProperty("UseCustomGeoCalculator");
+            p_InitialGroundHeightGuess = serializedObject.FindProperty("InitialGroundHeightGuess");
+            p_VuforiaGroundHitTestDistance = serializedObject.FindProperty("VuforiaGroundHitTestDistance");
+            p_MinGroundHeight = serializedObject.FindProperty("MinGroundHeight");
+            p_MaxGroundHeight = serializedObject.FindProperty("MaxGroundHeight");
+            p_GroundHeightSmoothingFactor = serializedObject.FindProperty("GroundHeightSmoothingFactor");
+
+            defineSymbolsManager = new DefineSymbolsManager(new[]
+            {
+            BuildTargetGroup.iOS,
+            BuildTargetGroup.Android
+            });
+        }
+
+        private void UpdateDefineSymbolsFromPlayerSettings()
+        {
+            defineSymbolsManager.UpdateFromBuildSettings();
+
+            foreach (var item in defineSymbolProps)
+            {
+                if (item.Value == "UseVuforia")
+                {
+#if !UNITY_2019_3_OR_NEWER
+#if UNITY_2019_2
+                    var value = defineSymbolsManager.Has(item.Key) && PlayerSettings.vuforiaEnabled;
+#else
+                    var value = defineSymbolsManager.Has(item.Key) && PlayerSettings.GetPlatformVuforiaEnabled(BuildTargetGroup.Android) && PlayerSettings.GetPlatformVuforiaEnabled(BuildTargetGroup.iOS);
+#endif
+                    UpdateDefineSymbolProp(item.Value, value);
+#endif
+                }
+                else
+                {
+                    UpdateDefineSymbolProp(item.Value, defineSymbolsManager.Has(item.Key));
+                }
+            }
+
+            serializedObject.ApplyModifiedProperties();
+        }
+
+        private void UpdateDefineSymbolProp(string propName, bool value)
+        {
+            var prop = serializedObject.FindProperty(propName);
+
+            if (prop == null)
+            {
+                return;
+            }
+
+            prop.boolValue = value;
+        }
+
+
+        public override void OnInspectorGUI()
+        {
+            serializedObject.Update();
+
+            UpdateDefineSymbolsFromPlayerSettings();
+
+            defineSymbolsManager.UpdateFromBuildSettings();
+
+
+            EditorGUILayout.HelpBox("AR+GPS Location " + ARLocationConfig.Version, MessageType.None, true);
+            EditorGUILayout.PropertyField(p_EarthRadiusInKM);
+            EditorGUILayout.PropertyField(p_EarthEquatorialRadius);
+            EditorGUILayout.PropertyField(p_EarthFirstEccentricitySquared);
+            EditorGUILayout.PropertyField(p_InitialGroundHeightGuess);
+            EditorGUILayout.PropertyField(p_MinGroundHeight);
+            EditorGUILayout.PropertyField(p_MaxGroundHeight);
+            EditorGUILayout.PropertyField(p_GroundHeightSmoothingFactor);
+            EditorGUILayout.PropertyField(p_VuforiaGroundHitTestDistance);
+            EditorGUILayout.PropertyField(p_UseVuforia);
+            EditorGUILayout.PropertyField(p_UseCustomGeoCalculator);
+
+
+            if (p_UseVuforia.boolValue)
+            {
+#if UNITY_2019_3_OR_NEWER
+		EditorGUILayout.HelpBox("Make sure that Vuforia is instaled in the Package Manager Window.  On Android, also make sure that the 'ARCore XR Plugin' is not installed.", MessageType.Info);
+#endif
+                // EditorGUILayout.HelpBox("So that Vuforia works correctly, please enable the 'Track Device Pose' option in the Vuforia configuration, and set the tracking" +
+                //     " mode to 'POSITIONAL'.", MessageType.Warning);
+                EditorGUILayout.HelpBox(
+                    "Note that the regular sample scenes do not work with Vuforia. You can download a project with Vuforia samples at https://github.com/dmbfm/unity-ar-gps-location-issues/releases/tag/v3.1.1", MessageType.Warning);
+            }
+
+
+            if (GUILayout.Button("Open Documentation"))
+            {
+                Application.OpenURL("https://docs.unity-ar-gps-location.com");
+            }
+
+            var config = (ARLocationConfig)target;
+
+            UpdateDefineSymbolPropConfig(config.UseVuforia, p_UseVuforia.boolValue, ARGPS_USE_VUFORIA);
+
+            UpdateVuforiaPlayerSettings(config.UseVuforia, p_UseVuforia.boolValue);
+
+            UpdateDefineSymbolPropConfig(config.UseCustomGeoCalculator, p_UseCustomGeoCalculator.boolValue, ARGPS_USE_CUSTOM_GEO_CALC);
+
+            serializedObject.ApplyModifiedProperties();
+        }
+
+        private void UpdateVuforiaPlayerSettings(bool oldValue, bool newValue)
+        {
+            if (newValue == oldValue)
+            {
+                return;
+            }
+
+#if !UNITY_2019_3_OR_NEWER
+#if UNITY_2019_2
+            if (newValue)
+            {
+                PlayerSettings.vuforiaEnabled = true;
+            }
+            else
+            {
+                PlayerSettings.vuforiaEnabled = false;
+            }
+#else
+            if (newValue)
+            {
+                PlayerSettings.SetPlatformVuforiaEnabled(BuildTargetGroup.Android, true);
+                PlayerSettings.SetPlatformVuforiaEnabled(BuildTargetGroup.iOS, true);
+            }
+            else
+            {
+                PlayerSettings.SetPlatformVuforiaEnabled(BuildTargetGroup.Android, false);
+                PlayerSettings.SetPlatformVuforiaEnabled(BuildTargetGroup.iOS, false);
+            }
+#endif
+#endif
+
+        }
+
+        private void UpdateDefineSymbolPropConfig(bool oldValue, bool newValue, string symbol)
+        {
+            if (newValue == oldValue) return;
+
+            if (newValue)
+            {
+                defineSymbolsManager.Add(symbol);
+            }
+            else
+            {
+                defineSymbolsManager.Remove(symbol);
+            }
+
+            defineSymbolsManager.ApplyToBuildSettings();
+        }
+    }
+}

+ 11 - 0
Assets/ARLocation/Editor/ARLocationConfigInspector.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8495d2aab784d08438028469591d9035
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 38 - 0
Assets/ARLocation/Editor/ARLocationEditorConfigManager.cs

@@ -0,0 +1,38 @@
+using UnityEngine;
+using UnityEditor;
+
+/// <summary>
+/// This is a static class that makes sure that there always is a
+/// ARLocationConfig resource for the project.
+/// </summary>
+[InitializeOnLoad]
+// ReSharper disable once InconsistentNaming
+public class ARLocationEditorConfigManager {
+    static ARLocationEditorConfigManager()
+    {
+        Debug.Log("[ARLocation]: Starting up!");
+
+        if (AssetDatabase.IsValidFolder("Assets/Resources"))
+        {
+            Debug.Log("[ARLocation]: Resource folder already exists!");
+        }
+        else
+        {
+            Debug.Log("[ARLocation]: Creating resource folder...");
+            AssetDatabase.CreateFolder("Assets", "Resources");
+        }
+
+        var ss = AssetDatabase.FindAssets("ARLocationConfig", new [] {"Assets/Resources"});
+
+        if (ss.Length > 0)
+        {
+            Debug.Log("[ARLocation]: Config already exists!");
+        }
+        else
+        {
+            Debug.Log("[ARLocation]: Creating new configuration!");
+            AssetDatabase.CopyAsset("Assets/ARLocation/ARLocationConfig.asset", "Assets/Resources/ARLocationConfig.asset");
+        }
+
+    }
+}

+ 11 - 0
Assets/ARLocation/Editor/ARLocationEditorConfigManager.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a4d3663ff15f0594b92750a28c890f98
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 19 - 0
Assets/ARLocation/Editor/ARLocationManagerInspector.cs

@@ -0,0 +1,19 @@
+using UnityEngine;
+using UnityEditor;
+
+namespace ARLocation
+{
+    [CustomEditor(typeof(ARLocationManager))]
+    public class ARLocationManagerInspector : Editor
+    {
+        public override void OnInspectorGUI()
+        {
+            DrawDefaultInspector();
+
+            if (GUILayout.Button("Open AR+GPS Location configuration"))
+            {
+                Selection.activeObject = Resources.Load<ARLocationConfig>("ARLocationConfig");
+            }
+        }
+    }
+}

+ 11 - 0
Assets/ARLocation/Editor/ARLocationManagerInspector.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 05ddda517c35529448a6280a661a6130
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 19 - 0
Assets/ARLocation/Editor/ARLocationOrientationInspector.cs

@@ -0,0 +1,19 @@
+using UnityEditor;
+
+namespace ARLocation
+{
+    [CustomEditor(typeof(ARLocationOrientation))]
+    public class ARLocationOrientationInspector : Editor
+    {
+        public override void OnInspectorGUI()
+        {
+            DrawDefaultInspector();
+
+#if PLATFORM_ANDROID
+            EditorGUILayout.HelpBox("On some Android devices, the magnetic compass data is not tilt compensated," +
+                                    "so it is recommended that you check the 'ApplyCompassTiltCompensationOnAndroid' option above. " +
+                                    "\n", MessageType.Warning);
+#endif
+        }
+    }
+}

+ 11 - 0
Assets/ARLocation/Editor/ARLocationOrientationInspector.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 7bbddfcfb1fdd744ca14e8d339d5de4e
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 19 - 0
Assets/ARLocation/Editor/ARLocationProviderInspector.cs

@@ -0,0 +1,19 @@
+using UnityEngine;
+using UnityEditor;
+
+namespace ARLocation
+{
+    [CustomEditor(typeof(ARLocationProvider))]
+    public class ARLocationProviderInspector : Editor
+    {
+        public override void OnInspectorGUI()
+        {
+            DrawDefaultInspector();
+
+            if (GUILayout.Button("Open AR+GPS Location configuration"))
+            {
+                Selection.activeObject = Resources.Load<ARLocationConfig>("ARLocationConfig");
+            }
+        }
+    }
+}

+ 11 - 0
Assets/ARLocation/Editor/ARLocationProviderInspector.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 31c8812c560040c459afdb25fb9e0e97
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 26 - 0
Assets/ARLocation/Editor/ConditionalPropertyDrawer.cs

@@ -0,0 +1,26 @@
+using UnityEngine;
+using UnityEditor;
+
+namespace ARLocation
+{
+    [CustomPropertyDrawer(typeof(ConditionalPropertyAttribute))]
+    public class ConditionalPropertyDrawer : PropertyDrawer
+    {
+        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
+        {
+            var conditionalAttribute = (ConditionalPropertyAttribute) attribute;
+            var name = conditionalAttribute.Name;
+
+            var path = property.propertyPath;
+            var prop = property.serializedObject.FindProperty(path.Replace(property.name, name));
+
+            if (prop != null)
+            {
+                if (prop.boolValue)
+                {
+                    EditorGUI.PropertyField(position, property);
+                }
+            }
+        }
+    }
+}

+ 11 - 0
Assets/ARLocation/Editor/ConditionalPropertyDrawer.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d6d3f69da74d06645a200b330b98e3cf
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 42 - 0
Assets/ARLocation/Editor/DefineSymbols.cs

@@ -0,0 +1,42 @@
+using System.Collections.Generic;
+// ReSharper disable MemberCanBePrivate.Global
+
+/// <summary>
+/// Utility class to manage a list of symbol strings.
+/// </summary>
+public class DefineSymbols {
+    private List<string> symbols;
+
+    public DefineSymbols(string symbols)
+    {
+        Set(symbols);
+    }
+
+    public void Set(string sym)
+    {
+        symbols = new List<string>(sym.Split(new [] { ";" }, System.StringSplitOptions.None));
+    }
+
+    public bool Has(string symbol)
+    {
+        return (symbols.FindIndex(obj => obj == symbol) >= 0);
+    }
+
+    public void Add(string symbol)
+    {
+        if (!Has(symbol))
+        {
+            symbols.Add(symbol);
+        }
+    }
+
+    public void Remove(string symbol)
+    {
+        symbols.Remove(symbol);
+    }
+
+    public string Get()
+    {
+        return string.Join(";", symbols.ToArray());
+    }
+}

+ 11 - 0
Assets/ARLocation/Editor/DefineSymbols.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f14e3e24ba92d4b4580962e6ff11b166
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 82 - 0
Assets/ARLocation/Editor/DefineSymbolsManager.cs

@@ -0,0 +1,82 @@
+using System.Collections.Generic;
+using UnityEditor;
+
+
+/// <summary>
+/// Utility class that manages Define Symbols for a given set of build targets.
+/// </summary>
+public class DefineSymbolsManager  {
+    private Dictionary<BuildTargetGroup, DefineSymbols> defineSymbols  = new Dictionary<BuildTargetGroup, DefineSymbols>();
+
+    public DefineSymbolsManager(BuildTargetGroup[] groups)
+    {
+        foreach (var group in groups)
+        {
+            var symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
+            defineSymbols.Add(group, new DefineSymbols(symbols));
+        }
+    }
+
+    public void UpdateFromBuildSettings()
+    {
+        var groups = defineSymbols.Keys;
+        defineSymbols = new Dictionary<BuildTargetGroup, DefineSymbols>();
+
+        foreach (var group in groups)
+        {
+            var symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
+            defineSymbols.Add(group, new DefineSymbols(symbols));
+        }
+
+    }
+
+    public void ApplyToBuildSettings()
+    {
+        foreach (var e in defineSymbols)
+        {
+            PlayerSettings.SetScriptingDefineSymbolsForGroup(e.Key, e.Value.Get());
+        }
+    }
+
+    public void Add(string symbol)
+    {
+        foreach (var item in defineSymbols)
+        {
+            item.Value.Add(symbol);
+        }
+    }
+
+    public void Remove(string symbol)
+    {
+        foreach (var item in defineSymbols)
+        {
+            item.Value.Remove(symbol);
+        }
+    }
+
+    public bool Has(string symbol)
+    {
+        var has = true;
+
+        foreach (var item in defineSymbols)
+        {
+            has = has && item.Value.Has(symbol);
+        }
+
+        return has;
+    }
+
+    public override string ToString()
+    {
+        var str = "DefineSymbolsManager {\n";
+
+        foreach (var item in defineSymbols)
+        {
+            str += item.Key + ": " + item.Value.Get() + "\n";
+        }
+
+        str += "}";
+
+        return str;
+    }
+}

+ 11 - 0
Assets/ARLocation/Editor/DefineSymbolsManager.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f176688e5ede64e18abc8e4885c3311a
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 103 - 0
Assets/ARLocation/Editor/GameObjectMenuItems.cs

@@ -0,0 +1,103 @@
+using UnityEngine;
+using UnityEditor;
+
+#if !ARGPS_USE_VUFORIA
+using UnityEngine.XR.ARFoundation;
+#endif
+
+namespace ARLocation
+{
+    public static class GameObjectMenuItems{
+
+        [MenuItem("GameObject/AR+GPS/ARLocationRoot", false, 20)]
+        public static void CreateARLocationRoot()
+        {
+            var go = new GameObject("ARLocationRoot");
+
+            go.AddComponent<ARLocationManager>();
+            go.AddComponent<ARLocationProvider>();
+
+            var arSessionOrigin = GameObject.Find("AR Session Origin");
+
+            if (arSessionOrigin != null)
+            {
+                go.transform.SetParent(arSessionOrigin.transform);
+            }
+        }
+
+        [MenuItem("GameObject/AR+GPS/GPS Stage Object", false, 20)]
+        public static GameObject CreateGpsStageObject()
+        {
+            var go = new GameObject("GPS Stage Object");
+
+            go.AddComponent<PlaceAtLocation>();
+
+            return go;
+        }
+
+        [MenuItem("GameObject/AR+GPS/GPS Hotspot Object", false, 20)]
+        public static GameObject CreateGpsHotspotObject()
+        {
+            var go = new GameObject("GPS Hotspot Object");
+
+            go.AddComponent<Hotspot>();
+
+            return go;
+        }
+
+#if ARGPS_DEV_MODE
+        [MenuItem("Assets/Print GUID", false)]
+        public static void PrintGuit()
+        {
+            foreach (var s in Selection.assetGUIDs)
+            {
+                Debug.Log(s);
+            }
+        }
+#endif
+
+        [MenuItem("GameObject/AR+GPS/Create Basic Scene Structure", false, 20)]
+        public static void CreateBasicScene()
+        {
+#if ARGPS_USE_VUFORIA
+            EditorApplication.ExecuteMenuItem("GameObject/Vuforia Engine/AR Camera");
+            Selection.activeObject = null;
+            EditorApplication.ExecuteMenuItem("GameObject/Vuforia Engine/Ground Plane/Plane Finder");
+
+            CreateARLocationRoot();
+            var stage = CreateGpsStageObject();
+
+            var capsule = GameObject.CreatePrimitive(PrimitiveType.Capsule);
+            capsule.transform.SetParent(stage.transform);
+#else
+            EditorApplication.ExecuteMenuItem("GameObject/XR/AR Session");
+            Selection.activeObject = null;
+            EditorApplication.ExecuteMenuItem("GameObject/XR/AR Session Origin");
+            Selection.activeObject = null;
+            EditorApplication.ExecuteMenuItem("GameObject/AR+GPS/ARLocationRoot");
+
+            var prevMain = GameObject.FindWithTag("MainCamera");
+            if (prevMain)
+            {
+                Object.DestroyImmediate(prevMain);
+            }
+
+            var cam = GameObject.Find("AR Camera");
+
+            if (cam)
+            {
+                cam.tag = "MainCamera";
+                var camera = cam.GetComponent<Camera>();
+                camera.farClipPlane = 1000.0f;
+            }
+
+            var arSessionOrigin = Object.FindObjectOfType<ARSessionOrigin>().gameObject;
+            arSessionOrigin.AddComponent<ARPlaneManager>();
+
+            var stage = CreateGpsStageObject();
+            var capsule = GameObject.CreatePrimitive(PrimitiveType.Capsule);
+            capsule.transform.SetParent(stage.transform);
+#endif
+        }
+    }
+}

+ 11 - 0
Assets/ARLocation/Editor/GameObjectMenuItems.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f06d2b153a6ae5a42b201b986063aacd
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 224 - 0
Assets/ARLocation/Editor/LocationPathInspector.cs

@@ -0,0 +1,224 @@
+using System;
+using UnityEngine;
+using UnityEditor;
+// ReSharper disable DelegateSubtraction
+
+namespace ARLocation
+{
+
+    [CustomEditor(typeof(LocationPath))]
+    public class LocationPathInspector : Editor
+    {
+
+        SerializedProperty alpha;
+        SerializedProperty locations;
+        SerializedProperty sceneViewScale;
+        SerializedProperty splineType;
+
+        // float viewScale = 1.0f;
+
+        private void OnEnable()
+        {
+            FindProperties();
+
+            AddOnSceneGUIDelegate(OnSceneGuiDelegate);
+
+            Tools.hidden = true;
+        }
+
+
+#if UNITY_2019_1_OR_NEWER
+        private void AddOnSceneGUIDelegate(Action<SceneView> del)
+        {
+            SceneView.duringSceneGui += del; // sceneView => OnSceneGUI();
+        }
+#else
+        private void AddOnSceneGUIDelegate(SceneView.OnSceneFunc del)
+        {
+            SceneView.onSceneGUIDelegate += del;
+        }
+#endif
+
+#if UNITY_2019_1_OR_NEWER
+        private void RemoveOnSceneGUIDelegate(Action<SceneView> del)
+        {
+            SceneView.duringSceneGui -= del; // sceneView => OnSceneGUI();
+        }
+#else
+        private void RemoveOnSceneGUIDelegate(SceneView.OnSceneFunc del)
+        {
+            SceneView.onSceneGUIDelegate -= del;
+        }
+#endif
+
+
+        private void OnSceneGuiDelegate(SceneView sceneview)
+        {
+            OnSceneGUI();
+        }
+
+        private void FindProperties()
+        {
+            alpha = serializedObject.FindProperty("Alpha");
+            locations = serializedObject.FindProperty("Locations");
+            sceneViewScale = serializedObject.FindProperty("SceneViewScale");
+            splineType = serializedObject.FindProperty("SplineType");
+        }
+
+        void OnDisable()
+        {
+            RemoveOnSceneGUIDelegate(OnSceneGuiDelegate);
+
+            Tools.hidden = false;
+        }
+
+        void DrawOnSceneGui()
+        {
+            FindProperties();
+
+            Handles.BeginGUI();
+
+            GUILayout.BeginArea(new Rect(20, 20, 200, 200));
+
+            var rect = EditorGUILayout.BeginVertical();
+            GUI.color = new Color(1, 1, 1, 0.4f);
+            GUI.Box(rect, GUIContent.none);
+
+            GUI.color = Color.white;
+
+            GUILayout.BeginHorizontal();
+            GUILayout.FlexibleSpace();
+            GUILayout.Label("ARLocation Path");
+            GUILayout.FlexibleSpace();
+            GUILayout.EndHorizontal();
+
+            var style = new GUIStyle
+            {
+                margin = new RectOffset(0, 0, 4, 200)
+            };
+
+            GUILayout.BeginHorizontal(style);
+            GUI.backgroundColor = new Color(0.2f, 0.5f, 0.92f);
+
+            GUILayout.Label("View Scale: ", GUILayout.Width(80.0f));
+
+
+            var newViewScale = GUILayout.HorizontalSlider(sceneViewScale.floatValue, 0.01f, 1.0f);
+
+            if (Math.Abs(newViewScale - sceneViewScale.floatValue) > 0.000001f)
+            {
+                sceneViewScale.floatValue = newViewScale;
+                serializedObject.ApplyModifiedProperties();
+            }
+
+            GUILayout.Label(sceneViewScale.floatValue.ToString("0.00"), GUILayout.Width(32.0f));
+
+
+            GUILayout.EndHorizontal();
+
+            EditorGUILayout.EndVertical();
+
+
+            GUILayout.EndArea();
+            Handles.EndGUI();
+        }
+
+        void OnSceneGUI()
+        {
+            LocationPath locationPath = (LocationPath)target;
+
+            if (locationPath.Locations == null)
+            {
+                return;
+            }
+
+            DrawOnSceneGui();
+            DrawPath();
+        }
+
+        public override void OnInspectorGUI()
+        {
+            serializedObject.Update();
+
+            if (((SplineType)splineType.enumValueIndex) == SplineType.CatmullromSpline)
+            {
+                EditorGUILayout.Slider(alpha, 0, 1, "Curve Alpha");
+            }
+
+            EditorGUILayout.PropertyField(splineType);
+            EditorGUILayout.PropertyField(locations, true);
+
+            serializedObject.ApplyModifiedProperties();
+        }
+
+        void DrawPath()
+        {
+            LocationPath locationPath = (LocationPath)target;
+            var pathLocations = locationPath.Locations;
+
+            if (pathLocations == null || pathLocations.Length < 2)
+            {
+                return;
+            }
+
+            var viewScale = sceneViewScale.floatValue;
+
+            var points = new Vector3[pathLocations.Length];
+
+            for (var i = 0; i < pathLocations.Length; i++)
+            {
+                var loc = pathLocations[i];
+                points[i] = Vector3.Scale(loc.ToVector3(), new Vector3(viewScale, 1, viewScale));
+            }
+
+
+            //var points = curve.SamplePoints(100, p => getVec(p, curve.points[0]));
+            var effScale = (1.0f + Mathf.Cos(viewScale * Mathf.PI / 2 - Mathf.PI));
+            var s = new Vector3(effScale, 1.0f, effScale);
+
+
+            var newCPs = new Vector3[locationPath.Locations.Length];
+            for (var i = 0; i < locationPath.Locations.Length; i++)
+            {
+                // ps.Add(locationPath.locations[i].ToVector3());
+
+                var loc = locationPath.Locations[i];
+                var p = Location.GetGameObjectPositionForLocation(
+                    null,
+                    new Vector3(),
+                   // new Transform(),
+                   pathLocations[0],
+                   pathLocations[i],
+                   true
+                   );
+                Handles.color = Color.blue;
+
+                Handles.SphereHandleCap(i, Vector3.Scale(p, s), Quaternion.identity, 0.4f, EventType.Repaint);
+
+                Vector3 newScaledPos = Handles.PositionHandle(Vector3.Scale(p, s), Quaternion.identity);
+                Vector3 newPos = new Vector3(newScaledPos.x/effScale, newScaledPos.y, newScaledPos.z / effScale);
+
+                Handles.Label(Vector3.Scale(p, s), loc.Label == "" ? ("   Point " + i) : loc.Label);
+                newCPs[i] = Vector3.Scale(p, s);
+            }
+
+            Spline newPath;
+            if (((SplineType)splineType.enumValueIndex) == SplineType.CatmullromSpline)
+            {
+                newPath = new CatmullRomSpline(newCPs, 100, alpha.floatValue);
+            }
+            else
+            {
+                newPath = new LinearSpline(newCPs);
+            }
+
+            var newSample = newPath.SamplePoints(1000);
+
+            for (var i = 0; i < (newSample.Length - 2); i++)
+            {
+                Handles.color = Color.green;
+                Handles.DrawLine(newSample[i + 1], newSample[i]);
+            }
+        }
+    }
+}

+ 11 - 0
Assets/ARLocation/Editor/LocationPathInspector.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 50e7e6d1d7290ee4592af63ab2c860ad
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 64 - 0
Assets/ARLocation/Editor/LocationPropertyDataDrawer.cs

@@ -0,0 +1,64 @@
+using UnityEditor;
+using UnityEngine;
+
+namespace ARLocation
+{
+    [CustomPropertyDrawer(typeof(LocationPropertyData))]
+    public class LocationPropertyDataDrawer : PropertyDrawer
+    {
+        private SerializedProperty type;
+        private SerializedProperty location;
+        private SerializedProperty locationData;
+        private SerializedProperty overrideAltitudeData;
+
+        public void FindSerializedProperties(SerializedProperty property)
+        {
+            type = property.FindPropertyRelative("LocationInputType");
+            location = property.FindPropertyRelative("Location");
+            locationData = property.FindPropertyRelative("LocationData");
+            overrideAltitudeData = property.FindPropertyRelative("OverrideAltitudeData");
+        }
+
+        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
+        {
+            FindSerializedProperties(property);
+
+            var height = EditorGUIUtility.singleLineHeight;
+
+            if (type.enumValueIndex == (int) LocationPropertyData.LocationPropertyType.Location)
+            {
+                height += EditorGUI.GetPropertyHeight(location);
+            }
+            else
+            {
+                height += EditorGUIUtility.singleLineHeight;
+                height += EditorGUI.GetPropertyHeight(overrideAltitudeData, includeChildren: true);
+            }
+
+            return height;
+        }
+
+        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
+        {
+            FindSerializedProperties(property);
+
+            EditorGUI.BeginProperty(position, label, property);
+            EditorGUI.PropertyField(position, type, includeChildren:true);
+
+            position.y += EditorGUIUtility.singleLineHeight;
+
+            if (type.enumValueIndex == (int) LocationPropertyData.LocationPropertyType.Location)
+            {
+                EditorGUI.PropertyField(position, location, includeChildren:true);
+            }
+            else
+            {
+                EditorGUI.PropertyField(position, locationData, includeChildren:true);
+                position.y += EditorGUI.GetPropertyHeight(locationData, includeChildren: true);
+                EditorGUI.PropertyField(position, overrideAltitudeData, includeChildren: true);
+            }
+
+            EditorGUI.EndProperty();
+        }
+    }
+}

+ 11 - 0
Assets/ARLocation/Editor/LocationPropertyDataDrawer.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e74c2c87e30c5fc49b3515cf1025dc7a
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 67 - 0
Assets/ARLocation/Editor/OverrideAltitudeDataDrawer.cs

@@ -0,0 +1,67 @@
+using UnityEngine;
+using UnityEditor;
+
+namespace ARLocation
+{
+    [CustomPropertyDrawer(typeof(OverrideAltitudeData))]
+    public class OverrideAltitudeDataDrawer : PropertyDrawer
+    {
+        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
+        {
+            EditorGUI.BeginProperty(position, label, property);
+
+            var initialRect = EditorGUI.IndentedRect(position); //position;
+
+            position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
+
+
+
+            var indent = EditorGUI.indentLevel;
+            EditorGUI.indentLevel = 0;
+            // EditorGUI.IndentedRect(position);
+
+            float height = 20.0f;
+
+            var boolRect = new Rect(position.x, position.y, 30, height);
+            var altitudeRect = new Rect(position.x, position.y + 20, 180, height);
+            var altitudeLabelRect = new Rect(initialRect.x, position.y + height, 50, height);
+
+            var altitudeModeRect = new Rect(position.x, position.y + (2 * height), 180, height);
+            var altitudeModeLabelRect = new Rect(initialRect.x, position.y + (2 * height), 50, height);
+
+            EditorGUI.PropertyField(boolRect, property.FindPropertyRelative("OverrideAltitude"), GUIContent.none);
+
+            if (property.FindPropertyRelative("OverrideAltitude").boolValue)
+            {
+                var x = new GUIContent();
+                var y = new GUIContent();
+                x.text = "Altitude";
+                EditorGUI.PrefixLabel(altitudeLabelRect, x);
+                // EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
+                EditorGUI.PropertyField(altitudeRect, property.FindPropertyRelative("Altitude"), GUIContent.none);
+
+                y.text = "Altitude Mode";
+                EditorGUI.PrefixLabel(altitudeModeLabelRect, y);
+                EditorGUI.PropertyField(altitudeModeRect, property.FindPropertyRelative("AltitudeMode"), GUIContent.none);
+            }
+
+            EditorGUI.indentLevel = indent;
+
+            EditorGUI.EndProperty();
+        }
+
+        public override float GetPropertyHeight(SerializedProperty property,
+                                               GUIContent label)
+        {
+            if (property.FindPropertyRelative("OverrideAltitude").boolValue)
+            {
+                return base.GetPropertyHeight(property, label) * 2 + 20;
+            }
+            else
+            {
+                return base.GetPropertyHeight(property, label); // * 2 + 20;
+            }
+            // Height is two times the standard height plus 20 pixels
+        }
+    }
+}

+ 11 - 0
Assets/ARLocation/Editor/OverrideAltitudeDataDrawer.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 49642f8f0a2fedd408d8af64073d1fb6
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/ARLocation/Experimental.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ec25786a09bfeed46977f384a6749f27
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 78 - 0
Assets/ARLocation/Experimental/NewPathLineRenderer.cs

@@ -0,0 +1,78 @@
+using UnityEngine;
+
+namespace ARLocation
+{
+    public class NewPathLineRenderer : MonoBehaviour
+    {
+        public LocationPath Path;
+        public int MaxNumberOfUpdates = 4;
+        private ARLocationProvider locationProvider;
+        private LineRenderer lineRenderer;
+        private Transform arLocationRoot;
+        bool initialized;
+        int updateCount;
+
+        void Start()
+        {
+#if UNITY_EDITOR
+            MaxNumberOfUpdates = 1;
+#endif
+        }
+
+        public void Init(LocationPath path, LineRenderer renderer)
+        {
+            Path = path;
+            lineRenderer = renderer;
+
+            arLocationRoot = ARLocationManager.Instance.gameObject.transform;
+
+            initialized = true;
+
+            locationProvider = ARLocationProvider.Instance;
+            locationProvider.OnLocationUpdatedDelegate += locationUpdatedHandler;
+            if (locationProvider.IsEnabled) {
+                locationUpdatedHandler(locationProvider.CurrentLocation, locationProvider.CurrentLocation);
+            }
+        }
+
+        private void locationUpdatedHandler(LocationReading locationReading, LocationReading _)
+        {
+            if (!initialized || updateCount >= MaxNumberOfUpdates)
+            {
+                return;
+            }
+
+            var points = new Vector3[Path.Locations.Length];
+            var cameraTransform = ARLocationManager.Instance.MainCamera.transform;
+            var location = locationReading.ToLocation();
+
+            for (int i = 0; i < points.Length; i++)
+            {
+                var loc = Path.Locations[i];
+                points[i] = Location.GetGameObjectPositionForLocation(arLocationRoot, ARLocationManager.Instance.MainCamera.transform, location, loc,  true);
+                //points[i] = lineRenderer.gameObject.transform.worldToLocalMatrix.MultiplyPoint(points[i]);
+                points[i].y = points[i].z;
+                points[i].z = 0;
+            }
+
+            lineRenderer.useWorldSpace = false;
+            lineRenderer.positionCount = Path.Locations.Length;
+            lineRenderer.SetPositions(points);
+            lineRenderer.alignment = LineAlignment.TransformZ;
+            lineRenderer.gameObject.transform.localRotation = Quaternion.Euler(90, 0, 0);
+
+            updateCount++;
+        }
+
+        void Update()
+        {
+            if (!initialized)
+            {
+                return;
+            }
+
+            lineRenderer.gameObject.transform.localPosition = MathUtils.SetY(lineRenderer.gameObject.transform.localPosition, Camera.main.transform.position.y - 1.5f);
+        }
+
+    }
+}

+ 11 - 0
Assets/ARLocation/Experimental/NewPathLineRenderer.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a248e512e07834b13830c5a39e601552
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/ARLocation/Experimental/World Builder.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 33924ad493fd33d4987b97f962032693
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

文件差異過大導致無法顯示
+ 3138 - 0
Assets/ARLocation/Experimental/World Builder/AR+GPS Location World Builder.unity


+ 7 - 0
Assets/ARLocation/Experimental/World Builder/AR+GPS Location World Builder.unity.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 423d0c8b7cbc90442a84476074b7e313
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 93 - 0
Assets/ARLocation/Experimental/World Builder/Cube.prefab

@@ -0,0 +1,93 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &2255247146297289413
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 8733874244619973945}
+  - component: {fileID: 669208965706171564}
+  - component: {fileID: 7432322451032678468}
+  - component: {fileID: 6371019429550497519}
+  m_Layer: 0
+  m_Name: Cube
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &8733874244619973945
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2255247146297289413}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 618.311, y: 995.1665, z: 244.87703}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!33 &669208965706171564
+MeshFilter:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2255247146297289413}
+  m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!23 &7432322451032678468
+MeshRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2255247146297289413}
+  m_Enabled: 1
+  m_CastShadows: 1
+  m_ReceiveShadows: 1
+  m_DynamicOccludee: 1
+  m_MotionVectors: 1
+  m_LightProbeUsage: 1
+  m_ReflectionProbeUsage: 1
+  m_RenderingLayerMask: 1
+  m_RendererPriority: 0
+  m_Materials:
+  - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
+  m_StaticBatchInfo:
+    firstSubMesh: 0
+    subMeshCount: 0
+  m_StaticBatchRoot: {fileID: 0}
+  m_ProbeAnchor: {fileID: 0}
+  m_LightProbeVolumeOverride: {fileID: 0}
+  m_ScaleInLightmap: 1
+  m_PreserveUVs: 0
+  m_IgnoreNormalsForChartDetection: 0
+  m_ImportantGI: 0
+  m_StitchLightmapSeams: 0
+  m_SelectedEditorRenderState: 3
+  m_MinimumChartSize: 4
+  m_AutoUVMaxDistance: 0.5
+  m_AutoUVMaxAngle: 89
+  m_LightmapParameters: {fileID: 0}
+  m_SortingLayerID: 0
+  m_SortingLayer: 0
+  m_SortingOrder: 0
+--- !u!65 &6371019429550497519
+BoxCollider:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2255247146297289413}
+  m_Material: {fileID: 0}
+  m_IsTrigger: 0
+  m_Enabled: 1
+  serializedVersion: 2
+  m_Size: {x: 1, y: 1, z: 1}
+  m_Center: {x: 0, y: 0, z: 0}

+ 7 - 0
Assets/ARLocation/Experimental/World Builder/Cube.prefab.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 248257bbf3470d245942003997bc15a8
+PrefabImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 94 - 0
Assets/ARLocation/Experimental/World Builder/Cylinder.prefab

@@ -0,0 +1,94 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &1376535175131390911
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1713198093814695061}
+  - component: {fileID: 2527089413613882664}
+  - component: {fileID: 2124265593322491995}
+  - component: {fileID: 5836677287786065492}
+  m_Layer: 0
+  m_Name: Cylinder
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &1713198093814695061
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1376535175131390911}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 618.311, y: 995.1665, z: 244.87703}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!33 &2527089413613882664
+MeshFilter:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1376535175131390911}
+  m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!23 &2124265593322491995
+MeshRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1376535175131390911}
+  m_Enabled: 1
+  m_CastShadows: 1
+  m_ReceiveShadows: 1
+  m_DynamicOccludee: 1
+  m_MotionVectors: 1
+  m_LightProbeUsage: 1
+  m_ReflectionProbeUsage: 1
+  m_RenderingLayerMask: 1
+  m_RendererPriority: 0
+  m_Materials:
+  - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
+  m_StaticBatchInfo:
+    firstSubMesh: 0
+    subMeshCount: 0
+  m_StaticBatchRoot: {fileID: 0}
+  m_ProbeAnchor: {fileID: 0}
+  m_LightProbeVolumeOverride: {fileID: 0}
+  m_ScaleInLightmap: 1
+  m_PreserveUVs: 0
+  m_IgnoreNormalsForChartDetection: 0
+  m_ImportantGI: 0
+  m_StitchLightmapSeams: 0
+  m_SelectedEditorRenderState: 3
+  m_MinimumChartSize: 4
+  m_AutoUVMaxDistance: 0.5
+  m_AutoUVMaxAngle: 89
+  m_LightmapParameters: {fileID: 0}
+  m_SortingLayerID: 0
+  m_SortingLayer: 0
+  m_SortingOrder: 0
+--- !u!136 &5836677287786065492
+CapsuleCollider:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1376535175131390911}
+  m_Material: {fileID: 0}
+  m_IsTrigger: 0
+  m_Enabled: 1
+  m_Radius: 0.5000001
+  m_Height: 2
+  m_Direction: 1
+  m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697}

+ 7 - 0
Assets/ARLocation/Experimental/World Builder/Cylinder.prefab.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 86b5de28eaa2f184895804c75f72fcb8
+PrefabImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 24 - 0
Assets/ARLocation/Experimental/World Builder/PrefabDb.asset

@@ -0,0 +1,24 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 4d58c52ff9f122a49a289c83a1611436, type: 3}
+  m_Name: PrefabDb
+  m_EditorClassIdentifier: 
+  Entries:
+  - MeshId: Cube
+    Prefab: {fileID: 2255247146297289413, guid: 248257bbf3470d245942003997bc15a8,
+      type: 3}
+  - MeshId: Cylinder
+    Prefab: {fileID: 1376535175131390911, guid: 86b5de28eaa2f184895804c75f72fcb8,
+      type: 3}
+  - MeshId: Logo
+    Prefab: {fileID: 2198125378339800612, guid: 987dd04d41b1fcf4a9ed5ade4d053c88,
+      type: 3}

+ 8 - 0
Assets/ARLocation/Experimental/World Builder/PrefabDb.asset.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: fa9d85e79a4b83b46bfc9476f5a185a6
+NativeFormatImporter:
+  externalObjects: {}
+  mainObjectFileID: 11400000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 73 - 0
Assets/ARLocation/Experimental/World Builder/Readme.txt

@@ -0,0 +1,73 @@
+# World Builder Sample Scene
+
+This a sample scene for the "World Builder" feature. This feature is still in
+experimental status, so use it with care!
+
+The basic idea of the "World Builder" is that you can add, place and adjust
+objects at runtime, and save the session so that it persists when the app is
+closed.
+
+This can be used to provide final users to create persistent experiences, or for
+developers to create experiences by manipulating objects "on-site", saving the
+resulting data to be loaded when the final user runs the app.
+
+In this sample, each time the app is closed, the World Session is serialized and
+saved on local storage; and each time opens, it loads the saved session and
+restores it. This is regulated by the "UseLocalStorege" option in the
+"WorldBuilder" component. If this is enabled, the session will be saved in local
+storage to a file named $"{id}.json".  If you disable this option the session
+won't be saved or loaded automatically. In this case, you can use the `ToJson`
+and `FromJson` methods to serialize/deserialize the "World Session" manually.
+That way you can, for instance, save the session on a server via network
+requests, allowing for persistent world sessions in the cloud.
+
+The "World Builder Application Controller" is an implementation of a simple
+application that uses the World Builder to position and adjust objects. It can
+serve as a base for you to modify and customize it to your needs.
+
+This controller has a very simple UI. In the main view, you choose which one of
+the 3 prefabs you want to place in the world. To place them, just touch the
+screen on the location.
+
+After an object is placed, you can select it by touching the object. That will
+change the UI, which will now display buttons for object adjustment; you can
+adjust the y-axis rotation by dragging horizontally, move the object to another
+location by touching the screen, or change its height by dragging vertically.
+
+# Using a Web Server 
+
+As it is, the scene is fully usable, and the session will be persistent via
+local storage. 
+
+There is support for primitive server/network persistency in the
+`WorldBuilderApplicationController`. To use it, check the "Save To Server"
+option, and set the URLs for the save and load endpoints.
+
+There is an example server in this repository: https://github.com/dmbfm/unity-ar-gps-location-world-builder-server
+
+To use it on the field, you need to set up a live server running this as https.
+
+To test it locally, clone the repository, run:
+
+> npm install
+> npm start
+
+That will start a server on `http://localhost:3000` by default, but you can
+change the hostname and port by editing the `server.js` file. 
+
+But you also need to tunell this server to a https endpoint. The easiest way to
+do that is to use ngrok (https://ngrok.com/). After downloading and settinup
+ngrok according to their instructions, run:
+
+> ngrok http 3000
+
+And that should create a tunnell with an adress like
+'https://{some_id}.ngrok.io'. Then all you need to do is set "Save World URL"
+to:
+
+'https://{some_id}.ngrok.io/save/' 
+
+and "Restore World URL" to 
+
+'https://{some_id}.ngrok.io/world/' 
+

+ 7 - 0
Assets/ARLocation/Experimental/World Builder/Readme.txt.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 8d53295e2c23a13459385f620b102663
+TextScriptImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 200 - 0
Assets/ARLocation/Experimental/World Builder/WorldBuilder.cs

@@ -0,0 +1,200 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace ARLocation
+{
+    public class WorldBuilder : MonoBehaviour
+    {
+        public PrefabDatabase PrefabDatabase;
+        public string Id = "World";
+        public bool UseLocalStorage;
+
+        [System.Serializable]
+        public class Entry
+        {
+            public Location Location;
+            public float Rotation;
+            public string MeshId;
+
+            [System.NonSerialized]
+            public GameObject Instance;
+        }
+
+        [System.Serializable]
+        public class World
+        {
+            public List<Entry> Entries = new List<Entry>();
+        }
+
+        class State
+        {
+            public World World = new World();
+        }
+
+        private readonly State state = new State();
+
+        public World GetWorld()
+        {
+            return state.World;
+        }
+
+        private bool initialized;
+
+        public bool Initialized => initialized;
+
+        IEnumerator Start()
+        {
+            yield return StartCoroutine(WaitForLocationServices());
+
+            if (UseLocalStorage)
+            {
+                RestoreWorldFromLocalStorage();
+            }
+
+            initialized = true;
+        }
+
+        IEnumerator WaitForLocationServices()
+        {
+            while (!ARLocationProvider.Instance.IsEnabled)
+            {
+                yield return new WaitForSeconds(0.1f);
+            }
+        }
+
+        public void AddEntry(string meshId, Vector3 worldPosition, float rotation = 0)
+        {
+            var location = ARLocationManager.Instance.GetLocationForWorldPosition(worldPosition);
+            var entry = new Entry { Location = location, MeshId = meshId, Rotation = rotation };
+            state.World.Entries.Add(entry);
+            PlaceEntryAtLocation(entry);
+        }
+
+        void OnDestroy()
+        {
+            SaveWorld();
+        }
+
+        void OnApplicationPause(bool pause)
+        {
+            if (pause) SaveWorld();
+        }
+
+        void PlaceWorld()
+        {
+            state.World.Entries.ForEach(PlaceEntryAtLocation);
+        }
+
+        void PlaceEntryAtLocation(Entry entry)
+        {
+            var prefab = PrefabDatabase.GetEntryById(entry.MeshId);
+
+            if (prefab == null)
+            {
+                Debug.LogWarning($"Invalid prefab '{entry.MeshId}'");
+                return;
+            }
+
+            var location = entry.Location;
+            var options = new PlaceAtLocation.PlaceAtOptions { };
+
+            entry.Instance = PlaceAtLocation.CreatePlacedInstance(prefab, location, options, false);
+            entry.Instance.transform.localEulerAngles = new Vector3(0, entry.Rotation, 0);
+        }
+
+        public string ToJson()
+        {
+            return JsonUtility.ToJson(state.World);
+        }
+
+        public void FromJson(string json)
+        {
+            ClearWorld();
+            state.World = JsonUtility.FromJson<World>(json);
+            PlaceWorld();
+        }
+
+        string GetJsonFilename()
+        {
+            var s = Id.Trim();
+
+            if (s == "") s = "World";
+
+            return Application.persistentDataPath + "/" + s + ".json";
+        }
+
+        public void SaveWorld()
+        {
+            if (!UseLocalStorage) return;
+
+            string json = JsonUtility.ToJson(state.World);
+            Debug.Log(json);
+
+            try
+            {
+                System.IO.File.WriteAllText(GetJsonFilename(), json);
+            }
+            catch
+            {
+                Debug.Log("[ARLocation::WorldBuilder::SaveWorld]: Failed to open json file for writing.");
+                return;
+            }
+
+            Debug.Log($"Written to json file '{GetJsonFilename()}'");
+        }
+
+        public void RestoreWorldFromLocalStorage()
+        {
+            if (!UseLocalStorage) return;
+
+            string json = "";
+            try
+            {
+                json = System.IO.File.ReadAllText(GetJsonFilename(), System.Text.Encoding.UTF8);
+            }
+            catch
+            {
+                Debug.Log("[ARLocation::WorldBuilder::RestoreWorld]: Failed to open json file for reading.");
+                return;
+            }
+
+            state.World = JsonUtility.FromJson<World>(json);
+            PlaceWorld();
+            Debug.Log($"Restored world from json file '{GetJsonFilename()}'");
+        }
+
+        public void ClearWorld()
+        {
+            state.World.Entries.ForEach(e => {
+                if (e.Instance != null)
+                {
+                    Destroy(e.Instance);
+                }
+            });
+            state.World = new World();
+        }
+
+        internal void MoveEntry(Entry entry, Vector3 point)
+        {
+            var location = ARLocationManager.Instance.GetLocationForWorldPosition(point);
+            entry.Location = location;
+
+            if (entry.Instance != null)
+            {
+                var placeAt = entry.Instance.GetComponent<PlaceAtLocation>();
+
+                if (placeAt != null)
+                {
+                    placeAt.Location = location;
+                }
+            }
+        }
+
+        public void RemoveEntry(Entry entry)
+        {
+            Destroy(entry.Instance);
+            state.World.Entries.Remove(entry);
+        }
+    }
+}

+ 11 - 0
Assets/ARLocation/Experimental/World Builder/WorldBuilder.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f479d71801b9c5043b03045000acdbd4
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 417 - 0
Assets/ARLocation/Experimental/World Builder/WorldBuilderApplicationController.cs

@@ -0,0 +1,417 @@
+using System.Text;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Networking;
+using UnityEngine.UI;
+using UnityEngine.XR.ARFoundation;
+
+namespace ARLocation
+{
+    [RequireComponent(typeof(WorldBuilder))]
+    public class WorldBuilderApplicationController : MonoBehaviour
+    {
+        [System.Serializable]
+        public class UiElementsSettings
+        {
+            public Button CubeBtn;
+            public Button CylinderBtn;
+            public Button LogoBtn;
+            public Button MoveBtn;
+            public Button RotateBtn;
+            public Button DeselectBtn;
+            public Button ClearWorldBtn;
+            public Button HeightBtn;
+            public Button DeleteObjectBtn;
+            public Text DebugText;
+        }
+
+        [System.Serializable]
+        public class RaycastMarginSettings
+        {
+            public float Top;
+            public float Bottom;
+            public float Left;
+            public float Right;
+        }
+
+        [System.Serializable]
+        public class GeneralSettings
+        {
+            public float HeightAdjustmentSensitivity = 0.25f;
+            public float RotationAdjustmentSensitivity = 1.0f;
+            public string SaveWorldUrl;
+            public string RestoreWorldUrl;
+            public bool SaveToServer;
+        }
+
+        public UiElementsSettings UiElements;
+        public RaycastMarginSettings RaycastMargins;
+        public GeneralSettings Settings;
+
+        private WorldBuilder worldBuilder;
+        private PlaceAtLocation selectedObject;
+        private WorldBuilder.Entry selectedObjectEntry;
+
+        enum AppState
+        {
+            PlacementMode,
+            MoveMode,
+            RotateMode,
+            HeightMode,
+            IdleMode
+        };
+
+        class State
+        {
+            public string CurrentMeshId;
+            public AppState AppState;
+        }
+
+        private readonly State state = new State();
+
+        private void Awake()
+        {
+            worldBuilder = GetComponent<WorldBuilder>();
+
+            if (Settings.SaveToServer)
+            {
+                worldBuilder.UseLocalStorage = false;
+            }
+
+            Debug.Assert(worldBuilder != null);
+            Debug.Assert(worldBuilder.PrefabDatabase.Entries.Count > 0);
+
+            state.CurrentMeshId = "Cube";
+            UiElements.CubeBtn.image.color = UiElements.CubeBtn.colors.pressedColor;
+
+            SetObjectSelectedUIVisible(false);
+
+            InitListeners();
+        }
+
+        IEnumerator Start()
+        {
+            if (Settings.SaveToServer)
+            {
+
+                while (!worldBuilder.Initialized)
+                {
+                    yield return new WaitForSeconds(0.1f);
+                }
+
+                yield return RestoreWorldFromServer();
+            }
+        }
+
+        IEnumerator RestoreWorldFromServer()
+        {
+            var request = UnityWebRequest.Get($"{Settings.RestoreWorldUrl}{worldBuilder.Id}");
+
+            yield return request.SendWebRequest();
+
+            if (Utils.Misc.WebRequestResultIsError(request))
+            {
+                Debug.Log("Failed to restore world from server!");
+                yield break;
+            }
+
+            Debug.Log(request.downloadHandler.text);
+            Debug.Log(request.responseCode);
+            worldBuilder.FromJson(request.downloadHandler.text);
+        }
+
+        IEnumerator SaveWorldToServer()
+        {
+            var request = new UnityWebRequest($"{Settings.SaveWorldUrl}{worldBuilder.Id}", "POST");
+            byte[] bodyRaw = Encoding.UTF8.GetBytes(worldBuilder.ToJson());
+            request.uploadHandler = (UploadHandler) new UploadHandlerRaw(bodyRaw);
+            request.downloadHandler = (DownloadHandler) new DownloadHandlerBuffer();
+            request.SetRequestHeader("Content-Type", "application/json");
+
+            yield return request.SendWebRequest();
+
+            if (Utils.Misc.WebRequestResultIsError(request))
+            {
+                Debug.LogWarning("Failed to save to server!");
+            }
+
+        }
+
+        void SetObjectSelectedUIVisible(bool visible)
+        {
+            UiElements.MoveBtn.gameObject.SetActive(visible);
+            UiElements.RotateBtn.gameObject.SetActive(visible);
+            UiElements.DeselectBtn.gameObject.SetActive(visible);
+            UiElements.HeightBtn.gameObject.SetActive(visible);
+            UiElements.DeleteObjectBtn.gameObject.SetActive(visible);
+
+            UiElements.CubeBtn.gameObject.SetActive(!visible);
+            UiElements.CylinderBtn.gameObject.SetActive(!visible);
+            UiElements.LogoBtn.gameObject.SetActive(!visible);
+            UiElements.ClearWorldBtn.gameObject.SetActive(!visible);
+        }
+
+        void SetMoveMode()
+        {
+            UiElements.MoveBtn.image.color = UiElements.MoveBtn.colors.pressedColor;
+            UiElements.RotateBtn.image.color = UiElements.MoveBtn.colors.normalColor;
+            UiElements.DeselectBtn.image.color = UiElements.MoveBtn.colors.normalColor;
+            UiElements.HeightBtn.image.color = UiElements.MoveBtn.colors.normalColor;
+            state.AppState = AppState.MoveMode;
+        }
+
+        void SetRotateMode()
+        {
+            UiElements.MoveBtn.image.color = UiElements.MoveBtn.colors.normalColor;
+            UiElements.RotateBtn.image.color = UiElements.MoveBtn.colors.pressedColor;
+            UiElements.DeselectBtn.image.color = UiElements.MoveBtn.colors.normalColor;
+            UiElements.HeightBtn.image.color = UiElements.MoveBtn.colors.normalColor;
+            state.AppState = AppState.RotateMode;
+        }
+
+        private void SetHeightMode()
+        {
+            UiElements.MoveBtn.image.color = UiElements.MoveBtn.colors.normalColor;
+            UiElements.RotateBtn.image.color = UiElements.MoveBtn.colors.normalColor;
+            UiElements.DeselectBtn.image.color = UiElements.MoveBtn.colors.normalColor;
+            UiElements.HeightBtn.image.color = UiElements.MoveBtn.colors.pressedColor;
+            state.AppState = AppState.HeightMode;
+        }
+
+        void InitListeners()
+        {
+            UiElements.ClearWorldBtn.onClick.AddListener(() =>
+            {
+                worldBuilder.ClearWorld();
+                SetObjectSelectedUIVisible(false);
+                state.AppState = AppState.PlacementMode;
+            });
+            UiElements.CubeBtn.onClick.AddListener(() =>
+            {
+                UiElements.CubeBtn.image.color = UiElements.CubeBtn.colors.pressedColor;
+                UiElements.CylinderBtn.image.color = UiElements.CylinderBtn.colors.normalColor;
+                UiElements.LogoBtn.image.color = UiElements.LogoBtn.colors.normalColor;
+                state.CurrentMeshId = "Cube";
+            });
+
+            UiElements.CylinderBtn.onClick.AddListener(() =>
+            {
+                UiElements.CubeBtn.image.color = UiElements.CubeBtn.colors.normalColor;
+                UiElements.CylinderBtn.image.color = UiElements.CylinderBtn.colors.pressedColor;
+                UiElements.LogoBtn.image.color = UiElements.LogoBtn.colors.normalColor;
+                state.CurrentMeshId = "Cylinder";
+            });
+
+            UiElements.LogoBtn.onClick.AddListener(() =>
+            {
+                UiElements.CubeBtn.image.color = UiElements.CubeBtn.colors.normalColor;
+                UiElements.CylinderBtn.image.color = UiElements.CylinderBtn.colors.normalColor;
+                UiElements.LogoBtn.image.color = UiElements.LogoBtn.colors.pressedColor;
+                state.CurrentMeshId = "Logo";
+            });
+
+            UiElements.DeselectBtn.onClick.AddListener(() =>
+            {
+                state.CurrentMeshId = "Cube";
+                UiElements.CubeBtn.image.color = UiElements.CubeBtn.colors.pressedColor;
+                UiElements.CylinderBtn.image.color = UiElements.CylinderBtn.colors.normalColor;
+                UiElements.LogoBtn.image.color = UiElements.LogoBtn.colors.normalColor;
+                state.AppState = AppState.PlacementMode;
+                SetObjectSelectedUIVisible(false);
+                selectedObjectEntry = null;
+            });
+
+            UiElements.RotateBtn.onClick.AddListener(() =>
+            {
+                SetRotateMode();
+            });
+
+            UiElements.MoveBtn.onClick.AddListener(() =>
+            {
+                SetMoveMode();
+            });
+
+            UiElements.HeightBtn.onClick.AddListener(() =>
+            {
+                SetHeightMode();
+            });
+
+            UiElements.DeleteObjectBtn.onClick.AddListener(() =>
+            {
+                worldBuilder.RemoveEntry(selectedObjectEntry);
+            });
+        }
+
+        void DebugOutput(string text)
+        {
+            if (UiElements.DebugText)
+            {
+                UiElements.DebugText.text = text;
+            }
+        }
+
+        void Update()
+        {
+            DebugOutput($" c = {ARLocationManager.Instance.MainCamera.transform.position}");
+            if (Input.touchCount == 1)
+            {
+                var touch = Input.touches[0];
+
+                if (state.AppState == AppState.RotateMode)
+                {
+                    if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary)
+                    {
+                        float dx = Settings.RotationAdjustmentSensitivity * (180.0f / Mathf.PI) * touch.deltaPosition.x / Screen.width;
+
+                        DebugOutput($"dx = {dx}");
+
+                        if (selectedObjectEntry != null && selectedObjectEntry.Instance != null)
+                        {
+                            var euler = selectedObjectEntry.Instance.transform.localEulerAngles;
+                            selectedObjectEntry.Rotation = euler.y + dx;
+                            selectedObjectEntry.Instance.transform.localEulerAngles = new Vector3(euler.x, selectedObjectEntry.Rotation, euler.z);
+                        }
+                    }
+                    return;
+                }
+                else if (state.AppState == AppState.HeightMode)
+                {
+                    if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary)
+                    {
+                        float dy = Settings.HeightAdjustmentSensitivity * (180.0f / Mathf.PI) * touch.deltaPosition.y / Screen.height;
+
+                        DebugOutput($"dy = {dy}");
+
+                        if (selectedObjectEntry != null && selectedObjectEntry.Instance != null)
+                        {
+                            var Location = selectedObjectEntry.Instance.GetComponent<PlaceAtLocation>().Location.Clone();
+                            Location.Altitude += dy;
+                            selectedObjectEntry.Location.Altitude += dy;
+                            selectedObjectEntry.Instance.GetComponent<PlaceAtLocation>().Location = Location;
+                        }
+                    }
+                    return;
+                }
+                else if (touch.phase == TouchPhase.Began)
+                {
+                    if (UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject(0)) return;
+
+                    OnTouchOrClick(touch.position);
+                }
+            }
+
+            if (Application.isEditor && Input.GetMouseButtonDown(0))
+            {
+                OnTouchOrClick(Input.mousePosition);
+            }
+        }
+
+        private void OnTouchOrClick(Vector2 p)
+        {
+            float x = p.x / Screen.width;
+            float y = p.y / Screen.height;
+
+            if (x < RaycastMargins.Left || x > (1 - RaycastMargins.Right)) return;
+            if (y < RaycastMargins.Bottom || y > (1 - RaycastMargins.Top)) return;
+
+            var camera = Application.isEditor ? Camera.main : ARLocationManager.Instance.MainCamera;
+            var ray = camera.ScreenPointToRay(p);
+
+
+            if (state.AppState == AppState.PlacementMode)
+            {
+                RaycastHit hit;
+                if (Physics.Raycast(ray, out hit))
+                {
+                    GameObject go = null;
+                    WorldBuilder.Entry entry = null;
+                    var o = hit.collider.transform;
+                    while (o.parent)
+                    {
+                        Debug.Log(o.name);
+                        entry = worldBuilder.GetWorld().Entries.Find(e => e.Instance == o.gameObject);
+
+                        if (entry != null)
+                        {
+                            go = entry.Instance;
+                            break;
+                        }
+
+                        o = o.parent;
+                    }
+
+                    if (go != null && entry != null)
+                    {
+                        selectedObjectEntry = entry;
+                        SetObjectSelectedUIVisible(true);
+                        SetMoveMode();
+                        return;
+                    }
+                }
+            }
+
+            float enter;
+            if (RaycastGround(ray, out enter))
+            {
+                var point = ray.GetPoint(enter);
+                switch (state.AppState)
+                {
+                    case AppState.PlacementMode:
+                        OnPlacementRaycast(point);
+                        break;
+
+                    case AppState.MoveMode:
+                        OnMoveModeRaycast(point);
+                        break;
+                }
+            }
+        }
+
+        private bool RaycastGround(Ray ray, out float t)
+        {
+            var arRaycastManager = FindObjectOfType<ARRaycastManager>();
+
+            if (Application.isEditor || arRaycastManager == null)
+            {
+                var camera = Application.isEditor ? Camera.main : ARLocationManager.Instance.MainCamera;
+                var plane = new Plane(new Vector3(0, 1, 0), camera.transform.position - new Vector3(0, 1.4f, 0));
+                return plane.Raycast(ray, out t);
+            }
+            else
+            {
+                List<ARRaycastHit> hits = new List<ARRaycastHit>();
+                arRaycastManager.Raycast(ray, hits, trackableTypes: UnityEngine.XR.ARSubsystems.TrackableType.PlaneWithinInfinity);
+
+                if (hits.Count > 0)
+                {
+                    t = hits[0].distance;
+                    return true;
+                }
+                else
+                {
+                    var camera = Application.isEditor ? Camera.main : ARLocationManager.Instance.MainCamera;
+                    var plane = new Plane(new Vector3(0, 1, 0), camera.transform.position - new Vector3(0, 1.4f, 0));
+                    return plane.Raycast(ray, out t);
+                }
+            }
+        }
+
+        private void OnMoveModeRaycast(Vector3 point)
+        {
+            worldBuilder.MoveEntry(selectedObjectEntry, point);
+        }
+
+        private void OnPlacementRaycast(Vector3 v)
+        {
+            Debug.Log("ok!");
+            worldBuilder.AddEntry(state.CurrentMeshId, v);
+
+            if (Settings.SaveToServer)
+            {
+                Debug.Log("ok2!");
+                StartCoroutine(SaveWorldToServer());
+            }
+        }
+    }
+}

+ 11 - 0
Assets/ARLocation/Experimental/World Builder/WorldBuilderApplicationController.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 50f8b463f98b13b4cb5daec613f68e18
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/ARLocation/Experimental/World Voxel Craft.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1f0c77335222ca24c8ca032ef4ea63d8
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

文件差異過大導致無法顯示
+ 2278 - 0
Assets/ARLocation/Experimental/World Voxel Craft/AR+GPS Location World Voxel.unity


+ 7 - 0
Assets/ARLocation/Experimental/World Voxel Craft/AR+GPS Location World Voxel.unity.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 1dda82d1016d23e459e52374ececdccf
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

文件差異過大導致無法顯示
+ 4758 - 0
Assets/ARLocation/Experimental/World Voxel Craft/Brick Particle System.prefab


+ 7 - 0
Assets/ARLocation/Experimental/World Voxel Craft/Brick Particle System.prefab.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: b816ddb2078d3e54fad239e0c1e1a8bb
+PrefabImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

二進制
Assets/ARLocation/Experimental/World Voxel Craft/Brick.wav


+ 22 - 0
Assets/ARLocation/Experimental/World Voxel Craft/Brick.wav.meta

@@ -0,0 +1,22 @@
+fileFormatVersion: 2
+guid: 03883e2c65cefd34e8ef1da948e77664
+AudioImporter:
+  externalObjects: {}
+  serializedVersion: 6
+  defaultSettings:
+    loadType: 0
+    sampleRateSetting: 0
+    sampleRateOverride: 44100
+    compressionFormat: 1
+    quality: 1
+    conversionMode: 0
+  platformSettingOverrides: {}
+  forceToMono: 0
+  normalize: 1
+  preloadAudioData: 1
+  loadInBackground: 0
+  ambisonic: 0
+  3D: 1
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 94 - 0
Assets/ARLocation/Experimental/World Voxel Craft/Chunk Plane.prefab

@@ -0,0 +1,94 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &844942035423891054
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 844942035423891042}
+  - component: {fileID: 844942035423891053}
+  - component: {fileID: 844942035423891052}
+  - component: {fileID: 844942035423891055}
+  m_Layer: 0
+  m_Name: Chunk Plane
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &844942035423891042
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 844942035423891054}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!33 &844942035423891053
+MeshFilter:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 844942035423891054}
+  m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!23 &844942035423891052
+MeshRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 844942035423891054}
+  m_Enabled: 1
+  m_CastShadows: 1
+  m_ReceiveShadows: 1
+  m_DynamicOccludee: 1
+  m_MotionVectors: 1
+  m_LightProbeUsage: 1
+  m_ReflectionProbeUsage: 1
+  m_RenderingLayerMask: 1
+  m_RendererPriority: 0
+  m_Materials:
+  - {fileID: 2100000, guid: 3897f83d1466f9b448527fb1370119a1, type: 2}
+  m_StaticBatchInfo:
+    firstSubMesh: 0
+    subMeshCount: 0
+  m_StaticBatchRoot: {fileID: 0}
+  m_ProbeAnchor: {fileID: 0}
+  m_LightProbeVolumeOverride: {fileID: 0}
+  m_ScaleInLightmap: 1
+  m_PreserveUVs: 0
+  m_IgnoreNormalsForChartDetection: 0
+  m_ImportantGI: 0
+  m_StitchLightmapSeams: 0
+  m_SelectedEditorRenderState: 3
+  m_MinimumChartSize: 4
+  m_AutoUVMaxDistance: 0.5
+  m_AutoUVMaxAngle: 89
+  m_LightmapParameters: {fileID: 0}
+  m_SortingLayerID: 0
+  m_SortingLayer: 0
+  m_SortingOrder: 0
+--- !u!64 &844942035423891055
+MeshCollider:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 844942035423891054}
+  m_Material: {fileID: 0}
+  m_IsTrigger: 0
+  m_Enabled: 1
+  serializedVersion: 3
+  m_Convex: 0
+  m_CookingOptions: 14
+  m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0}

+ 7 - 0
Assets/ARLocation/Experimental/World Voxel Craft/Chunk Plane.prefab.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 32ad66e8dcd76944c8cdeb69ceb8f6ca
+PrefabImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 78 - 0
Assets/ARLocation/Experimental/World Voxel Craft/ChunkIndicator.mat

@@ -0,0 +1,78 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!21 &2100000
+Material:
+  serializedVersion: 6
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_Name: ChunkIndicator
+  m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
+  m_ShaderKeywords: _ALPHAPREMULTIPLY_ON
+  m_LightmapFlags: 4
+  m_EnableInstancingVariants: 0
+  m_DoubleSidedGI: 0
+  m_CustomRenderQueue: 3000
+  stringTagMap:
+    RenderType: Transparent
+  disabledShaderPasses: []
+  m_SavedProperties:
+    serializedVersion: 3
+    m_TexEnvs:
+    - _BumpMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailAlbedoMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailMask:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailNormalMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _EmissionMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _MainTex:
+        m_Texture: {fileID: 2800000, guid: 11776792d1743954d9350ae1c1e2930c, type: 3}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _MetallicGlossMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _OcclusionMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _ParallaxMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    m_Floats:
+    - _BumpScale: 1
+    - _Cutoff: 0.5
+    - _DetailNormalMapScale: 1
+    - _DstBlend: 10
+    - _GlossMapScale: 1
+    - _Glossiness: 0
+    - _GlossyReflections: 1
+    - _Metallic: 0
+    - _Mode: 3
+    - _OcclusionStrength: 1
+    - _Parallax: 0.02
+    - _SmoothnessTextureChannel: 0
+    - _SpecularHighlights: 1
+    - _SrcBlend: 1
+    - _UVSec: 0
+    - _ZWrite: 0
+    m_Colors:
+    - _Color: {r: 1, g: 1, b: 1, a: 0.078431375}
+    - _EmissionColor: {r: 1, g: 1, b: 1, a: 1}

+ 8 - 0
Assets/ARLocation/Experimental/World Voxel Craft/ChunkIndicator.mat.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3897f83d1466f9b448527fb1370119a1
+NativeFormatImporter:
+  externalObjects: {}
+  mainObjectFileID: 2100000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 93 - 0
Assets/ARLocation/Experimental/World Voxel Craft/CubeBrick.prefab

@@ -0,0 +1,93 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &2610591546250173276
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 2610591546250173216}
+  - component: {fileID: 2610591546250173219}
+  - component: {fileID: 2610591546250173218}
+  - component: {fileID: 2610591546250173277}
+  m_Layer: 0
+  m_Name: CubeBrick
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &2610591546250173216
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2610591546250173276}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!33 &2610591546250173219
+MeshFilter:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2610591546250173276}
+  m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!23 &2610591546250173218
+MeshRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2610591546250173276}
+  m_Enabled: 1
+  m_CastShadows: 1
+  m_ReceiveShadows: 1
+  m_DynamicOccludee: 1
+  m_MotionVectors: 1
+  m_LightProbeUsage: 1
+  m_ReflectionProbeUsage: 1
+  m_RenderingLayerMask: 1
+  m_RendererPriority: 0
+  m_Materials:
+  - {fileID: 2100000, guid: 8197d0f2c5b22e34cb961867c6b0bb89, type: 2}
+  m_StaticBatchInfo:
+    firstSubMesh: 0
+    subMeshCount: 0
+  m_StaticBatchRoot: {fileID: 0}
+  m_ProbeAnchor: {fileID: 0}
+  m_LightProbeVolumeOverride: {fileID: 0}
+  m_ScaleInLightmap: 1
+  m_PreserveUVs: 0
+  m_IgnoreNormalsForChartDetection: 0
+  m_ImportantGI: 0
+  m_StitchLightmapSeams: 0
+  m_SelectedEditorRenderState: 3
+  m_MinimumChartSize: 4
+  m_AutoUVMaxDistance: 0.5
+  m_AutoUVMaxAngle: 89
+  m_LightmapParameters: {fileID: 0}
+  m_SortingLayerID: 0
+  m_SortingLayer: 0
+  m_SortingOrder: 0
+--- !u!65 &2610591546250173277
+BoxCollider:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2610591546250173276}
+  m_Material: {fileID: 0}
+  m_IsTrigger: 0
+  m_Enabled: 1
+  serializedVersion: 2
+  m_Size: {x: 1, y: 1, z: 1}
+  m_Center: {x: 0, y: 0, z: 0}

+ 7 - 0
Assets/ARLocation/Experimental/World Voxel Craft/CubeBrick.prefab.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: ea1041d6d459b1244a69e945813b0067
+PrefabImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 77 - 0
Assets/ARLocation/Experimental/World Voxel Craft/CubeBrickMaterial.mat

@@ -0,0 +1,77 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!21 &2100000
+Material:
+  serializedVersion: 6
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_Name: CubeBrickMaterial
+  m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
+  m_ShaderKeywords: _GLOSSYREFLECTIONS_OFF _SPECULARHIGHLIGHTS_OFF
+  m_LightmapFlags: 4
+  m_EnableInstancingVariants: 0
+  m_DoubleSidedGI: 0
+  m_CustomRenderQueue: -1
+  stringTagMap: {}
+  disabledShaderPasses: []
+  m_SavedProperties:
+    serializedVersion: 3
+    m_TexEnvs:
+    - _BumpMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailAlbedoMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailMask:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailNormalMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _EmissionMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _MainTex:
+        m_Texture: {fileID: 2800000, guid: 1c79c11d09b36a24d819377072e7bc9c, type: 3}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _MetallicGlossMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _OcclusionMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _ParallaxMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    m_Floats:
+    - _BumpScale: 1
+    - _Cutoff: 0.5
+    - _DetailNormalMapScale: 1
+    - _DstBlend: 0
+    - _GlossMapScale: 1
+    - _Glossiness: 0
+    - _GlossyReflections: 0
+    - _Metallic: 0
+    - _Mode: 0
+    - _OcclusionStrength: 1
+    - _Parallax: 0.02
+    - _SmoothnessTextureChannel: 0
+    - _SpecularHighlights: 0
+    - _SrcBlend: 1
+    - _UVSec: 0
+    - _ZWrite: 1
+    m_Colors:
+    - _Color: {r: 1, g: 1, b: 1, a: 1}
+    - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}

+ 8 - 0
Assets/ARLocation/Experimental/World Voxel Craft/CubeBrickMaterial.mat.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 8197d0f2c5b22e34cb961867c6b0bb89
+NativeFormatImporter:
+  externalObjects: {}
+  mainObjectFileID: 2100000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 93 - 0
Assets/ARLocation/Experimental/World Voxel Craft/CubeGold.prefab

@@ -0,0 +1,93 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &2610591546250173276
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 2610591546250173216}
+  - component: {fileID: 2610591546250173219}
+  - component: {fileID: 2610591546250173218}
+  - component: {fileID: 2610591546250173277}
+  m_Layer: 0
+  m_Name: CubeGold
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &2610591546250173216
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2610591546250173276}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!33 &2610591546250173219
+MeshFilter:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2610591546250173276}
+  m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!23 &2610591546250173218
+MeshRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2610591546250173276}
+  m_Enabled: 1
+  m_CastShadows: 1
+  m_ReceiveShadows: 1
+  m_DynamicOccludee: 1
+  m_MotionVectors: 1
+  m_LightProbeUsage: 1
+  m_ReflectionProbeUsage: 1
+  m_RenderingLayerMask: 1
+  m_RendererPriority: 0
+  m_Materials:
+  - {fileID: 2100000, guid: 3cfa752b2bcf5294fa9eb0c995228478, type: 2}
+  m_StaticBatchInfo:
+    firstSubMesh: 0
+    subMeshCount: 0
+  m_StaticBatchRoot: {fileID: 0}
+  m_ProbeAnchor: {fileID: 0}
+  m_LightProbeVolumeOverride: {fileID: 0}
+  m_ScaleInLightmap: 1
+  m_PreserveUVs: 0
+  m_IgnoreNormalsForChartDetection: 0
+  m_ImportantGI: 0
+  m_StitchLightmapSeams: 0
+  m_SelectedEditorRenderState: 3
+  m_MinimumChartSize: 4
+  m_AutoUVMaxDistance: 0.5
+  m_AutoUVMaxAngle: 89
+  m_LightmapParameters: {fileID: 0}
+  m_SortingLayerID: 0
+  m_SortingLayer: 0
+  m_SortingOrder: 0
+--- !u!65 &2610591546250173277
+BoxCollider:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2610591546250173276}
+  m_Material: {fileID: 0}
+  m_IsTrigger: 0
+  m_Enabled: 1
+  serializedVersion: 2
+  m_Size: {x: 1, y: 1, z: 1}
+  m_Center: {x: 0, y: 0, z: 0}

+ 7 - 0
Assets/ARLocation/Experimental/World Voxel Craft/CubeGold.prefab.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: edc88edd49b83984dbbc688e401d189a
+PrefabImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 77 - 0
Assets/ARLocation/Experimental/World Voxel Craft/CubeGoldMaterial.mat

@@ -0,0 +1,77 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!21 &2100000
+Material:
+  serializedVersion: 6
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_Name: CubeGoldMaterial
+  m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
+  m_ShaderKeywords: _GLOSSYREFLECTIONS_OFF _SPECULARHIGHLIGHTS_OFF
+  m_LightmapFlags: 4
+  m_EnableInstancingVariants: 0
+  m_DoubleSidedGI: 0
+  m_CustomRenderQueue: -1
+  stringTagMap: {}
+  disabledShaderPasses: []
+  m_SavedProperties:
+    serializedVersion: 3
+    m_TexEnvs:
+    - _BumpMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailAlbedoMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailMask:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailNormalMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _EmissionMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _MainTex:
+        m_Texture: {fileID: 2800000, guid: edc435636172e4b40a67e70d301be0cf, type: 3}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _MetallicGlossMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _OcclusionMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _ParallaxMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    m_Floats:
+    - _BumpScale: 1
+    - _Cutoff: 0.5
+    - _DetailNormalMapScale: 1
+    - _DstBlend: 0
+    - _GlossMapScale: 1
+    - _Glossiness: 0
+    - _GlossyReflections: 0
+    - _Metallic: 0
+    - _Mode: 0
+    - _OcclusionStrength: 1
+    - _Parallax: 0.02
+    - _SmoothnessTextureChannel: 0
+    - _SpecularHighlights: 0
+    - _SrcBlend: 1
+    - _UVSec: 0
+    - _ZWrite: 1
+    m_Colors:
+    - _Color: {r: 1, g: 1, b: 1, a: 1}
+    - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}

+ 8 - 0
Assets/ARLocation/Experimental/World Voxel Craft/CubeGoldMaterial.mat.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3cfa752b2bcf5294fa9eb0c995228478
+NativeFormatImporter:
+  externalObjects: {}
+  mainObjectFileID: 2100000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 93 - 0
Assets/ARLocation/Experimental/World Voxel Craft/CubeStone.prefab

@@ -0,0 +1,93 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &2610591546250173276
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 2610591546250173216}
+  - component: {fileID: 2610591546250173219}
+  - component: {fileID: 2610591546250173218}
+  - component: {fileID: 2610591546250173277}
+  m_Layer: 0
+  m_Name: CubeStone
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &2610591546250173216
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2610591546250173276}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!33 &2610591546250173219
+MeshFilter:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2610591546250173276}
+  m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!23 &2610591546250173218
+MeshRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2610591546250173276}
+  m_Enabled: 1
+  m_CastShadows: 1
+  m_ReceiveShadows: 1
+  m_DynamicOccludee: 1
+  m_MotionVectors: 1
+  m_LightProbeUsage: 1
+  m_ReflectionProbeUsage: 1
+  m_RenderingLayerMask: 1
+  m_RendererPriority: 0
+  m_Materials:
+  - {fileID: 2100000, guid: ff79b186a05140f459d6913b1c0e7890, type: 2}
+  m_StaticBatchInfo:
+    firstSubMesh: 0
+    subMeshCount: 0
+  m_StaticBatchRoot: {fileID: 0}
+  m_ProbeAnchor: {fileID: 0}
+  m_LightProbeVolumeOverride: {fileID: 0}
+  m_ScaleInLightmap: 1
+  m_PreserveUVs: 0
+  m_IgnoreNormalsForChartDetection: 0
+  m_ImportantGI: 0
+  m_StitchLightmapSeams: 0
+  m_SelectedEditorRenderState: 3
+  m_MinimumChartSize: 4
+  m_AutoUVMaxDistance: 0.5
+  m_AutoUVMaxAngle: 89
+  m_LightmapParameters: {fileID: 0}
+  m_SortingLayerID: 0
+  m_SortingLayer: 0
+  m_SortingOrder: 0
+--- !u!65 &2610591546250173277
+BoxCollider:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2610591546250173276}
+  m_Material: {fileID: 0}
+  m_IsTrigger: 0
+  m_Enabled: 1
+  serializedVersion: 2
+  m_Size: {x: 1, y: 1, z: 1}
+  m_Center: {x: 0, y: 0, z: 0}

+ 7 - 0
Assets/ARLocation/Experimental/World Voxel Craft/CubeStone.prefab.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 1b7ec642be620524eb98454c5f7d6220
+PrefabImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 77 - 0
Assets/ARLocation/Experimental/World Voxel Craft/CubeStoneMaterial.mat

@@ -0,0 +1,77 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!21 &2100000
+Material:
+  serializedVersion: 6
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_Name: CubeStoneMaterial
+  m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
+  m_ShaderKeywords: _GLOSSYREFLECTIONS_OFF _SPECULARHIGHLIGHTS_OFF
+  m_LightmapFlags: 4
+  m_EnableInstancingVariants: 0
+  m_DoubleSidedGI: 0
+  m_CustomRenderQueue: -1
+  stringTagMap: {}
+  disabledShaderPasses: []
+  m_SavedProperties:
+    serializedVersion: 3
+    m_TexEnvs:
+    - _BumpMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailAlbedoMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailMask:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailNormalMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _EmissionMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _MainTex:
+        m_Texture: {fileID: 2800000, guid: 48aab1160aad9cb42a86704adb712ddb, type: 3}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _MetallicGlossMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _OcclusionMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _ParallaxMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    m_Floats:
+    - _BumpScale: 1
+    - _Cutoff: 0.5
+    - _DetailNormalMapScale: 1
+    - _DstBlend: 0
+    - _GlossMapScale: 1
+    - _Glossiness: 0
+    - _GlossyReflections: 0
+    - _Metallic: 0
+    - _Mode: 0
+    - _OcclusionStrength: 1
+    - _Parallax: 0.02
+    - _SmoothnessTextureChannel: 0
+    - _SpecularHighlights: 0
+    - _SrcBlend: 1
+    - _UVSec: 0
+    - _ZWrite: 1
+    m_Colors:
+    - _Color: {r: 1, g: 1, b: 1, a: 1}
+    - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}

+ 8 - 0
Assets/ARLocation/Experimental/World Voxel Craft/CubeStoneMaterial.mat.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ff79b186a05140f459d6913b1c0e7890
+NativeFormatImporter:
+  externalObjects: {}
+  mainObjectFileID: 2100000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 94 - 0
Assets/ARLocation/Experimental/World Voxel Craft/Indicator Plane.prefab

@@ -0,0 +1,94 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &6772245970910680329
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 6772245970910680325}
+  - component: {fileID: 6772245970910680330}
+  - component: {fileID: 6772245970910680331}
+  - component: {fileID: 6772245970910680328}
+  m_Layer: 0
+  m_Name: Indicator Plane
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &6772245970910680325
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 6772245970910680329}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!33 &6772245970910680330
+MeshFilter:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 6772245970910680329}
+  m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!23 &6772245970910680331
+MeshRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 6772245970910680329}
+  m_Enabled: 1
+  m_CastShadows: 1
+  m_ReceiveShadows: 1
+  m_DynamicOccludee: 1
+  m_MotionVectors: 1
+  m_LightProbeUsage: 1
+  m_ReflectionProbeUsage: 1
+  m_RenderingLayerMask: 1
+  m_RendererPriority: 0
+  m_Materials:
+  - {fileID: 2100000, guid: 972d65b3365e8da45aa7abe44e2847b5, type: 2}
+  m_StaticBatchInfo:
+    firstSubMesh: 0
+    subMeshCount: 0
+  m_StaticBatchRoot: {fileID: 0}
+  m_ProbeAnchor: {fileID: 0}
+  m_LightProbeVolumeOverride: {fileID: 0}
+  m_ScaleInLightmap: 1
+  m_PreserveUVs: 0
+  m_IgnoreNormalsForChartDetection: 0
+  m_ImportantGI: 0
+  m_StitchLightmapSeams: 0
+  m_SelectedEditorRenderState: 3
+  m_MinimumChartSize: 4
+  m_AutoUVMaxDistance: 0.5
+  m_AutoUVMaxAngle: 89
+  m_LightmapParameters: {fileID: 0}
+  m_SortingLayerID: 0
+  m_SortingLayer: 0
+  m_SortingOrder: 0
+--- !u!64 &6772245970910680328
+MeshCollider:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 6772245970910680329}
+  m_Material: {fileID: 0}
+  m_IsTrigger: 0
+  m_Enabled: 1
+  serializedVersion: 3
+  m_Convex: 0
+  m_CookingOptions: 14
+  m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0}

+ 7 - 0
Assets/ARLocation/Experimental/World Voxel Craft/Indicator Plane.prefab.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 61587ac9ea0231a42a30af282181f6d9
+PrefabImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 78 - 0
Assets/ARLocation/Experimental/World Voxel Craft/Indicator.mat

@@ -0,0 +1,78 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!21 &2100000
+Material:
+  serializedVersion: 6
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_Name: Indicator
+  m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
+  m_ShaderKeywords: _ALPHAPREMULTIPLY_ON _EMISSION
+  m_LightmapFlags: 1
+  m_EnableInstancingVariants: 0
+  m_DoubleSidedGI: 0
+  m_CustomRenderQueue: 3000
+  stringTagMap:
+    RenderType: Transparent
+  disabledShaderPasses: []
+  m_SavedProperties:
+    serializedVersion: 3
+    m_TexEnvs:
+    - _BumpMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailAlbedoMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailMask:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _DetailNormalMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _EmissionMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _MainTex:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _MetallicGlossMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _OcclusionMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    - _ParallaxMap:
+        m_Texture: {fileID: 0}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    m_Floats:
+    - _BumpScale: 1
+    - _Cutoff: 0.5
+    - _DetailNormalMapScale: 1
+    - _DstBlend: 10
+    - _GlossMapScale: 1
+    - _Glossiness: 0
+    - _GlossyReflections: 1
+    - _Metallic: 0
+    - _Mode: 3
+    - _OcclusionStrength: 1
+    - _Parallax: 0.02
+    - _SmoothnessTextureChannel: 0
+    - _SpecularHighlights: 1
+    - _SrcBlend: 1
+    - _UVSec: 0
+    - _ZWrite: 0
+    m_Colors:
+    - _Color: {r: 0, g: 0, b: 0, a: 0.34117648}
+    - _EmissionColor: {r: 0.005882353, g: 0.24019608, b: 0.048039217, a: 1}

+ 8 - 0
Assets/ARLocation/Experimental/World Voxel Craft/Indicator.mat.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 972d65b3365e8da45aa7abe44e2847b5
+NativeFormatImporter:
+  externalObjects: {}
+  mainObjectFileID: 2100000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

二進制
Assets/ARLocation/Experimental/World Voxel Craft/Pickaxe.png


+ 88 - 0
Assets/ARLocation/Experimental/World Voxel Craft/Pickaxe.png.meta

@@ -0,0 +1,88 @@
+fileFormatVersion: 2
+guid: e58360d20adab9847b941465ba56d135
+TextureImporter:
+  fileIDToRecycleName: {}
+  externalObjects: {}
+  serializedVersion: 9
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    sRGBTexture: 1
+    linearTexture: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapsPreserveCoverage: 0
+    alphaTestReferenceValue: 0.5
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+  isReadable: 0
+  streamingMipmaps: 0
+  streamingMipmapsPriority: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 6
+  cubemapConvolution: 0
+  seamlessCubemap: 0
+  textureFormat: 1
+  maxTextureSize: 2048
+  textureSettings:
+    serializedVersion: 2
+    filterMode: 0
+    aniso: -1
+    mipBias: -100
+    wrapU: 1
+    wrapV: 1
+    wrapW: -1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 1
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spritePixelsToUnits: 100
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spriteGenerateFallbackPhysicsShape: 1
+  alphaUsage: 1
+  alphaIsTransparency: 1
+  spriteTessellationDetail: -1
+  textureType: 8
+  textureShape: 1
+  singleChannelComponent: 0
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  platformSettings:
+  - serializedVersion: 2
+    buildTarget: DefaultTexturePlatform
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+  spriteSheet:
+    serializedVersion: 2
+    sprites: []
+    outline: []
+    physicsShape: []
+    bones: []
+    spriteID: 3fe255138a94f8c49b18b9b0be3a12d1
+    vertices: []
+    indices: 
+    edges: []
+    weights: []
+  spritePackingTag: 
+  pSDRemoveMatte: 0
+  pSDShowRemoveMatteOption: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 24 - 0
Assets/ARLocation/Experimental/World Voxel Craft/PrefabDb.asset

@@ -0,0 +1,24 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 4d58c52ff9f122a49a289c83a1611436, type: 3}
+  m_Name: PrefabDb
+  m_EditorClassIdentifier: 
+  Entries:
+  - MeshId: Brick
+    Prefab: {fileID: 2610591546250173276, guid: ea1041d6d459b1244a69e945813b0067,
+      type: 3}
+  - MeshId: Stone
+    Prefab: {fileID: 2610591546250173276, guid: 1b7ec642be620524eb98454c5f7d6220,
+      type: 3}
+  - MeshId: Gold
+    Prefab: {fileID: 2610591546250173276, guid: edc88edd49b83984dbbc688e401d189a,
+      type: 3}

+ 8 - 0
Assets/ARLocation/Experimental/World Voxel Craft/PrefabDb.asset.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: b31140512dc5e8648b3d725f2529861f
+NativeFormatImporter:
+  externalObjects: {}
+  mainObjectFileID: 11400000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 739 - 0
Assets/ARLocation/Experimental/World Voxel Craft/WorldVoxelController.cs

@@ -0,0 +1,739 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace ARLocation
+{
+    public class WorldVoxelController : MonoBehaviour
+    {
+        // Start is called before the first frame update
+        public PrefabDatabase PrefabDatabase;
+
+        [System.Serializable]
+        class Voxel
+        {
+            public string PrefabId;
+            public int i, j, k;
+
+            [System.NonSerialized]
+            public GameObject Instance;
+        }
+
+        struct VoxelHit
+        {
+            public Voxel Voxel;
+            public Vector3 Normal;
+            public Vector3 WorldNorma;
+        }
+
+        [System.Serializable]
+        class WorldChunk
+        {
+            public List<Voxel> Voxels = new List<Voxel>();
+            public Location ChunkLocation;
+            public float ChunkRotation;
+            public bool HasLocation;
+            public int Length;
+
+            [System.NonSerialized]
+            public Vector3 Origin;
+
+            [System.NonSerialized]
+            public GameObject ChunkContainer;
+
+            [System.NonSerialized]
+            public Bounds Bounds;
+
+            //[System.NonSerialized]
+            //public GameObject ChunkPlaneInstance;
+
+            [System.NonSerialized]
+            public bool IsFresh;
+        }
+
+        [System.Serializable]
+        class World
+        {
+            public List<WorldChunk> Chunks = new List<WorldChunk>();
+        }
+
+        [System.Serializable]
+        public class ElementsSettingsData
+        {
+            public Button ClearWorldBtn;
+            public Button PickAxeBtn;
+            public Button BrickBtn;
+            public Button StoneBtn;
+            public Button GoldBtn;
+            public Text DebugText;
+            public AudioClip Create;
+            public AudioClip Destroy;
+            public ParticleSystem BrickParticle;
+            public GameObject IndicatorPlane;
+            public GameObject ChunkPlanePrefab;
+        }
+
+        public enum Tools
+        {
+            PickAxe,
+            Block
+        }
+
+        public enum Blocks
+        {
+            Brick,
+            Stone,
+            Gold
+        }
+
+        [System.Serializable]
+        public class RaycastMarginSettings
+        {
+            public float Top;
+            public float Bottom;
+            public float Left;
+            public float Right;
+
+            public bool IsInside(Vector2 v)
+            {
+                if (v.x < Left || v.x > (1 - Right)) return false;
+                if (v.y < Bottom || v.y > (1 - Top)) return false;
+
+                return true;
+            }
+        }
+
+        [System.Serializable]
+        public class SettingsData
+        {
+            public float CunkScale = 1.0f;
+            public Color ButtonNormalColor;
+            public Color ButtonSelectedColor;
+        }
+
+        class StateData
+        {
+            public ApplicationState AppState;
+            public GameState GameState;
+            public Blocks CurrentBlock;
+            public WorldChunk CurrentChunk;
+            public Location CurrentLocation;
+        }
+
+        public ElementsSettingsData Elements;
+        public RaycastMarginSettings RaycastMargins;
+        public SettingsData Settings;
+
+        private World world = new World();
+        private readonly StateData state = new StateData();
+
+        private void LogText(string str)
+        {
+            Debug.Log(str);
+            Elements.DebugText.text = str;
+        }
+
+        enum ApplicationState
+        {
+            Initializing,
+            Running
+        };
+
+        enum GameState
+        {
+            Destroy,
+            Build
+        };
+
+        private IEnumerator StartWorld()
+        {
+            LogText($"Loading previous session file...");
+            yield return new WaitForSeconds(0.5f);
+
+            if (RestoreWorldFromLocalStorage())
+            {
+                LogText($"Restored world with {world.Chunks.Count} chunks");
+                yield return new WaitForSeconds(0.5f);
+
+                if (world.Chunks.Count > 0)
+                {
+                    double distance;
+                    var closestChunk = FindClosestChunk(state.CurrentLocation, out distance, 1000.0);
+                    if (closestChunk != null)
+                    {
+                        LogText($"Found closes chunk at {closestChunk.ChunkLocation}, d = {distance}");
+                        yield return new WaitForSeconds(0.5f);
+
+                        SetCurrentChunk(closestChunk);
+                        LogText($"Current Chunk Set");
+                        yield return new WaitForSeconds(0.5f);
+
+                        yield break;
+                    }
+                    else
+                    {
+                        LogText($"No chunk nearby!");
+                        yield return new WaitForSeconds(0.5f);
+
+                        var i = 0;
+                        foreach (var c in world.Chunks)
+                        {
+                            var d = Location.HorizontalDistance(state.CurrentLocation, c.ChunkLocation);
+                            LogText($"Chunk {i} at {c.ChunkLocation}, d = {d}");
+                            yield return new WaitForSeconds(0.5f);
+                            i++;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                LogText($"No world to restore!");
+                yield return new WaitForSeconds(0.5f);
+            }
+
+            LogText("Creating new chunk...");
+            yield return new WaitForSeconds(0.5f);
+
+            var chunk = CreateTestChunk();
+            chunk.IsFresh = true;
+            world.Chunks.Add(chunk);
+            SetCurrentChunk(chunk);
+            UpdateChunkLocation(chunk);
+
+            LogText("Added new chunk!");
+            yield return new WaitForSeconds(0.5f);
+        }
+
+
+        private IEnumerator Start()
+        {
+            Utils.Misc.HideGameObject(Elements.IndicatorPlane);
+            ARLocationProvider.Instance.OnLocationUpdated.AddListener(OnLocationUpdatedListener);
+            ChooseBrick();
+
+            LogText("Starting...");
+            LogText("Waiting for location...");
+            yield return new WaitForSeconds(0.5f);
+
+            yield return StartCoroutine(WaitForLocationServices());
+            state.CurrentLocation = ARLocationProvider.Instance.CurrentLocation.ToLocation();
+            LogText($"Location enabled: {state.CurrentLocation}");
+            yield return new WaitForSeconds(0.5f);
+
+            yield return StartCoroutine(StartWorld());
+
+            LogText($"Starting UI Listeners...");
+            yield return new WaitForSeconds(0.5f);
+            InitUiListeners();
+
+            LogText($"Setting app running...");
+            yield return new WaitForSeconds(0.5f);
+            state.AppState = ApplicationState.Running;
+
+            LogText($"App is running!");
+        }
+
+        void SetCurrentChunk(WorldChunk chunk)
+        {
+            if ((state.CurrentChunk != null) && (state.CurrentChunk.ChunkContainer != null)) Destroy(state.CurrentChunk.ChunkContainer);
+
+            state.CurrentChunk = chunk;
+
+            if (chunk.ChunkContainer == null)
+            {
+                BuildChunk(chunk);
+            }
+        }
+
+        void AddVoxelToChunk(WorldChunk c, string PrefabId, int i, int j, int k)
+        {
+            Voxel v = new Voxel { PrefabId = PrefabId, i = i, j = j, k = k };
+            v.Instance = Instantiate(PrefabDatabase.GetEntryById(PrefabId), c.ChunkContainer.transform);
+            v.Instance.transform.localPosition = new Vector3(v.i, v.j, v.k);
+            c.Voxels.Add(v);
+        }
+
+        WorldChunk CreateDefaultChunk()
+        {
+            return new WorldChunk { Origin = new Vector3(0, -1.4f, 4), Length = 100 };
+        }
+
+        WorldChunk CreateTestChunk()
+        {
+            WorldChunk c = new WorldChunk
+            {
+                Voxels = new List<Voxel>
+                {
+                    new Voxel
+                    {
+                        PrefabId = "Brick",
+                        Instance = null,
+                        i = 0, j = 0, k = 0
+                    }
+                },
+                Origin = new Vector3(0, -1.4f, 4),
+                Length = 100
+            };
+
+            for (int i = 1; i < 10; i++)
+            {
+                c.Voxels.Add(new Voxel { PrefabId = "Brick", i = i, j = 0, k = 0 });
+            }
+
+            for (int i = 1; i < 10; i++)
+            {
+                c.Voxels.Add(new Voxel { PrefabId = "Brick", i = i, j = 0, k = 9 });
+            }
+
+            for (int i = 1; i < 10; i++)
+            {
+                c.Voxels.Add(new Voxel { PrefabId = "Brick", i = 0, j = 0, k = i });
+            }
+
+            for (int i = 1; i < 10; i++)
+            {
+                c.Voxels.Add(new Voxel { PrefabId = "Brick", i = 9, j = 0, k = i });
+            }
+
+            return c;
+        }
+
+        IEnumerator WaitForLocationServices()
+        {
+            while (!ARLocationProvider.Instance.IsEnabled)
+            {
+                yield return new WaitForSeconds(0.1f);
+            }
+        }
+
+        bool InputIsDown(out Vector2 pos)
+        {
+            if (Application.isEditor)
+            {
+                pos = Input.mousePosition;
+                return Input.GetMouseButtonDown(0) && RaycastMargins.IsInside(pos / new Vector2(Screen.width, Screen.height));
+            }
+
+            if (Input.touchCount == 1 && Input.touches[0].phase == TouchPhase.Began)
+            {
+                pos = Input.touches[0].position;
+                return RaycastMargins.IsInside(pos / new Vector2(Screen.width, Screen.height));
+            }
+
+            pos = new Vector3();
+            return false;
+        }
+
+        private void Update()
+        {
+            if (state.AppState == ApplicationState.Initializing) return;
+
+            if (state.CurrentChunk == null)
+            {
+                FindClosestChunkOrCreateNew(state.CurrentLocation);
+                return;
+            }
+
+            Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0));
+            VoxelHit hit;
+            if (RaycastChunk(ray, state.CurrentChunk, out hit))
+            {
+                Utils.Misc.ShowGameObject(Elements.IndicatorPlane);
+                var t = Elements.IndicatorPlane.transform;
+                t.SetParent(state.CurrentChunk.ChunkContainer.transform);
+                t.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
+                t.transform.localEulerAngles = new Vector3(0, 0, 0);
+                t.transform.localPosition = new Vector3(hit.Voxel.i + Mathf.FloorToInt(hit.Normal.x) * 0.505f, hit.Voxel.j + Mathf.FloorToInt(hit.Normal.y) * 0.505f, hit.Voxel.k + Mathf.FloorToInt(hit.Normal.z) * 0.505f);
+                //LogText("" + hit.Normal);
+                var Normal = hit.Normal;
+
+                if (Mathf.Abs(Normal.x) < 0.0001f && Mathf.Abs(Normal.y) < 0.0001f)
+                {
+                    float sign = Normal.z < 0 ? -1.0f : 1.0f;
+                    Elements.IndicatorPlane.transform.localEulerAngles = new Vector3(sign * 90.0f, 0, 0);
+                }
+                else if (Mathf.Abs(Normal.z) < 0.0001f && Mathf.Abs(Normal.y) < 0.0001f)
+                {
+                    float sign = Normal.x < 0 ? 1.0f : -1.0f;
+                    Elements.IndicatorPlane.transform.localEulerAngles = new Vector3(0, 0, sign * 90.0f);
+                }
+            }
+            else
+            {
+                Utils.Misc.HideGameObject(Elements.IndicatorPlane);
+                return;
+            }
+
+            Vector2 touchPos;
+            bool isDown = InputIsDown(out touchPos);
+
+            switch (state.GameState)
+            {
+                case GameState.Destroy:
+                    {
+                        if (isDown && hit.Voxel.Instance != null)
+                        { 
+                            var i = Instantiate(Elements.BrickParticle);
+                            i.transform.position = hit.Voxel.Instance.transform.position;
+                            i.GetComponent<ParticleSystemRenderer>().material = hit.Voxel.Instance.GetComponent<MeshRenderer>().material;
+                            i.Play();
+
+                            state.CurrentChunk.Voxels.Remove(hit.Voxel);
+                            Destroy(hit.Voxel.Instance);
+
+
+                            var a = Camera.main.GetComponent<AudioSource>();
+                            if (a)
+                            {
+                                a.clip = Elements.Destroy;
+                                a.Play();
+                            }
+                        }
+                    }
+                    break;
+                case GameState.Build:
+                    {
+                        if (isDown)
+                        {
+                            AddVoxelToChunk(state.CurrentChunk, GetMeshIdForBlock(state.CurrentBlock), hit.Voxel.i + Mathf.FloorToInt(hit.Normal.x), hit.Voxel.j + Mathf.FloorToInt(hit.Normal.y), hit.Voxel.k + Mathf.FloorToInt(hit.Normal.z));
+                            var a = Camera.main.GetComponent<AudioSource>();
+                            if (a)
+                            {
+                                a.clip = Elements.Create;
+                                a.Play();
+                            }
+                        }
+                    }
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        bool RaycastChunk(Ray ray, WorldChunk chunk, out VoxelHit hit)
+        {
+            //if (!chunk.Bounds.IntersectRay(ray)) {
+            //    hit = new VoxelHit();
+            //    return false;
+            //}
+
+            VoxelHit currentHit = new VoxelHit();
+            float currentDistance = 0;
+            bool hasHit = false;
+            foreach (var v in chunk.Voxels)
+            {
+                if (v.Instance)
+                {
+                    var collider = v.Instance.GetComponent<BoxCollider>();
+
+                    Debug.Assert(collider);
+
+                    RaycastHit h;
+                    if (collider.Raycast(ray, out h, chunk.Length))
+                    {
+                        if (!hasHit || h.distance < currentDistance)
+                        {
+                            hasHit = true;
+                            currentDistance = h.distance;
+                            currentHit = new VoxelHit { Voxel = v, WorldNorma = h.normal, Normal = chunk.ChunkContainer.transform.InverseTransformDirection(h.normal) };
+                        }
+                    }
+                }
+            }
+
+            hit = currentHit;
+
+            if (hasHit)
+            {
+                hit = currentHit;
+                return true;
+            }
+            else
+            {
+                var chunkOrigin = chunk.ChunkContainer.transform.position;
+                var plane = new Plane(new Vector3(0, 1, 0), -chunkOrigin.y + 0.5f * Settings.CunkScale);
+                float d;
+                if (plane.Raycast(ray, out d))
+                {
+                    var p = chunk.ChunkContainer.transform.InverseTransformPoint(ray.GetPoint(d));
+
+                    var i = Mathf.FloorToInt(p.x + 0.5f);
+                    var j = -1;
+                    var k = Mathf.FloorToInt(p.z + 0.5f);
+
+                    hit = new VoxelHit { Voxel = new Voxel { PrefabId = "", i = i, j = j, k = k }, Normal = new Vector3(0, 1, 0) };
+
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        bool RestoreWorldFromLocalStorage()
+        {
+            string json = "";
+            try
+            {
+                json = System.IO.File.ReadAllText(GetJsonFilename(), System.Text.Encoding.UTF8);
+            }
+            catch
+            {
+                Debug.Log("[ARLocation::WorldBuilder::RestoreWorld]: Failed to open json file for reading.");
+                //RandomPopulateWorld();
+                return false;
+            }
+
+            world = JsonUtility.FromJson<World>(json);
+            Debug.Log($"Restored world from json file '{GetJsonFilename()}'");
+
+            return true;
+        }
+
+        string GetJsonFilename()
+        {
+            var s = "WorldVoxelCraft";
+
+            return Application.persistentDataPath + "/" + s + ".json";
+        }
+
+        WorldChunk FindClosestChunk(Location l, out double distance, double maxDistance)
+        {
+            WorldChunk current = null;
+            double currentDistance = 0;
+
+            foreach (var c in world.Chunks)
+            {
+                var d = Location.HorizontalDistance(c.ChunkLocation, l);
+
+                if (current == null || d < currentDistance)
+                {
+                    current = c;
+                    currentDistance = d;
+                }
+            }
+
+            distance = currentDistance;
+
+            if (currentDistance > maxDistance) return null;
+
+            return current;
+        }
+
+        void BuildChunk(WorldChunk chunk)
+        {
+            chunk.ChunkContainer = new GameObject();
+            chunk.ChunkContainer.transform.localScale = new Vector3(Settings.CunkScale, Settings.CunkScale, Settings.CunkScale);
+            if (chunk.HasLocation)
+            {
+                PlaceAtLocation.AddPlaceAtComponent(chunk.ChunkContainer, chunk.ChunkLocation, new PlaceAtLocation.PlaceAtOptions { MaxNumberOfLocationUpdates = 2 });
+                chunk.ChunkContainer.transform.localEulerAngles = new Vector3(0, chunk.ChunkRotation, 0);
+            }
+            else
+            {
+                chunk.ChunkContainer.transform.position = chunk.Origin;
+                chunk.Bounds = new Bounds(chunk.Origin, new Vector3(chunk.Length, chunk.Length, chunk.Length));
+                chunk.ChunkContainer.AddComponent<GroundHeight>();
+            }
+
+            foreach (var v in chunk.Voxels)
+            {
+                v.Instance = Instantiate(PrefabDatabase.GetEntryById(v.PrefabId), chunk.ChunkContainer.transform);
+                v.Instance.transform.localPosition = new Vector3(v.i, v.j, v.k);
+            }
+
+            //if (Elements.ChunkPlanePrefab != null)
+            //{
+            //    chunk.ChunkPlaneInstance = Instantiate(Elements.ChunkPlanePrefab, chunk.ChunkContainer.transform);
+            //    chunk.ChunkPlaneInstance.transform.localPosition = new Vector3(0, -0.5f, 0);
+            //    //chunk.ChunkPlaneInstance.transform.localScale = new Vector3(5, 1, 5);
+            //    chunk.ChunkPlaneInstance.transform.localScale = new Vector3(chunk.Length/10, 1, chunk.Length/10);
+            //    //chunk.ChunkPlaneInstance.GetComponent<MeshRenderer>().material.mainTextureScale = new Vector2(50, 50);
+            //    chunk.ChunkPlaneInstance.GetComponent<MeshRenderer>().material.mainTextureScale = new Vector2(chunk.Length, chunk.Length);
+            //    chunk.ChunkPlaneInstance.GetComponent<MeshRenderer>().material.mainTextureOffset = new Vector2(0.5f, 0.5f);
+            //}
+        }
+
+        private void OnApplicationPause(bool pause)
+        {
+            if (pause) SaveWorldToLocalStorage();
+        }
+
+        private void OnDestroy()
+        {
+            SaveWorldToLocalStorage();
+        }
+
+        void SaveWorldToLocalStorage()
+        {
+            var json = JsonUtility.ToJson(world);
+
+            try
+            {
+                System.IO.File.WriteAllText(GetJsonFilename(), json);
+            }
+            catch
+            {
+                Debug.Log("[ARLocation::WorldBuilder::SaveWorld]: Failed to open json file for writing.");
+                return;
+            }
+
+            Debug.Log("Saved " + GetJsonFilename());
+        }
+
+        private void OnLocationUpdatedListener(Location l)
+        {
+
+            if (state.AppState != ApplicationState.Running) return;
+
+            state.CurrentLocation = l;
+
+            FindClosestChunkOrCreateNew(l);
+
+            if (state.CurrentChunk != null)
+            {
+                UpdateChunkLocation(state.CurrentChunk);
+            }
+
+        }
+
+        private void FindClosestChunkOrCreateNew(Location l)
+        {
+            double distance;
+            var newClosestChunk = FindClosestChunk(l, out distance, 1000.0f);
+            if (newClosestChunk != state.CurrentChunk && newClosestChunk != null)
+            {
+                SetCurrentChunk(newClosestChunk);
+            }
+            
+            if (state.CurrentChunk == null)
+            {
+                SetCurrentChunk(CreateDefaultChunk());
+            }
+
+        }
+
+        void UpdateChunkLocation(WorldChunk c)
+        {
+            if (!c.IsFresh) return;
+
+            c.ChunkLocation = ARLocationManager.Instance.GetLocationForWorldPosition(c.ChunkContainer.transform.position);
+            c.ChunkLocation.Altitude = 0;
+            c.ChunkLocation.AltitudeMode = AltitudeMode.GroundRelative;
+            var arLocationRoot = ARLocationManager.Instance.gameObject.transform;
+            float angle = Vector3.SignedAngle(c.ChunkContainer.transform.forward, arLocationRoot.forward, new Vector3(0, 1, 0));
+            c.ChunkRotation = angle;
+            c.HasLocation = true;
+
+            LogText($"Updated chunk location to {c.ChunkLocation}");
+        }
+
+        private void InitUiListeners()
+        {
+            Elements.ClearWorldBtn.onClick.AddListener(() =>
+            {
+                ClearWorld();
+            });
+
+            Elements.PickAxeBtn.onClick.AddListener(() =>
+            {
+                ChoosePickaxe();
+            });
+
+            Elements.BrickBtn.onClick.AddListener(() =>
+            {
+                ChooseBrick();
+            });
+
+            Elements.StoneBtn.onClick.AddListener(() =>
+            {
+                ChooseStone();
+            });
+
+            Elements.GoldBtn.onClick.AddListener(() =>
+            {
+                ChooseGold();
+            });
+        }
+
+        void ChooseBrick()
+        {
+            state.GameState = GameState.Build;
+            state.CurrentBlock = Blocks.Brick;
+
+            Elements.BrickBtn.GetComponent<Image>().color = Settings.ButtonSelectedColor;
+            Elements.GoldBtn.GetComponent<Image>().color = Settings.ButtonNormalColor;
+            Elements.StoneBtn.GetComponent<Image>().color = Settings.ButtonNormalColor;
+            Elements.PickAxeBtn.GetComponent<Image>().color = Settings.ButtonNormalColor;
+        }
+
+        void ChooseGold()
+        {
+            state.GameState = GameState.Build;
+            state.CurrentBlock = Blocks.Gold;
+
+            Elements.BrickBtn.GetComponent<Image>().color = Settings.ButtonNormalColor;
+            Elements.GoldBtn.GetComponent<Image>().color = Settings.ButtonSelectedColor;
+            Elements.StoneBtn.GetComponent<Image>().color = Settings.ButtonNormalColor;
+            Elements.PickAxeBtn.GetComponent<Image>().color = Settings.ButtonNormalColor;
+        }
+
+        void ChooseStone()
+        {
+            state.GameState = GameState.Build;
+            state.CurrentBlock = Blocks.Stone;
+
+            Elements.BrickBtn.GetComponent<Image>().color = Settings.ButtonNormalColor;
+            Elements.GoldBtn.GetComponent<Image>().color = Settings.ButtonNormalColor;
+            Elements.StoneBtn.GetComponent<Image>().color = Settings.ButtonSelectedColor;
+            Elements.PickAxeBtn.GetComponent<Image>().color = Settings.ButtonNormalColor;
+        }
+
+        void ChoosePickaxe()
+        {
+            state.GameState = GameState.Destroy;
+            
+
+            Elements.BrickBtn.GetComponent<Image>().color = Settings.ButtonNormalColor;
+            Elements.GoldBtn.GetComponent<Image>().color = Settings.ButtonNormalColor;
+            Elements.StoneBtn.GetComponent<Image>().color = Settings.ButtonNormalColor;
+            Elements.PickAxeBtn.GetComponent<Image>().color = Settings.ButtonSelectedColor;
+        }
+
+        void ClearChunk(WorldChunk chunk)
+        {
+            if (chunk.ChunkContainer != null)
+            {
+                Elements.IndicatorPlane.transform.SetParent(null);
+                Destroy(chunk.ChunkContainer);
+            }
+
+            chunk.Voxels = new List<Voxel>();
+        }
+
+        void ClearWorld()
+        {
+            world.Chunks.ForEach(ClearChunk);
+            world.Chunks = new List<WorldChunk>();
+            state.CurrentChunk = null;
+            LogText("World cleared!");
+        }
+
+        private string GetMeshIdForBlock(Blocks b)
+        {
+            switch (b)
+            {
+                case Blocks.Brick:
+                    return "Brick";
+                case Blocks.Stone:
+                    return "Stone";
+                case Blocks.Gold:
+                    return "Gold";
+                default:
+                    return "";
+            }
+        }
+    }
+}

+ 11 - 0
Assets/ARLocation/Experimental/World Voxel Craft/WorldVoxelController.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 793438b15ed25ff469ce6892a8f0a5ef
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

二進制
Assets/ARLocation/Experimental/World Voxel Craft/brick_mixed 1.png


+ 88 - 0
Assets/ARLocation/Experimental/World Voxel Craft/brick_mixed 1.png.meta

@@ -0,0 +1,88 @@
+fileFormatVersion: 2
+guid: 428c40559c0c093408e2c0ca1c884d8f
+TextureImporter:
+  fileIDToRecycleName: {}
+  externalObjects: {}
+  serializedVersion: 9
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    sRGBTexture: 1
+    linearTexture: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapsPreserveCoverage: 0
+    alphaTestReferenceValue: 0.5
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+  isReadable: 0
+  streamingMipmaps: 0
+  streamingMipmapsPriority: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 6
+  cubemapConvolution: 0
+  seamlessCubemap: 0
+  textureFormat: 1
+  maxTextureSize: 2048
+  textureSettings:
+    serializedVersion: 2
+    filterMode: 0
+    aniso: -1
+    mipBias: -100
+    wrapU: 1
+    wrapV: 1
+    wrapW: -1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 1
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spritePixelsToUnits: 100
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spriteGenerateFallbackPhysicsShape: 1
+  alphaUsage: 1
+  alphaIsTransparency: 1
+  spriteTessellationDetail: -1
+  textureType: 8
+  textureShape: 1
+  singleChannelComponent: 0
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  platformSettings:
+  - serializedVersion: 2
+    buildTarget: DefaultTexturePlatform
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+  spriteSheet:
+    serializedVersion: 2
+    sprites: []
+    outline: []
+    physicsShape: []
+    bones: []
+    spriteID: 3143f8aaae1fa0f40a660f79fbaf8eec
+    vertices: []
+    indices: 
+    edges: []
+    weights: []
+  spritePackingTag: 
+  pSDRemoveMatte: 0
+  pSDShowRemoveMatteOption: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

二進制
Assets/ARLocation/Experimental/World Voxel Craft/brick_mixed.png


+ 88 - 0
Assets/ARLocation/Experimental/World Voxel Craft/brick_mixed.png.meta

@@ -0,0 +1,88 @@
+fileFormatVersion: 2
+guid: 1c79c11d09b36a24d819377072e7bc9c
+TextureImporter:
+  fileIDToRecycleName: {}
+  externalObjects: {}
+  serializedVersion: 9
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    sRGBTexture: 1
+    linearTexture: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapsPreserveCoverage: 0
+    alphaTestReferenceValue: 0.5
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+  isReadable: 0
+  streamingMipmaps: 0
+  streamingMipmapsPriority: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 6
+  cubemapConvolution: 0
+  seamlessCubemap: 0
+  textureFormat: 1
+  maxTextureSize: 2048
+  textureSettings:
+    serializedVersion: 2
+    filterMode: 0
+    aniso: -1
+    mipBias: -100
+    wrapU: -1
+    wrapV: -1
+    wrapW: -1
+  nPOTScale: 1
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spritePixelsToUnits: 100
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spriteGenerateFallbackPhysicsShape: 1
+  alphaUsage: 1
+  alphaIsTransparency: 0
+  spriteTessellationDetail: -1
+  textureType: 0
+  textureShape: 1
+  singleChannelComponent: 0
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  platformSettings:
+  - serializedVersion: 2
+    buildTarget: DefaultTexturePlatform
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+  spriteSheet:
+    serializedVersion: 2
+    sprites: []
+    outline: []
+    physicsShape: []
+    bones: []
+    spriteID: 
+    vertices: []
+    indices: 
+    edges: []
+    weights: []
+  spritePackingTag: 
+  pSDRemoveMatte: 0
+  pSDShowRemoveMatteOption: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

二進制
Assets/ARLocation/Experimental/World Voxel Craft/rect12.png


+ 88 - 0
Assets/ARLocation/Experimental/World Voxel Craft/rect12.png.meta

@@ -0,0 +1,88 @@
+fileFormatVersion: 2
+guid: 11776792d1743954d9350ae1c1e2930c
+TextureImporter:
+  fileIDToRecycleName: {}
+  externalObjects: {}
+  serializedVersion: 9
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    sRGBTexture: 1
+    linearTexture: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapsPreserveCoverage: 0
+    alphaTestReferenceValue: 0.5
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+  isReadable: 0
+  streamingMipmaps: 0
+  streamingMipmapsPriority: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 6
+  cubemapConvolution: 0
+  seamlessCubemap: 0
+  textureFormat: 1
+  maxTextureSize: 2048
+  textureSettings:
+    serializedVersion: 2
+    filterMode: -1
+    aniso: -1
+    mipBias: -100
+    wrapU: -1
+    wrapV: -1
+    wrapW: -1
+  nPOTScale: 1
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spritePixelsToUnits: 100
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spriteGenerateFallbackPhysicsShape: 1
+  alphaUsage: 1
+  alphaIsTransparency: 0
+  spriteTessellationDetail: -1
+  textureType: 0
+  textureShape: 1
+  singleChannelComponent: 0
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  platformSettings:
+  - serializedVersion: 2
+    buildTarget: DefaultTexturePlatform
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+  spriteSheet:
+    serializedVersion: 2
+    sprites: []
+    outline: []
+    physicsShape: []
+    bones: []
+    spriteID: 
+    vertices: []
+    indices: 
+    edges: []
+    weights: []
+  spritePackingTag: 
+  pSDRemoveMatte: 0
+  pSDShowRemoveMatteOption: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

二進制
Assets/ARLocation/Experimental/World Voxel Craft/stone_granite_brick 1.png


+ 88 - 0
Assets/ARLocation/Experimental/World Voxel Craft/stone_granite_brick 1.png.meta

@@ -0,0 +1,88 @@
+fileFormatVersion: 2
+guid: 71990741ce209b042959f26603714031
+TextureImporter:
+  fileIDToRecycleName: {}
+  externalObjects: {}
+  serializedVersion: 9
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    sRGBTexture: 1
+    linearTexture: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapsPreserveCoverage: 0
+    alphaTestReferenceValue: 0.5
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+  isReadable: 0
+  streamingMipmaps: 0
+  streamingMipmapsPriority: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 6
+  cubemapConvolution: 0
+  seamlessCubemap: 0
+  textureFormat: 1
+  maxTextureSize: 2048
+  textureSettings:
+    serializedVersion: 2
+    filterMode: 0
+    aniso: -1
+    mipBias: -100
+    wrapU: 1
+    wrapV: 1
+    wrapW: -1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 1
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spritePixelsToUnits: 100
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spriteGenerateFallbackPhysicsShape: 1
+  alphaUsage: 1
+  alphaIsTransparency: 1
+  spriteTessellationDetail: -1
+  textureType: 8
+  textureShape: 1
+  singleChannelComponent: 0
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  platformSettings:
+  - serializedVersion: 2
+    buildTarget: DefaultTexturePlatform
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+  spriteSheet:
+    serializedVersion: 2
+    sprites: []
+    outline: []
+    physicsShape: []
+    bones: []
+    spriteID: 995852b9cbd97854db2f52830080722e
+    vertices: []
+    indices: 
+    edges: []
+    weights: []
+  spritePackingTag: 
+  pSDRemoveMatte: 0
+  pSDShowRemoveMatteOption: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

二進制
Assets/ARLocation/Experimental/World Voxel Craft/stone_granite_brick.png


+ 88 - 0
Assets/ARLocation/Experimental/World Voxel Craft/stone_granite_brick.png.meta

@@ -0,0 +1,88 @@
+fileFormatVersion: 2
+guid: 48aab1160aad9cb42a86704adb712ddb
+TextureImporter:
+  fileIDToRecycleName: {}
+  externalObjects: {}
+  serializedVersion: 9
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    sRGBTexture: 1
+    linearTexture: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapsPreserveCoverage: 0
+    alphaTestReferenceValue: 0.5
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+  isReadable: 0
+  streamingMipmaps: 0
+  streamingMipmapsPriority: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 6
+  cubemapConvolution: 0
+  seamlessCubemap: 0
+  textureFormat: 1
+  maxTextureSize: 2048
+  textureSettings:
+    serializedVersion: 2
+    filterMode: 0
+    aniso: -1
+    mipBias: -100
+    wrapU: -1
+    wrapV: -1
+    wrapW: -1
+  nPOTScale: 1
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spritePixelsToUnits: 100
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spriteGenerateFallbackPhysicsShape: 1
+  alphaUsage: 1
+  alphaIsTransparency: 0
+  spriteTessellationDetail: -1
+  textureType: 0
+  textureShape: 1
+  singleChannelComponent: 0
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  platformSettings:
+  - serializedVersion: 2
+    buildTarget: DefaultTexturePlatform
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+  spriteSheet:
+    serializedVersion: 2
+    sprites: []
+    outline: []
+    physicsShape: []
+    bones: []
+    spriteID: 
+    vertices: []
+    indices: 
+    edges: []
+    weights: []
+  spritePackingTag: 
+  pSDRemoveMatte: 0
+  pSDShowRemoveMatteOption: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

二進制
Assets/ARLocation/Experimental/World Voxel Craft/topaz_brick 1.png


+ 0 - 0
Assets/ARLocation/Experimental/World Voxel Craft/topaz_brick 1.png.meta


部分文件因文件數量過多而無法顯示