/// <summary> /// Update the hovered point. /// </summary> private void UpdateHoveredPoint() { var pickRay = m_application.RPickRay.GetRay(); var hitInfo = new RaycastHit(); hitInfo.distance = float.NaN; GameObject pickedGO = null; foreach (var layer in m_application.GetLayers()) { UtilUnity.PickRecursively( layer.Model, pickRay, layer.Model, ref pickedGO, ref hitInfo); } m_application.RPickRay.HitDistance = hitInfo.distance; if (pickedGO != null) { _hitInfo = hitInfo; } else { _hitInfo = null; } }
/// <summary> /// /// </summary> private void OnActiveObjectTypeChanged() { if (null != _previewGO) { UtilUnity.Destroy(_previewGO); _previewGO = null; } _previewGO = GameObject.Instantiate( ActiveObjectPrefab, Vector3.zero, Quaternion.identity); if (null != _previewGO.GetComponent<BoxCollider>()) { _previewGO.AddComponent<PlacementGuides>(); } m_application.m_leftControllerText.text = ActiveObjectPrefabDefinition.Name; m_application.m_leftControllerText.gameObject.SetActive(true); var pi = _previewGO.GetComponent<PickInitializable>(); if (pi == null) { m_application.m_leftControllerText.color = Color.red; pi = _previewGO.AddComponent<PickInitializable>(); pi.PickInitializationTypes.Add(PickInitializable.PickInitializationType.Default); } else { m_application.m_leftControllerText.color = Color.black; } }
private void OnHover(GameObject gameObject) { _hoveredObject = gameObject; if (null == gameObject) { _hoverBoxGO.gameObject.SetActive(false); } else { _hoverBoxGO.SetActive(true); var boxCollider = _hoveredObject.gameObject.GetComponent<Collider>() as BoxCollider; if (null == boxCollider) { // The top-level go does not have a box collider => compute bounds recursively. var bounds = UtilUnity.CalculateBounds(_hoveredObject); if (bounds.HasValue) { _hoverBoxGO.transform.position = bounds.Value.center; _hoverBoxGO.transform.rotation = Quaternion.identity; _hoverBox.Size = bounds.Value.size; } } else { // The top-level has a box collider => use that as input for our hoverbox definition. _hoverBoxGO.transform.position = _hoveredObject.gameObject.transform.TransformPoint(boxCollider.center); _hoverBoxGO.transform.rotation = _hoveredObject.gameObject.transform.rotation; _hoverBox.Size = boxCollider.size; } } }
/// <summary> /// <see cref="ApplicationState{T}.Exit"/> implementation. /// </summary> public override void Exit() { Pause(); //m_application.LocomotionEnabled = true; // Enable only R pickray. m_application.RPickRay.gameObject.SetActive(false); m_application.HudInfoPanel.SetActive(false); m_application.HudInfoText.text = ""; foreach (var box in _selectBoxes) { UtilUnity.Destroy(box.gameObject); } _selectBoxes.Clear(); if (null != _hoverBoxGO) { UtilUnity.Destroy(_hoverBoxGO); _hoverBoxGO = null; _hoverBox = null; } m_application.SaveProjectData(); }
/// <summary> /// <see cref="ImmersionMode.Enter()"/> implementation. /// </summary> public override void Enter() { m_application.Logger.Debug("ApplicationStateWalkthrough.Enter()"); if (m_application._teleportAreaGO == null) { m_application._teleportAreaGO = UtilUnity.FindGameObjectElseError(m_application.gameObject.scene, "TeleportArea"); var teleportAreaVolumeGO = m_application._teleportAreaGO.transform.Find("Volume"); if (teleportAreaVolumeGO == null) { m_application.Logger.Error("TeleportArea.Volume gameobject not found."); } m_application._teleportAreaVolume = teleportAreaVolumeGO.GetComponent <TeleportAreaVolume>(); if (m_application._teleportAreaVolume == null) { m_application.Logger.Error("TeleportArea.Volume: TeleportAreaVolume component not found."); } m_application._teleportAreaGO.SetActive(false); } if (activePoiReferenceSystem == null) { activePoiReferenceSystem = m_application.CreateReferenceSystem("POI", null); } Resume(); }
/// <summary> /// /// </summary> public override void UpdateModelLocationAndScale() { //Logger.Debug("ApplicationStateScaleModel.UpdateModelLocationAndScale()"); var activeProject = m_application.ActiveProject; if (activeProject == null) { return; } var scale = 0.04f; activeProject.transform.position = Vector3.zero; activeProject.transform.rotation = Quaternion.identity; activeProject.transform.localScale = scale * Vector3.one; activeProject.transform.position = m_application.OffsetPerID; // Locate around anchor. { var modelAnchor = UtilUnity.FindGameObjectElseWarn( m_application.gameObject.scene, "ModelAnchor", m_application.Logger); if (modelAnchor != null) { activeProject.transform.position -= scale * (modelAnchor.transform.localPosition - m_application.OffsetPerID); } } // Add height offset. var pos = activeProject.transform.position; pos.y = 1 + _modelOffset; activeProject.transform.position = pos; // Rotate it. activeProject.transform.RotateAround(m_application.OffsetPerID, Vector3.up, _modelRotation); foreach (var editData in m_application.EditDatas) { var t = editData.ContainerGameObject.transform; t.position = activeProject.transform.position; t.rotation = activeProject.transform.rotation; t.localScale = activeProject.transform.localScale; } }
/// <summary> /// <see cref="ApplicationState{T}.Exit"/> implementation. /// </summary> public override void Exit() { //m_application.LocomotionEnabled = true; // Enable only R pickray. m_application.RPickRay.gameObject.SetActive(false); m_application.HudInfoPanel.SetActive(false); m_application.HudInfoText.text = ""; if (null != _previewGO) { UtilUnity.Destroy(_previewGO); } }
private void OnPropertiesChanged() { foreach (var panel in _propertyPanels) { panel.transform.SetParent(null); UtilUnity.Destroy(panel); } _propertyPanels.Clear(); _yOffset = 0; foreach (var property in _properties.Properties) { CreateProperyPanel(property); } }
/// <summary> /// Deletes the selected objects. /// </summary> public void Delete() { var selectedObjects = new List<GameObject>(_selectedObjects); OnHover(null); OnSelect(null); foreach (var selectedObject in selectedObjects) { foreach (var editData in m_application.EditDatas) { if (editData.GameObjects.Contains(selectedObject)) { editData.GameObjects.Remove(selectedObject); } UtilUnity.Destroy(selectedObject); } } }
/// <summary> /// /// </summary> /// <param name="applicationInstanceIndex"></param> /// <returns></returns> private Camera GetApplicationCamera(int applicationInstanceIndex) { var tag = "GetApplicationCamera(" + applicationInstanceIndex + ")"; var cameraName = "CenterEyeAnchor(" + applicationInstanceIndex + ")"; var cameraGO = UtilUnity.TryFindGameObject(cameraName); if (cameraGO == null) { throw new Exception(tag + "GameObject '" + cameraName + "' not found!"); } var camera = cameraGO.GetComponent <Camera>(); if (camera == null) { throw new Exception(tag + "GameObject '" + cameraName + "' does not contain a 'Camera' component!"); } return(camera); }
/// <summary> /// Create an instance of the active prefab, /// position it at the location of the preview, /// and add it persistently to the project content. /// </summary> private void CreateObject() { // Create the new editable object. var objectGO = GameObject.Instantiate( ActiveObjectPrefab, _previewGO.transform.position, _previewGO.transform.rotation); var editable = objectGO.GetComponent<E>(); if (editable is IPrefabInstantiation prefabInstantiation) { prefabInstantiation.PrefabPath = ActiveObjectPrefabDefinition.PrefabPath; } else { m_application.Logger.Error("Trying to create an editable that is not an IPrefabInstantiation!" + editable.ToString()); UtilUnity.Destroy(objectGO); return; } if (editable is ILayerContent layerContent) { layerContent.LayerName = m_application.EstimateLayer(objectGO); } // Give the new editable object a unique name. objectGO.name = ActiveObjectPrefab.name + " (" + Guid.NewGuid().ToString() + ")"; // Add the new editable object to the project content. EditData.Add(objectGO); // Clear the picked points. _pickedInfos.Clear(); }
/// <summary> /// If an application instance is being initialized, and its appliction scene is fully loaded, /// performs the post-load operations to finalize the initialization. /// - Get handle to UnityApplication instance /// - Push the viewlayout to the application camera. /// - Start initialization of the next application instance. /// </summary> private IEnumerator InitializeApplicationInstances() { var tag = "EditorTestApplication.InitializeApplicationInstances()"; _activeApplicationInstanceIndex = 0; for (int applicationInstanceBeingInitializedIndex = 0; applicationInstanceBeingInitializedIndex < DefaultNumApplicationInstances; ++applicationInstanceBeingInitializedIndex) { var loadApplicationSceneOperation = SceneManager.LoadSceneAsync(ApplicationSceneName, LoadSceneMode.Additive); while (!loadApplicationSceneOperation.isDone) { yield return(null); } var applicationSceneOrig = SceneManager.GetSceneByName(ApplicationSceneName); while (applicationSceneOrig == null) { yield return(null); // Application scene not loaded yet. applicationSceneOrig = SceneManager.GetSceneByName(ApplicationSceneName); } while (!applicationSceneOrig.isLoaded) { yield return(null); // Application scene not loaded yet. } var postFix = "(" + applicationInstanceBeingInitializedIndex + ")"; // Since renaming a saved scene is not allowed, // we merge the loaded application scene into a uniquely named new scene(applicationScene). // // The originally loaded scene (applicationSceneOrig) will be destroyed automatically // by merging it into the final, uniquely named, application scene. var uniqueApplicationSceneName = applicationSceneOrig.name + postFix; var applicationScene = SceneManager.CreateScene(uniqueApplicationSceneName); SceneManager.MergeScenes(applicationSceneOrig, applicationScene); // First get the UnityApplication from the loaded application scene. UnityApplication applicationInstance = null; foreach (var go in applicationScene.GetRootGameObjects()) { applicationInstance = UtilUnity.GetFirstComponentOfType <UnityApplication>(go); if (applicationInstance != null) { break; } } if (applicationInstance == null) { throw new Exception(tag + "Loaded application scene does not contain a GameObject with a UnityApplication component!"); } // Only enable input on the first application instance. applicationInstance.ID = applicationInstanceBeingInitializedIndex; applicationInstance.EnableInput = (applicationInstanceBeingInitializedIndex == 0); ((ApplicationArchiVR)applicationInstance).EnvironmentalLighting.gameObject.SetActive(false); _applicationInstances.Add(applicationInstance); foreach (var go in applicationScene.GetRootGameObjects()) { go.transform.position += applicationInstance.OffsetPerID; } applicationScenes.Add(applicationScene); var cameraGO = GameObject.Find("CenterEyeAnchor"); if (cameraGO == null) { throw new Exception(tag + "GameObject 'CenterEyeAnchor' not found in application scene!"); } cameraGO.name = cameraGO.name + postFix; // So it is not found anymore next time. var camera = cameraGO.GetComponent <Camera>(); if (camera == null) { throw new Exception(tag + "GameObject 'CenterEyeAnchor' does not have a Camera component!"); } camera.rect = WindowPlacements[_viewLayout][applicationInstanceBeingInitializedIndex]; if (applicationInstanceBeingInitializedIndex == _activeApplicationInstanceIndex) { AttachBorderToView(applicationInstanceBeingInitializedIndex); } // Disable the default camera. GetDefaultCameraGO(applicationInstanceBeingInitializedIndex).SetActive(false); } // Now that all application scenes have been loaded, perform the startup logic on them. StartCoroutine(PerformStartupLogic()); }
private void OnSelect(GameObject gameObject) { // Remove bounding boxes from current selection. foreach (var box in _selectBoxes) { UtilUnity.Destroy(box.gameObject); } _selectBoxes.Clear(); // Update selection. if (_addToSelection) { if (null != gameObject) { if (_selectedObjects.Contains(gameObject)) { _selectedObjects.Remove(gameObject); } else { _selectedObjects.Add(gameObject); } } } else { _selectedObjects.Clear(); if (null != gameObject) { _selectedObjects.Add(gameObject); } } // Add bounding boxes for current selection. foreach (var selectedObject in _selectedObjects) { var selectedObjectBoundingBoxGO = new GameObject("SelectedObjectBoundingBox"); var selectedObjectBoundingBox = selectedObjectBoundingBoxGO.AddComponent<LineRendererBox>(); selectedObjectBoundingBox.Color = m_application.SelectionColor; selectedObjectBoundingBoxGO.SetActive(true); selectedObjectBoundingBoxGO.transform.SetParent(selectedObject.transform, false); var bounds = UtilUnity.CalculateBounds(selectedObject); if (bounds.HasValue) { selectedObjectBoundingBoxGO.transform.position = bounds.Value.center; selectedObjectBoundingBox.Size = selectedObject.transform.InverseTransformVector(bounds.Value.size); } _selectBoxes.Add(selectedObjectBoundingBox); } bool autoShowPropertiesOnSingleObjectSelected = false; if (autoShowPropertiesOnSingleObjectSelected) { ShowProperties(); } }
/// <summary> /// <see cref="ApplicationState{T}.Update"/> implementation. /// </summary> public override void Update() { UpdateControllerUI(); m_application.Fly(); m_application.UpdateTrackingSpace(); var controllerState = m_application.m_controllerInput.m_controllerState; // Setting lights as the active object type is done by: // - Pressing 'L' on the keyboard. if (Input.GetKeyDown(KeyCode.L)) { StartCreateLight(); } // Setting props as the active object type is done by: // - Pressing 'F' on the keyboard. if (Input.GetKeyDown(KeyCode.F)) { StartCreateProp(); } // Setting POI as the active object type is done by: // - Pressing 'P' on the keyboard. if (Input.GetKeyDown(KeyCode.P)) { StartCreatePOI(); } // Delete selected lights is performed by: // - Pressing the controller 'B' button. var delete = controllerState.bButtonDown; if (delete) { Delete(); } // Additive selection is enabled while: // - keeping R controller hand trigger pressed. _addToSelection = controllerState.rHandTriggerPressed; // Exiting edit mode is done by: // - Pressing left controller index trigger. var returnToParentState = controllerState.lIndexTriggerDown; if (returnToParentState) { if (!m_application.PropertiesMenuPanel.gameObject.activeSelf) { m_application.PopApplicationState(); } else { CloseProperties(); } return; } #region Update hovered object GameObject hoveredObject = null; var pickRay = m_application.RPickRay.GetRay(); foreach (var editData in m_application.EditDatas) { foreach (var gameObject in editData.GameObjects) { var hitInfo = new RaycastHit(); hitInfo.distance = float.NaN; GameObject pickedGO = null; UtilUnity.PickRecursively( gameObject, pickRay, gameObject, ref pickedGO, ref hitInfo); if (null != pickedGO) { hoveredObject = gameObject; break; } } } OnHover(hoveredObject); #endregion Update hovered object if (m_application.m_controllerInput.m_controllerState.rIndexTriggerDown) { if (!m_application.PropertiesMenuPanel.gameObject.activeSelf) // Do not select/unselect objects while properties menu is open. { OnSelect(_hoveredObject); } } }
/// <summary> /// <see cref="ApplicationState{T}.Update()"/> implementation. /// </summary> public override void Update() { //WM.Logger.Debug("ApplicationStateScaleModel.Update()"); UpdateControllerUI(); if (m_application.ToggleActiveProject()) { return; } //if (m_application.ToggleImmersionModeIfInputAndNetworkModeAllows()) //{ // return; //} // Clients cannot toggle model layer visibility! if (m_application.NetworkMode != WM.Net.NetworkMode.Client) { // Toggle model layer visibility using picking. if (m_application.m_controllerInput.m_controllerState.rIndexTriggerDown) { if (pickedLayer != null) { m_application.SetModelLayerVisible(pickedLayerIndex, !pickedLayer.activeSelf); } else { m_application.UnhideAllModelLayers(); } } } // Show name of picked model layer in right control text. m_application.m_rightControllerText.text = (pickedLayer == null) ? "" : pickedLayer.name; m_application.Fly(); #region Maquette manipulation. // Clients cannot manipulate model! if (m_application.NetworkMode != WM.Net.NetworkMode.Client) { var cs = m_application.m_controllerInput.m_controllerState; float magnitudeRotateMaquette = cs.lThumbStick.x; float magnitudeTranslateMaquette = cs.lThumbStick.y; #region Update MaquetteManipulationMode bool manipulating = (Mathf.Abs(magnitudeRotateMaquette) > 0.1f) || (Mathf.Abs(magnitudeTranslateMaquette) > 0.1f); if (maquetteManipulationMode == ModelManipulationMode.None) { if (manipulating) { maquetteManipulationMode = (Mathf.Abs(magnitudeRotateMaquette) > Mathf.Abs(magnitudeTranslateMaquette)) ? ModelManipulationMode.Rotate : ModelManipulationMode.Translate; } else { maquetteManipulationMode = ModelManipulationMode.None; } } else { if (!manipulating) { maquetteManipulationMode = ModelManipulationMode.None; } } #endregion float positionOffset = _modelOffset; float rotationOffset = _modelRotation; switch (maquetteManipulationMode) { case ModelManipulationMode.Translate: { positionOffset = Mathf.Clamp(_modelOffset + magnitudeTranslateMaquette * _modelMoveSpeed * Time.deltaTime, -1.0f, 0.6f); } break; case ModelManipulationMode.Rotate: { rotationOffset += magnitudeRotateMaquette * _modelRotateSpeed * Time.deltaTime; } break; } if (maquetteManipulationMode != ModelManipulationMode.None) { var command = new SetModelLocationCommand(positionOffset, rotationOffset); if (m_application.NetworkMode == NetworkMode.Server) { m_application.Server.BroadcastCommand(command); } else { command.Execute(m_application); } } } #endregion #region Updated picked model layer // Clients cannot pick model layers! if (m_application.NetworkMode != NetworkMode.Client) { var pickRay = m_application.RPickRay.GetRay(); var hitInfo = new RaycastHit(); hitInfo.distance = float.NaN; pickedLayer = null; foreach (var layer in m_application.GetLayers()) { UtilUnity.PickRecursively( layer.Model, pickRay, layer.Model, ref pickedLayer, ref hitInfo); } if (pickedLayer == null) { pickedLayerIndex = -1; } else { int layerIndex = 0; foreach (var layer in m_application.GetLayers()) { if (pickedLayer == layer.Model) { pickedLayerIndex = layerIndex; break; } ++layerIndex; } Debug.Assert(pickedLayerIndex != -1); } m_application.RPickRay.HitDistance = hitInfo.distance; } #endregion var controllerState = m_application.m_controllerInput.m_controllerState; // Pressing 'BackSpace' on the keyboard is a shortcut for returning to the default state. var returnToDefaultState = controllerState.lIndexTriggerDown || Input.GetKeyDown(KeyCode.Backspace); if (returnToDefaultState) { m_application.PopApplicationState(); } }