/// <summary> /// Raise a Tango Area Description event if there is new data. /// </summary> internal static void SendIfAvailable() { if (!m_isCallbackSet) { return; } if (m_onTangoAreaDescriptionExported != null && m_onTangoAreaDescriptionImported != null) { lock (m_lockObject) { if (m_isImportFinished) { m_onTangoAreaDescriptionImported(m_isSuccessful, AreaDescription.ForUUID(m_eventString)); m_isImportFinished = false; m_eventString = string.Empty; } if (m_isExportFinished) { m_onTangoAreaDescriptionExported(m_isSuccessful); m_isExportFinished = false; } } } }
/// <summary> /// Inits the emulation for a given area description UUID and set of Tango Application settings. /// </summary> /// <param name="uuid">UUID of the Area Description that /// TangoApplication.Startup() was called with.</param> /// <param name="haveAreaDescriptionPermissions">If set to <c>true</c>, assume area description /// permissions have been requested and 'granted'.</param> /// <param name="learningMode">If set to <c>true</c>, service is in learning mode.</param> /// <param name="artificialOffset">Artificial offset fom Start of Service to Area Description.</param> public static void InitEmulationForUUID(string uuid, bool haveAreaDescriptionPermissions, bool learningMode, Vector3 artificialOffset) { m_usingEmulatedDescriptionFrames = false; m_currentUUID = uuid; if (haveAreaDescriptionPermissions) { if (!string.IsNullOrEmpty(uuid)) { if (AreaDescription.ForUUID(uuid).GetMetadata() != null) { m_usingEmulatedDescriptionFrames = true; } else { m_currentUUID = string.Empty; Debug.LogError("Requested Area Description UUID does not exist."); } } else if (learningMode) { m_usingEmulatedDescriptionFrames = true; } } m_emulationAreaOffset = artificialOffset; }
/// <summary> /// Saves the current area description, returning the area description saved. /// /// You can only save an area description while connected to the Tango Service and if you have enabled Area /// Learning mode. If you loaded an ADF before connecting, then calling this method appends any new learned /// areas to that ADF and returns the same UUID. If you did not load an ADF, this method creates a new ADF and /// a new UUID for that ADF. /// </summary> /// <returns> /// AreaDescription instance for the newly saved area description if saved successfully, <c>null</c> otherwise. /// /// See logcat for details of why the saved failed. /// </returns> public static AreaDescription SaveCurrent() { byte[] rawUUID = new byte[Common.UUID_LENGTH]; if (AreaDescriptionAPI.TangoService_saveAreaDescription(rawUUID) != Common.ErrorType.TANGO_SUCCESS) { Debug.Log("Could not save area description.\n" + Environment.StackTrace); return(null); } string uuid = Encoding.UTF8.GetString(rawUUID); return(AreaDescription.ForUUID(uuid)); }
/// <summary> /// Get a list of all the area descriptions on the device. /// </summary> /// <returns>A list of area descriptions, or <c>null</c> if the list could not be queried.</returns> public static AreaDescription[] GetList() { string[] uuids = _GetUUIDList(); if (uuids == null || uuids.Length == 0) { return(null); } AreaDescription[] adfs = new AreaDescription[uuids.Length]; for (int it = 0; it < uuids.Length; ++it) { adfs[it] = new AreaDescription(uuids[it]); } return(adfs); }
/// <summary> /// Raise a Tango Area Description event if there is new data. /// </summary> internal void SendEventIfAvailable() { if (OnTangoAreaDescriptionExported != null && OnTangoAreaDescriptionImported != null) { lock (m_lockObject) { if (m_isImportFinished) { OnTangoAreaDescriptionImported(m_isSuccessful, AreaDescription.ForUUID(m_eventString)); m_isImportFinished = false; m_eventString = string.Empty; } if (m_isExportFinished) { OnTangoAreaDescriptionExported(m_isSuccessful); m_isExportFinished = false; } } } }
/// <summary> /// Called every time an Area Description toggle changes state. /// </summary> /// <param name="areaDescription">Area Description the toggle is for.</param> /// <param name="value">The new state of the toggle.</param> private void _OnAreaDescriptionToggleChanged(AreaDescription areaDescription, bool value) { if (value) { _SelectAreaDescription(areaDescription); } else { _SelectAreaDescription(null); } }
/// <summary> /// Actually do the Area description export. /// /// This runs over multiple frames, so a Unity coroutine is used. /// </summary> /// <returns>Coroutine IEnumerator.</returns> /// <param name="areaDescription">Area Description to export.</param> private IEnumerator _DoExportAreaDescription(AreaDescription areaDescription) { if (TouchScreenKeyboard.visible) { yield break; } TouchScreenKeyboard kb = TouchScreenKeyboard.Open("/sdcard/", TouchScreenKeyboardType.Default, false); while (!kb.done && !kb.wasCanceled) { yield return null; } if (kb.done) { areaDescription.ExportToFile(kb.text); } }
/// <summary> /// Callback function when toggle button is selected. /// </summary> /// <param name="item">Caller item object.</param> /// <param name="value">Selected value of the toggle button.</param> private void _OnToggleChanged(AreaDescription item, bool value) { if (value) { Globals.m_curAreaDescription = item; } }
/// <summary> /// Manual initalization step 2: Call this to connect to the Tango service. /// /// After connecting to the Tango service, you will get updates for Motion Tracking, Depth Sensing, and Area /// Learning. If you have a specific Area Description you want to localize too, pass that Area Description in /// here. /// </summary> /// <param name="areaDescription">If not null, the Area Description to localize to.</param> public void Startup(AreaDescription areaDescription) { // Make sure all required permissions have been granted. if (m_requiredPermissions != PermissionsTypes.NONE) { Debug.Log("TangoApplication.Startup() -- ERROR: Not all required permissions were accepted yet."); return; } _CheckTangoVersion(); if (m_enableVideoOverlay && m_useExperimentalVideoOverlay) { int yTextureWidth = 0; int yTextureHeight = 0; int uvTextureWidth = 0; int uvTextureHeight = 0; m_tangoConfig.GetInt32(TangoConfig.Keys.EXPERIMENTAL_Y_TEXTURE_WIDTH, ref yTextureWidth); m_tangoConfig.GetInt32(TangoConfig.Keys.EXPERIMENTAL_Y_TEXTURE_HEIGHT, ref yTextureHeight); m_tangoConfig.GetInt32(TangoConfig.Keys.EXPERIMENTAL_UV_TEXTURE_WIDTH, ref uvTextureWidth); m_tangoConfig.GetInt32(TangoConfig.Keys.EXPERIMENTAL_UV_TEXTURE_HEIGHT, ref uvTextureHeight); if (yTextureWidth == 0 || yTextureHeight == 0 || uvTextureWidth == 0 || uvTextureHeight == 0) { Debug.Log("Video overlay texture sizes were not set properly"); } m_yuvTexture.ResizeAll(yTextureWidth, yTextureHeight, uvTextureWidth, uvTextureHeight); } if (areaDescription != null) { _InitializeMotionTracking(areaDescription.m_uuid); } else { _InitializeMotionTracking(null); } if (m_tangoConfig.SetBool(TangoConfig.Keys.ENABLE_DEPTH_PERCEPTION_BOOL, m_enableDepth) && m_enableDepth) { _SetDepthCallbacks(); } if (m_enableVideoOverlay) { _SetVideoOverlayCallbacks(); } _SetEventCallbacks(); _TangoConnect(); }
/// <summary> /// Get a list of all the area descriptions on the device. /// </summary> /// <returns>A list of area descriptions, or <c>null</c> if the list could not be queried.</returns> public static AreaDescription[] GetList() { string[] uuids = _GetUUIDList(); if (uuids == null || uuids.Length == 0) { return null; } AreaDescription[] adfs = new AreaDescription[uuids.Length]; for (int it = 0; it < uuids.Length; ++it) { adfs[it] = new AreaDescription(uuids[it]); } return adfs; }
/// <summary> /// Actually do the Area Description save. /// </summary> /// <returns>Coroutine IEnumerator.</returns> private IEnumerator _DoSaveCurrentAreaDescription() { if (TouchScreenKeyboard.visible || m_saveThread != null) { yield break; } TouchScreenKeyboard kb = TouchScreenKeyboard.Open("Unnamed"); while (!kb.done && !kb.wasCanceled) { yield return null; } if (kb.done) { // Disable interaction before saving. m_initialized = false; m_savingText.gameObject.SetActive(true); if (m_tangoApplication.m_enableAreaLearning) { m_saveThread = new Thread(delegate() { // Start saving process in another thread. m_curAreaDescription = AreaDescription.SaveCurrent(); AreaDescription.Metadata metadata = m_curAreaDescription.GetMetadata(); metadata.m_name = kb.text; m_curAreaDescription.SaveMetadata(metadata); }); m_saveThread.Start(); } else { _SaveMarkerToDisk(); Application.LoadLevel(Application.loadedLevel); } } }
/// <summary> /// Callback function when toggle button is selected. /// </summary> /// <param name="item">Caller item object.</param> /// <param name="value">Selected value of the toggle button.</param> private void _OnToggleChanged(AreaDescription item, bool value) { if (value) { m_savedUUID = item.m_uuid; m_createSelectedButton.interactable = true; if (File.Exists(m_meshSavePath + "/" + item.m_uuid)) { m_startGameButton.interactable = true; } else { m_startGameButton.interactable = false; } } else { m_savedUUID = null; m_createSelectedButton.interactable = false; m_startGameButton.interactable = false; } }
/// <summary> /// This is called when the Area Description import operation completes. /// /// Please note that the Tango Service can only load Area Description file from internal storage. /// </summary> /// <param name="isSuccessful">If the import operation completed successfully.</param> /// <param name="areaDescription">The imported Area Description.</param> public void OnAreaDescriptionImported(bool isSuccessful, AreaDescription areaDescription) { if (!isSuccessful) { AndroidHelper.ShowAndroidToastMessage("Area Description import failed, unable to join game."); _QuitGame(); return; } // Only non-master client will run this part of code. m_loadedAreaDescription = areaDescription; m_tangoApplication.Startup(m_loadedAreaDescription); _StartPlayer(); }
/// <summary> /// Saves the current area description, returning the area description saved. /// /// You can only save an area description while connected to the Tango Service and if you have enabled Area /// Learning mode. If you loaded an area description before connecting, then calling this method appends any /// new learned areas to that area description and returns an area description with the same UUID. If you did /// not load an area description, this method creates a new area description and a new UUID for that area /// description. /// </summary> /// <returns> /// AreaDescription instance for the newly saved area description if saved successfully, <c>null</c> otherwise. /// /// See logcat for details of why a saved failed. /// </returns> public static AreaDescription SaveCurrent() { #if UNITY_EDITOR if (!EmulatedAreaDescriptionHelper.m_usingEmulatedDescriptionFrames) { Debug.LogError("Error in Area Description save emulation:\nNo current emulated area description."); return(null); } // If we don't have an existing UUID, this is a 'new' Area Description, so we'll have to create it. if (string.IsNullOrEmpty(EmulatedAreaDescriptionHelper.m_currentUUID)) { // Just use a .net GUID for the UUID. string uuid = Guid.NewGuid().ToString(); EmulatedAreaDescriptionHelper.m_currentUUID = uuid; try { Directory.CreateDirectory(EMULATED_ADF_SAVE_PATH); using (StreamWriter streamWriter = new StreamWriter(File.Open(EMULATED_ADF_SAVE_PATH + uuid + EMULATED_ADF_EXTENSION, FileMode.Create))) { Metadata metadata = new Metadata(); metadata.m_name = "Unnamed"; metadata.m_dateTime = DateTime.Now; metadata.m_transformationPosition = new double[3]; metadata.m_transformationRotation = new double[] { 0, 0, 0, 1 }; metadataXmlSerializer.Serialize(streamWriter, metadata); } } catch (IOException ioException) { Debug.LogError("IO error in Area Description save/load emulation:\n" + ioException.Message); return(null); } return(AreaDescription.ForUUID(uuid)); } else { // Since we don't actually save any description of the area in emulation, // if we're using an existing UUID, we don't have to do anything but return it. return(AreaDescription.ForUUID(EmulatedAreaDescriptionHelper.m_currentUUID)); } #else byte[] rawUUID = new byte[Common.UUID_LENGTH]; if (AreaDescriptionAPI.TangoService_saveAreaDescription(rawUUID) != Common.ErrorType.TANGO_SUCCESS) { Debug.Log("Could not save area description.\n" + Environment.StackTrace); return(null); } // Don't want to include the null terminator in the C# string. string uuid = Encoding.UTF8.GetString(rawUUID, 0, Common.UUID_LENGTH - 1); return(AreaDescription.ForUUID(uuid)); #endif }
/// <summary> /// Manual initalization step 2: Call this to connect to the Tango service. /// /// After connecting to the Tango service, you will get updates for Motion Tracking, Depth Sensing, and Area /// Learning. If you have a specific Area Description you want to localize too, pass that Area Description in /// here. /// </summary> /// <param name="areaDescription">If not null, the Area Description to localize to.</param> public void Startup(AreaDescription areaDescription) { // Make sure all required permissions have been granted. if (m_requiredPermissions != PermissionsTypes.NONE) { Debug.Log("TangoApplication.Startup() -- ERROR: Not all required permissions were accepted yet."); return; } InitApplication(); if (areaDescription != null) { InitProviders(areaDescription.m_uuid); } else { InitProviders(null); } ConnectToService(); }
/// <summary> /// Thread method to save an Area Description and marker data. Make this the ThreadFunc. /// </summary> /// <param name="xmlDataList">The marker's data list.</param> private void _AsyncDataSaving(List<MarkerData> xmlDataList) { if (xmlDataList == null) { Debug.Log("AndroidInGameController._AsyncDataSaving(): xmlDataList is null"); } if (m_tangoApplication.m_enableAreaLearning) { m_curAreaDescription = AreaDescription.SaveCurrent(); } _WriteToXml(m_curAreaDescription.m_uuid + ".xml", xmlDataList); }
/// <summary> /// Actually do the Area Description save. /// </summary> /// <returns>Coroutine IEnumerator.</returns> private IEnumerator _DoSaveAreaDescriptionAndMesh() { if (m_saveThread != null) { yield break; } // Disable interaction before saving. m_initialized = false; m_savingText.text = "Saving Area Description..."; if (string.IsNullOrEmpty(m_savedUUID)) { m_saveThread = new Thread(delegate() { // Save the Area Description to file. m_curAreaDescription = AreaDescription.SaveCurrent(); AreaDescription.Metadata metadata = m_curAreaDescription.GetMetadata(); m_savedUUID = m_curAreaDescription.m_uuid; metadata.m_name = metadata.m_dateTime.ToLongTimeString(); m_curAreaDescription.SaveMetadata(metadata); // Save the tango dynamic mesh to file. StartCoroutine(_DoSaveTangoDynamicMesh()); }); m_saveThread.Start(); } else { StartCoroutine(_DoSaveTangoDynamicMesh()); } }
/// <summary> /// Select a specific Area Description to show details. /// </summary> /// <param name="areaDescription">Area Description to show details for, or <c>null</c> if details should be hidden.</param> private void _SelectAreaDescription(AreaDescription areaDescription) { m_selectedAreaDescription = areaDescription; if (areaDescription != null) { m_selectedMetadata = areaDescription.GetMetadata(); m_detailsParent.gameObject.SetActive(true); m_detailsDate.text = m_selectedMetadata.m_dateTime.ToLongDateString() + ", " + m_selectedMetadata.m_dateTime.ToLongTimeString(); m_detailsEditableName.text = m_selectedMetadata.m_name; m_detailsEditablePosX.text = m_selectedMetadata.m_transformationPosition[0].ToString(); m_detailsEditablePosY.text = m_selectedMetadata.m_transformationPosition[1].ToString(); m_detailsEditablePosZ.text = m_selectedMetadata.m_transformationPosition[2].ToString(); m_detailsEditableRotQX.text = m_selectedMetadata.m_transformationRotation[0].ToString(); m_detailsEditableRotQY.text = m_selectedMetadata.m_transformationRotation[1].ToString(); m_detailsEditableRotQZ.text = m_selectedMetadata.m_transformationRotation[2].ToString(); m_detailsEditableRotQW.text = m_selectedMetadata.m_transformationRotation[3].ToString(); } else { m_selectedMetadata = null; m_detailsParent.gameObject.SetActive(false); } }
/// <summary> /// From button press: start creating a mesh for occlusion. /// /// If an Area Description has been selected, use it and link it to the dynamic mesh. /// If no Area Description selected, create one while meshing. /// </summary> /// <param name="createNew">If set to <c>true</c> create new mesh and new Area Description.</param> public void Button_CreateAreaDescriptionMesh(bool createNew) { m_3dReconstruction = true; m_menuOpen = false; // Enable the pose controller, but disable the AR screen. m_arPoseController.gameObject.SetActive(true); m_arPoseController.gameObject.GetComponent<TangoARScreen>().enabled = false; // Need to enable depth to build the mesh. m_tangoApplication.m_enableDepth = true; // Set UI panel to the mesh construction panel. m_areaDescriptionLoaderPanel.SetActive(false); m_meshBuildPanel.SetActive(true); m_meshInteractionPanel.SetActive(false); // Initialize tango application and pose controller depending on whether Area Description has been selected. if (createNew) { m_curAreaDescription = null; m_tangoApplication.m_areaDescriptionLearningMode = true; m_arPoseController.m_useAreaDescriptionPose = false; m_relocalizeImage.gameObject.SetActive(false); m_tangoApplication.Startup(null); } else { if (!string.IsNullOrEmpty(m_savedUUID)) { m_curAreaDescription = AreaDescription.ForUUID(m_savedUUID); m_tangoApplication.m_areaDescriptionLearningMode = false; m_arPoseController.m_useAreaDescriptionPose = true; m_relocalizeImage.gameObject.SetActive(true); m_tangoApplication.Startup(m_curAreaDescription); } else { Debug.LogError("No Area Description loaded."); } } }
/// <summary> /// Called when entering a room (by creating or joining it). Called on all clients (including the Master Client). /// </summary> /// <remarks>This method is commonly used to instantiate player characters. /// If a match has to be started "actively", you can call an [PunRPC](@ref PhotonView.RPC) triggered by a user's /// button-press or a timer. /// /// When this is called, you can usually already access the existing players in the room via /// PhotonNetwork.playerList. Also, all custom properties should be already available as Room.customProperties. /// Check Room.playerCount to find out if enough players are in the room to start playing.</remarks> public override void OnJoinedRoom() { #if UNITY_EDITOR m_tangoApplication.Startup(null); _StartPlayer(); #else if (Globals.m_curAreaDescription != null) { Directory.CreateDirectory(TEMP_FILE_PATH); Globals.m_curAreaDescription.ExportToFile(TEMP_FILE_PATH); } #endif m_loadedAreaDescription = Globals.m_curAreaDescription; }
/// <summary> /// From button press: start the game by loading the mesh and the Area Description. /// /// Generate a new mesh from the saved area definition mesh data linked to the selected Area Description. /// </summary> public void Button_StartAreaDescriptionMesh() { if (string.IsNullOrEmpty(m_savedUUID)) { AndroidHelper.ShowAndroidToastMessage("Please choose an Area Description."); return; } if (!File.Exists(m_meshSavePath + "/" + m_savedUUID)) { AndroidHelper.ShowAndroidToastMessage("Please choose an Area Description with mesh data."); return; } m_3dReconstruction = false; m_menuOpen = false; // Enable objects needed to use Area Description and mesh for occlusion. m_arPoseController.gameObject.SetActive(true); m_arPoseController.m_useAreaDescriptionPose = true; // Disable unused components in tango application. m_tangoApplication.m_areaDescriptionLearningMode = false; m_tangoApplication.m_enableDepth = false; // Set UI panel to the mesh interaction panel. m_relocalizeImage.gameObject.SetActive(true); m_areaDescriptionLoaderPanel.SetActive(false); m_meshBuildPanel.SetActive(false); m_meshInteractionPanel.SetActive(true); // Load mesh. AreaDescriptionMesh mesh = _DeserializeAreaDescriptionMesh(m_savedUUID); if (mesh == null) { return; } // Create GameObject container with mesh components for the loaded mesh. m_meshFromFile = new GameObject(); MeshFilter mf = m_meshFromFile.AddComponent<MeshFilter>(); mf.mesh = _AreaDescriptionMeshToUnityMesh(mesh); MeshRenderer mr = m_meshFromFile.AddComponent<MeshRenderer>(); mr.material = m_depthMaskMat; m_meshFromFile.AddComponent<MeshCollider>(); m_meshFromFile.layer = LayerMask.NameToLayer("Occlusion"); // Load Area Description file. m_curAreaDescription = AreaDescription.ForUUID(m_savedUUID); m_tangoApplication.Startup(m_curAreaDescription); }
/// <summary> /// Callback function when toggle button is selected. /// </summary> /// <param name="item">Caller item object.</param> /// <param name="value">Selected value of the toggle button.</param> private void _OnToggleChanged(AreaDescription item, bool value) { if (value) { m_curAreaDescriptionUUID = item.m_uuid; } }
/// <summary> /// Manual initialization step 2: Call this to connect to the Tango service. /// /// After connecting to the Tango service, you will get updates for Motion Tracking, Depth Sensing, and Area /// Learning. If you have a specific Area Description you want to localize too, pass that Area Description in /// here. /// </summary> /// <param name="areaDescription">If not null, the Area Description to localize to.</param> public void Startup(AreaDescription areaDescription) { // Make sure all required permissions have been granted. if (m_requiredPermissions != PermissionsTypes.NONE) { Debug.Log("TangoApplication.Startup() -- ERROR: Not all required permissions were accepted yet."); return; } if (!_CheckTangoVersion()) { // Error logged in _CheckTangoVersion function. return; } // Setup configs. m_tangoConfig = new TangoConfig(TangoEnums.TangoConfigType.TANGO_CONFIG_DEFAULT); m_tangoRuntimeConfig = new TangoConfig(TangoEnums.TangoConfigType.TANGO_CONFIG_RUNTIME); if (m_enableVideoOverlay && m_videoOverlayUseYUVTextureIdMethod) { int yTextureWidth = 0; int yTextureHeight = 0; int uvTextureWidth = 0; int uvTextureHeight = 0; m_tangoConfig.GetInt32(TangoConfig.Keys.EXPERIMENTAL_Y_TEXTURE_WIDTH, ref yTextureWidth); m_tangoConfig.GetInt32(TangoConfig.Keys.EXPERIMENTAL_Y_TEXTURE_HEIGHT, ref yTextureHeight); m_tangoConfig.GetInt32(TangoConfig.Keys.EXPERIMENTAL_UV_TEXTURE_WIDTH, ref uvTextureWidth); m_tangoConfig.GetInt32(TangoConfig.Keys.EXPERIMENTAL_UV_TEXTURE_HEIGHT, ref uvTextureHeight); if (yTextureWidth == 0 || yTextureHeight == 0 || uvTextureWidth == 0 || uvTextureHeight == 0) { Debug.Log("Video overlay texture sizes were not set properly"); } m_yuvTexture.ResizeAll(yTextureWidth, yTextureHeight, uvTextureWidth, uvTextureHeight); } if (areaDescription != null) { _InitializeMotionTracking(areaDescription.m_uuid); } else { _InitializeMotionTracking(null); } if (m_tangoConfig.SetBool(TangoConfig.Keys.ENABLE_DEPTH_PERCEPTION_BOOL, m_enableDepth) && m_tangoConfig.SetInt32(TangoConfig.Keys.DEPTH_MODE, (int)TangoConfig.DepthMode.XYZC) && m_enableDepth) { DepthListener.SetCallback(); } if (m_tangoConfig.SetBool(TangoConfig.Keys.ENABLE_COLOR_CAMERA_BOOL, m_enableVideoOverlay) && m_enableVideoOverlay) { _SetVideoOverlayCallbacks(); } TangoEventListener.SetCallback(); if (m_enable3DReconstruction) { Register(m_tango3DReconstruction); } _TangoConnect(); }