Пример #1
0
        private void RaycastAllObjectsNoTerrains(Ray ray, List <GameObjectRayHit> objectHits)
        {
            bool canPickMeshObjects = !IsObjectPickMaskFlagSet(MouseCursorObjectPickFlags.ObjectMesh);
            bool canPickBoxes       = !IsObjectPickMaskFlagSet(MouseCursorObjectPickFlags.ObjectBox);
            bool canPickSprites     = !IsObjectPickMaskFlagSet(MouseCursorObjectPickFlags.ObjectSprite);

            if (canPickMeshObjects && canPickBoxes && canPickSprites)
            {
                List <GameObjectRayHit> objectMeshHits = Octave3DScene.Get().RaycastAllMesh(ray);
                if (objectMeshHits.Count != 0)
                {
                    objectHits.AddRange(objectMeshHits);
                }

                List <GameObjectRayHit> objectBoxHits = Octave3DScene.Get().RaycastAllBox(ray);
                objectBoxHits.RemoveAll(item => item.HitObject.HasMesh() || item.HitObject.HasSpriteRendererWithSprite());
                if (objectBoxHits.Count != 0)
                {
                    objectHits.AddRange(objectBoxHits);
                }

                List <GameObjectRayHit> objectSpriteHits = Octave3DScene.Get().RaycastAllSprite(ray);
                objectSpriteHits.RemoveAll(item => item.HitObject.HasMesh() || item.HitObject.GetComponent <SpriteRenderer>().IsPixelFullyTransparent(item.HitPoint));
                if (objectSpriteHits.Count != 0)
                {
                    objectHits.AddRange(objectSpriteHits);
                }
            }
            else
            {
                if (!IsObjectPickMaskFlagSet(MouseCursorObjectPickFlags.ObjectMesh))
                {
                    List <GameObjectRayHit> objectMeshHits = Octave3DScene.Get().RaycastAllMesh(ray);
                    if (objectMeshHits.Count != 0)
                    {
                        objectHits.AddRange(objectMeshHits);
                    }
                }

                if (!IsObjectPickMaskFlagSet(MouseCursorObjectPickFlags.ObjectSprite))
                {
                    List <GameObjectRayHit> objectSpriteHits = Octave3DScene.Get().RaycastAllSprite(ray);
                    objectSpriteHits.RemoveAll(item => objectHits.Contains(item) || item.HitObject.GetComponent <SpriteRenderer>().IsPixelFullyTransparent(item.HitPoint));
                    if (objectSpriteHits.Count != 0)
                    {
                        objectHits.AddRange(objectSpriteHits);
                    }
                }

                if (!IsObjectPickMaskFlagSet(MouseCursorObjectPickFlags.ObjectBox))
                {
                    List <GameObjectRayHit> objectBoxHits = Octave3DScene.Get().RaycastAllBox(ray);
                    objectBoxHits.RemoveAll(item => objectHits.Contains(item));
                    if (objectBoxHits.Count != 0)
                    {
                        objectHits.AddRange(objectBoxHits);
                    }
                }
            }
        }
Пример #2
0
        public static List <GameObject> Duplicate(IEnumerable <GameObject> sourceObjects)
        {
            List <GameObject> sourceParents = Octave3DWorldBuilder.ActiveInstance.GetRoots(sourceObjects);

            var clonedObjects = new List <GameObject>();

            foreach (GameObject parent in sourceParents)
            {
                GameObject prefab          = parent.GetSourcePrefab();
                Transform  parentTransform = parent.transform;

                if (prefab == null)
                {
                    GameObject clonedParent = parent.CloneAsWorkingObject(parentTransform.parent);
                    //clonedParent.transform.parent = parent.transform.parent;
                    clonedObjects.AddRange(clonedParent.GetAllChildrenIncludingSelf());
                    Octave3DScene.Get().RegisterObjectHierarchy(clonedParent);
                }
                else
                {
                    GameObject clonedParent = ObjectInstantiation.InstantiateObjectHierarchyFromPrefab(prefab, parentTransform.position, parentTransform.rotation, parentTransform.lossyScale);
                    clonedObjects.AddRange(clonedParent.GetAllChildrenIncludingSelf());
                    Octave3DScene.Get().RegisterObjectHierarchy(clonedParent);
                }
            }

            SceneViewCamera.Instance.SetObjectVisibilityDirty();
            return(clonedObjects);
        }
Пример #3
0
 private void RenderRefreshSceneButton()
 {
     if (GUILayout.Button(GetContentForRefreshSceneButton(), GUILayout.Width(EditorGUILayoutEx.PreferedActionButtonWidth * 0.45f)))
     {
         Octave3DScene.Get().Refresh(true);
     }
 }
Пример #4
0
        private void PlaceObjectFromPlacementGuide(bool checkForIntersection)
        {
            ObjectPlacementGuide placementGuide      = ObjectPlacementGuide.Instance;
            GameObject           placedHierarchyRoot = null;

            OrientedBox       guideHierarchyWorldOrientedBox = ObjectPlacementGuide.SceneObject.GetHierarchyWorldOrientedBox();
            List <GameObject> intersectingObjects            = ObjectQueries.GetIntersectingObjects(guideHierarchyWorldOrientedBox, new List <GameObject> {
                _strokeSurface.SurfaceObject
            }, true);

            if (!checkForIntersection || ObjectPlacementSettings.Get().ObjectIntersectionSettings.AllowIntersectionForDecorPaintSingleModeDrag ||
                intersectingObjects.Count == 0)
            {
                placedHierarchyRoot = Octave3DScene.Get().InstantiateObjectHierarchyFromPrefab(placementGuide.SourcePrefab, placementGuide.gameObject.transform);
                ObjectHierarchyRootsWerePlacedInSceneMessage.SendToInterestedListeners(placedHierarchyRoot, ObjectHierarchyRootsWerePlacedInSceneMessage.PlacementType.ObjectPlacement);

                List <GameObject> allPlacedObjects = placedHierarchyRoot.GetAllChildrenIncludingSelf();
                _objectsPlacedWhileDragging.AddRange(allPlacedObjects);
                DecorPaintObjectPlacement.Get().DecorPaintMask.ObjectCollectionMask.Mask(allPlacedObjects);
            }

            _orientedBoxOfLastPlacedHierarchy = ObjectPlacementGuide.SceneObject.GetHierarchyWorldOrientedBox();
            _pivotPointsOfLastPlacedHierarchy.FromOrientedBoxAndDecorStrokeSurface(_orientedBoxOfLastPlacedHierarchy, _strokeSurface);

            if (DecorPaintObjectPlacementSettings.Get().SingleDecorPaintModeSettings.RandomizePrefabsInActiveCategory)
            {
                PrefabCategory activePrefabCategory = PrefabCategoryDatabase.Get().ActivePrefabCategory;
                if (activePrefabCategory != null)
                {
                    activePrefabCategory.RandomizeActivePrefab();
                }
            }
        }
Пример #5
0
        private void PlaceBlock()
        {
            List <GameObject> placedHierarchyRoots = Octave3DScene.Get().InstantiateObjectHirarchiesFromPlacementDataCollection(_objectPlacementBlock.EndManualConstruction());

            ObjectHierarchyRootsWerePlacedInSceneMessage.SendToInterestedListeners(placedHierarchyRoots, ObjectHierarchyRootsWerePlacedInSceneMessage.PlacementType.ObjectPlacement);
            ObjectPlacementGuide.Active = true;
        }
Пример #6
0
        private void PlaceObjects()
        {
            if (CanPlaceObjectsOnHoveredSurface())
            {
                var placementDataInstances             = _objectPlacementDataCalculator.Calculate(RotationToApplyForStrokeAlignment);
                List <GameObject> placedHierarchyRoots = Octave3DScene.Get().InstantiateObjectHirarchiesFromPlacementDataCollection(placementDataInstances);
                for (int rootIndex = 0; rootIndex < placedHierarchyRoots.Count; ++rootIndex)
                {
                    GameObject root = placedHierarchyRoots[rootIndex];
                    if (placementDataInstances[rootIndex].MustEmbedInSurface)
                    {
                        if (_strokeSurface.Type == DecorPaintStrokeSurfaceType.Terrain)
                        {
                            root.EmbedInSurfaceByVertex(-Vector3.up, _strokeSurface.SurfaceObject);
                        }
                        else if (_strokeSurface.Type == DecorPaintStrokeSurfaceType.Mesh)
                        {
                            root.EmbedInSurfaceByVertex(-_strokeSurface.Plane.normal, _strokeSurface.SurfaceObject);
                        }
                    }
                }

                List <GameObject> allPlacedObjects = GameObjectExtensions.GetAllObjectsInHierarchyCollection(placedHierarchyRoots);
                _objectsPlacedWhileDragging.AddRange(allPlacedObjects);
                DecorPaintObjectPlacement.Get().DecorPaintMask.ObjectCollectionMask.Mask(allPlacedObjects);

                ObjectHierarchyRootsWerePlacedInSceneMessage.SendToInterestedListeners(placedHierarchyRoots, ObjectHierarchyRootsWerePlacedInSceneMessage.PlacementType.ObjectPlacement);
            }

            RegisterPlacementPoint();
        }
Пример #7
0
        public static GameObject ReplaceGameObjectHierarchyPrefab(GameObject gameObject, GameObject newPrefab)
        {
            if (gameObject == null || PrefabUtility.GetPrefabType(newPrefab) != PrefabType.Prefab)
            {
                return(null);
            }

            // Store any needed object data
            OrientedBox originalWorldOrientedBox = gameObject.GetHierarchyWorldOrientedBox();

            if (originalWorldOrientedBox.IsInvalid())
            {
                return(null);
            }
            int  originalObjectLayer = gameObject.layer;
            bool isObjectStatic      = gameObject.isStatic;

            Transform  originalObjectTransform = gameObject.transform;
            Vector3    worldScale    = originalObjectTransform.lossyScale;
            Quaternion worldRotation = originalObjectTransform.rotation;

            // Create a new game object from the specified prefab
            GameObject newObject = PrefabUtility.InstantiatePrefab(newPrefab) as GameObject;

            if (newObject != null)
            {
                // Register the created object for Undo and set its transform data. Also store any significant
                // data that the original object had before it was destroyed.
                UndoEx.RegisterCreatedGameObject(newObject);
                Transform newObjectTransform = newObject.transform;
                newObjectTransform.localScale = worldScale;
                newObjectTransform.rotation   = worldRotation;
                newObjectTransform.parent     = originalObjectTransform.transform.parent;
                newObject.SetSelectedHierarchyWireframeHidden(ObjectPlacementSettings.Get().HideWireframeWhenPlacingObjects);
                newObject.layer    = originalObjectLayer;
                newObject.isStatic = isObjectStatic;

                // We will adjust the new object's position such that its center is the same as the
                // one the original object had. This produces better results especially when the new
                // object is a multi-level object hierarchy.
                OrientedBox newHierarchyWorldOrientedBox = newObject.GetHierarchyWorldOrientedBox();
                if (newHierarchyWorldOrientedBox.IsInvalid())
                {
                    GameObject.DestroyImmediate(newObject);
                    return(null);
                }
                newObjectTransform.position = ObjectPositionCalculator.CalculateObjectHierarchyPosition(newPrefab, originalWorldOrientedBox.Center, worldScale, worldRotation);

                // We will also inform the scene that a new object was created so that all the necessary steps can be performed
                Octave3DScene.Get().RegisterObjectHierarchy(newObject);

                // Destroy the old object
                UndoEx.DestroyObjectImmediate(gameObject);

                return(newObject);
            }

            return(null);
        }
Пример #8
0
        private List <GameObject> GetPotentiallyVisibleGameObjects()
        {
            var visibilitySphere = new CameraPotentialVisibleObjectsSphere();

            visibilitySphere.Calculate(Camera, GetViewVolume());

            return(Octave3DScene.Get().OverlapSphere(visibilitySphere.Sphere));
        }
Пример #9
0
 private bool DoesBoxPassObjectIntersectionTest(OrientedBox objectBox, GameObject prefab, TransformMatrix objectMatrix)
 {
     if (_allowObjectIntersection)
     {
         return(true);
     }
     return(!Octave3DScene.Get().BoxIntersectsAnyObjectBoxes(objectBox, new List <GameObject> {
         DecorPaintObjectPlacement.Get().DecorPaintSurfaceObject
     }, true));
 }
Пример #10
0
        public static List <GameObject> GetIntersectingObjects(OrientedBox orientedBox, bool ignoreFaceTouch)
        {
            List <GameObject> intersectingObjects = Octave3DScene.Get().OverlapBox(orientedBox);

            if (ignoreFaceTouch)
            {
                intersectingObjects.RemoveAll(item => orientedBox.AreAllBoxPointsOnOrInFrontOfAnyFacePlane(item.GetWorldOrientedBox()));
            }

            return(intersectingObjects);
        }
Пример #11
0
        public static void PerformRegistrationForOctave3DScene(Octave3DScene octave3DScene)
        {
            if (octave3DScene != null)
            {
                MessageListenerDatabase listenerDatabase = MessageListenerDatabase.Instance;
                listenerDatabase.UnregisterListener(octave3DScene);

                listenerDatabase.RegisterListenerForMessage(MessageType.ToolWasReset, octave3DScene);
                listenerDatabase.RegisterListenerForMessage(MessageType.ToolWasSelected, octave3DScene);
            }
        }
Пример #12
0
        public static void DuplicateSelection()
        {
            if (ObjectSelection.Get().NumberOfSelectedObjects == 0)
            {
                return;
            }

            ObjectSelection   objectSelection    = ObjectSelection.Get();
            List <GameObject> allSelectedObjects = objectSelection.GetAllSelectedGameObjects();
            List <GameObject> selectedParents    = GameObjectExtensions.GetParents(allSelectedObjects);

            var clonedObjects = new List <GameObject>();
            var clonedParents = new List <GameObject>();

            foreach (GameObject parent in selectedParents)
            {
                GameObject prefab          = parent.GetSourcePrefab();
                Transform  parentTransform = parent.transform;

                if (prefab == null)
                {
                    GameObject clonedParent = parent.CloneAsWorkingObject(parentTransform.parent);
                    //clonedParent.transform.parent = parent.transform.parent;
                    clonedObjects.AddRange(clonedParent.GetAllChildrenIncludingSelf());
                    Octave3DScene.Get().RegisterObjectHierarchy(clonedParent);
                    clonedParents.Add(clonedParent);
                }
                else
                {
                    GameObject clonedParent = ObjectInstantiation.InstantiateObjectHierarchyFromPrefab(prefab, parentTransform.position, parentTransform.rotation, parentTransform.lossyScale);
                    clonedObjects.AddRange(clonedParent.GetAllChildrenIncludingSelf());
                    Octave3DScene.Get().RegisterObjectHierarchy(clonedParent);
                    clonedParents.Add(clonedParent);
                }
            }

            if (clonedObjects.Count != 0)
            {
                objectSelection.Clear();
                objectSelection.AddGameObjectCollectionToSelection(clonedObjects);
                objectSelection.ObjectSelectionGizmos.OnObjectSelectionUpdated();
            }

            if (clonedParents.Count != 0)
            {
                ObjectHierarchyRootsWerePlacedInSceneMessage.SendToInterestedListeners(clonedParents, ObjectHierarchyRootsWerePlacedInSceneMessage.PlacementType.Selection);
            }

            SceneViewCamera.Instance.SetObjectVisibilityDirty();
        }
        private void PlaceObject()
        {
            ObjectPlacementGuide placementGuide      = ObjectPlacementGuide.Instance;
            GameObject           placedHierarchyRoot = Octave3DScene.Get().InstantiateObjectHierarchyFromPrefab(placementGuide.SourcePrefab, placementGuide.WorldPosition, placementGuide.WorldRotation, placementGuide.WorldScale);

            ObjectHierarchyRootsWerePlacedInSceneMessage.SendToInterestedListeners(placedHierarchyRoot, ObjectHierarchyRootsWerePlacedInSceneMessage.PlacementType.ObjectPlacement);

            if (PointAndClickObjectPlacementSettings.Get().RandomizePrefabsInActiveCategory)
            {
                PrefabCategory activePrefabCategory = PrefabCategoryDatabase.Get().ActivePrefabCategory;
                if (activePrefabCategory != null)
                {
                    activePrefabCategory.RandomizeActivePrefab();
                }
            }
        }
        private void PlaceObjects()
        {
            if (CanPlaceObjectsOnHoveredSurface())
            {
                var placementDataInstances             = _objectPlacementDataCalculator.Calculate(RotationToApplyForStrokeAlignment);
                List <GameObject> placedHierarchyRoots = Octave3DScene.Get().InstantiateObjectHirarchiesFromPlacementDataCollection(placementDataInstances);

                List <GameObject> allPlacedObjects = GameObjectExtensions.GetAllObjectsInHierarchyCollection(placedHierarchyRoots);
                _objectsPlacedWhileDragging.AddRange(allPlacedObjects);
                DecorPaintObjectPlacement.Get().DecorPaintMask.ObjectCollectionMask.Mask(allPlacedObjects);

                ObjectHierarchyRootsWerePlacedInSceneMessage.SendToInterestedListeners(placedHierarchyRoots, ObjectHierarchyRootsWerePlacedInSceneMessage.PlacementType.ObjectPlacement);
            }

            RegisterPlacementPoint();
        }
Пример #15
0
        public void BeginPreviewGenSession()
        {
            if (_isPreiewGenSessionActive)
            {
                return;
            }

            _sceneLightToActiveState.Clear();
            List <Light> sceneLights = Octave3DScene.Get().GetSceneLights();

            foreach (var light in sceneLights)
            {
                _sceneLightToActiveState.Add(light, light.gameObject.activeSelf);
                light.gameObject.SetActive(false);
            }

            _isPreiewGenSessionActive = true;
        }
Пример #16
0
        public GameObject MirrorGameObjectHierarchy(GameObject hierarchyRoot, Prefab sourcePrefab)
        {
            if (!IsActive)
            {
                return(null);
            }

            GameObject  mirroredHierarchyRoot     = null;
            OrientedBox hierarchyWorldOrientedBox = hierarchyRoot.GetHierarchyWorldOrientedBox();

            if (!hierarchyWorldOrientedBox.IsValid())
            {
                return(null);
            }

            OrientedBox mirroredBox = Mirroring.MirrorOrientedBox(_mirror.WorldPlane, hierarchyWorldOrientedBox, _mirrorRotation);

            if (!_allowIntersectionForMirroredObjects && ObjectQueries.IntersectsAnyObjectsInScene(mirroredBox, true))
            {
                return(null);
            }
            if (!_mirrorSpanningObjects && _mirror.WorldPlane.ClassifyOrientedBox(hierarchyWorldOrientedBox) == BoxPlaneClassificationResult.Spanning)
            {
                return(null);
            }

            Transform hierarchyRootTransform = hierarchyRoot.transform;

            if (sourcePrefab != null)
            {
                mirroredHierarchyRoot = Octave3DScene.Get().InstantiateObjectHierarchyFromPrefab(sourcePrefab, hierarchyRootTransform.position, hierarchyRootTransform.rotation, hierarchyRootTransform.lossyScale);
            }
            else
            {
                mirroredHierarchyRoot = hierarchyRoot.CloneAsWorkingObject(hierarchyRoot.transform.parent);
            }

            mirroredHierarchyRoot.ApplyTransformDataToRootChildren(hierarchyRoot);

            Mirroring.MirrorObjectHierarchyTransform(_mirror.WorldPlane, mirroredHierarchyRoot, _mirrorRotation);

            return(mirroredHierarchyRoot);
        }
Пример #17
0
        public void HandleMouseButtonDownEvent(Event e)
        {
            if (ObjectPlacementGuide.ExistsInScene && _objectPlacementPath.IsUnderManualConstruction && AllShortcutCombos.Instance.PlacePathOnClick.IsActive())
            {
                e.DisableInSceneView();
                List <GameObject> placedHierarchyRoots = Octave3DScene.Get().InstantiateObjectHirarchiesFromPlacementDataCollection(_objectPlacementPath.EndManualConstruction());
                ObjectHierarchyRootsWerePlacedInSceneMessage.SendToInterestedListeners(placedHierarchyRoots, ObjectHierarchyRootsWerePlacedInSceneMessage.PlacementType.ObjectPlacement);

                if (ObjectPlacementGuide.ExistsInScene)
                {
                    ObjectPlacementGuide.Active = true;
                }
                return;
            }

            if (_objectPlacementPath.IsUnderManualConstruction && AllShortcutCombos.Instance.ManualAttach2NewSegmentsToPath.IsActive())
            {
                e.DisableInSceneView();
                _objectPlacementPath.Attach2NewSegmentsIfUnderManualConstruction();
            }

            if (!_objectPlacementPath.IsUnderManualConstruction && AllShortcutCombos.Instance.BeginManualPathConstruction.IsActive() && e.InvolvesLeftMouseButton())
            {
                e.DisableInSceneView();

                if (ObjectPlacementGuide.ExistsInScene)
                {
                    _objectPlacementPath.SetStartObject(ObjectPlacementGuide.SceneObject);
                    _objectPlacementPath.BeginManualConstruction();
                    if (_objectPlacementPath.IsUnderManualConstruction)
                    {
                        ObjectPlacementGuide.Active = false;
                    }
                }
                else
                {
                    Debug.LogWarning("Can not begin path construction because the placement guide does not exist in the scene. Please activate a prefab to start construction.");
                }
            }
        }
Пример #18
0
        /// <summary>
        /// Registers the specified object with the tree.
        /// </summary>
        public void RegisterGameObject(GameObject gameObject)
        {
            Light[] lights = gameObject.GetComponents <Light>();
            foreach (var light in lights)
            {
                Octave3DScene.Get().RegisterSceneLight(light);
            }

            if (!CanGameObjectBeRegisteredWithTree(gameObject))
            {
                return;
            }

            // Build the object's sphere
            Box    objectWorldBox = gameObject.GetWorldBox();
            Sphere objectSphere   = objectWorldBox.GetEncpasulatingSphere();

            // Add the object as a terminal node. Also store the node in the dictionary so that we can
            // use it when it's needed.
            SphereTreeNode <GameObject> objectNode = _sphereTree.AddTerminalNode(objectSphere, gameObject);

            _gameObjectToNode.Add(gameObject, objectNode);
        }
Пример #19
0
 public static Octave3DMeshDatabase Get()
 {
     return(Octave3DScene.Get().Octave3DMeshDatabase);
 }
        public List <GameObject> GetPotentialyOverlappedGameObjects()
        {
            Sphere overlapSphere = new Sphere(Center, CalculateObjectOverlapSphereRadius());

            return(Octave3DScene.Get().OverlapSphere(overlapSphere));
        }
Пример #21
0
        public void SnapHierarchyToNearbyObjects(GameObject hierarchyRoot, ProjectedBoxFacePivotPoints projectedBoxFacePivotPoints)
        {
            Vector3 chosenSnapDestination = Vector3.zero, chosenSnapPivot = Vector3.zero;
            float   minDistance = float.MaxValue;
            float   snapEpsilon = Settings.ObjectToObjectSnapEpsilon;

            // Snapping will only work if there is at least one mesh object in the hierarchy or at least one sprite renderer
            // with a valid sprite. So we will first get that out of the way. If this condition is not met, we will just return.
            List <GameObject> meshObjectsInHierarchy   = hierarchyRoot.GetHierarchyObjectsWithMesh();
            List <GameObject> spriteObjectsInHierarchy = hierarchyRoot.GetHierarchyObjectsWithSprites();

            if (meshObjectsInHierarchy.Count == 0 && spriteObjectsInHierarchy.Count == 0)
            {
                return;
            }

            // When snapping, we will need to collect the nearby snap destination points (e.g. vertices or box corner points).
            // In order to do this we will perform an overlap test using the hierarchy's world box. The size of the box is
            // increased by 'snapEpsilon' on all axes to account for the snap espilon.
            Box hierarchyWorldBox = hierarchyRoot.GetHierarchyWorldBox();

            if (!hierarchyWorldBox.IsValid())
            {
                return;
            }
            Box hierarchyQueryBox = hierarchyWorldBox;

            hierarchyQueryBox.Size = hierarchyQueryBox.Size + Vector3.one * snapEpsilon;

            // Acquire the nearby objects that contain the possible snap destination points
            List <GameObject> nearbyObjects = Octave3DScene.Get().OverlapBox(hierarchyQueryBox);

            if (nearbyObjects.Count == 0)
            {
                return;
            }

            // If the user chose vertex snapping, we will only continue if we have at least one mesh in our hierarchy.
            // Otherwise we will resort to box snapping.
            if (Settings.ObjectToObjectSnapMode == ObjectToObjectSnapMode.Vertex && meshObjectsInHierarchy.Count != 0)
            {
                foreach (GameObject gameObject in nearbyObjects)
                {
                    Box objectWorldBox = Box.GetInvalid();

                    // We will first attempt to retrieve the mesh's world box
                    Mesh objectMesh    = gameObject.GetMeshFromFilterOrSkinnedMeshRenderer();
                    bool objectHasMesh = objectMesh != null;

                    Octave3DMesh objectOctave3DMesh = Octave3DMeshDatabase.Get().GetOctave3DMesh(objectMesh);
                    if (objectOctave3DMesh == null)
                    {
                        objectHasMesh = false;
                    }
                    if (objectHasMesh)
                    {
                        objectWorldBox = gameObject.GetMeshWorldBox();
                    }

                    // If the world box is still invalid, we will acquire the object's sprite world box.
                    if (objectWorldBox.IsInvalid())
                    {
                        if (gameObject.HasSpriteRendererWithSprite())
                        {
                            objectWorldBox = gameObject.GetNonMeshWorldBox();
                        }
                    }

                    // If at this point the box is still invalid, it most likely means that the object doesn't have
                    // a mesh or a sprite attached to it, so we will go on to the next iteration of the loop.
                    if (objectWorldBox.IsInvalid())
                    {
                        continue;
                    }

                    Box objectQueryBox = objectWorldBox;
                    objectQueryBox.Size += Vector3.one * snapEpsilon;

                    // At this point, we have a valid world box, but we need to check if it comes from a mesh or from
                    // a sprite. If it's from a mesh, we will perform the vertex-to-vertex snap. Otherwise, we will
                    // snap the vertices of all meshes in our hierarchy to the corner points of the sprite.
                    if (objectHasMesh)
                    {
                        // Detect the object vertices which are overlapped by the hierarchy box
                        List <Vector3> objectOverlappedVerts = objectOctave3DMesh.GetOverlappedWorldVerts(hierarchyQueryBox, gameObject.transform.GetWorldMatrix());

                        // Loop through all meshes in the hierarchy
                        foreach (var meshObjInHierarchy in meshObjectsInHierarchy)
                        {
                            Mesh hierarchyMesh = meshObjInHierarchy.GetMeshFromFilterOrSkinnedMeshRenderer();
                            if (hierarchyMesh == null)
                            {
                                continue;
                            }

                            Octave3DMesh hierarchyOctave3DMesh = Octave3DMeshDatabase.Get().GetOctave3DMesh(hierarchyMesh);
                            if (hierarchyOctave3DMesh == null)
                            {
                                continue;
                            }

                            // Detect all vertices inside the mesh which are overlapped by the object's box (inverse operation of what we performed in the
                            // beginning). The idea is to collect all source vertices that could pottentially intersect with each other.
                            List <Vector3> hierarchyMeshOverlappedVerts = hierarchyOctave3DMesh.GetOverlappedWorldVerts(objectQueryBox, meshObjInHierarchy.transform.GetWorldMatrix());
                            foreach (Vector3 hierarchyVertex in hierarchyMeshOverlappedVerts)
                            {
                                foreach (Vector3 objectVertex in objectOverlappedVerts)
                                {
                                    float distance = (hierarchyVertex - objectVertex).magnitude;
                                    if (distance < minDistance)
                                    {
                                        minDistance           = distance;
                                        chosenSnapDestination = objectVertex;
                                        chosenSnapPivot       = hierarchyVertex;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        List <Vector3> spriteWorldCornerPoints = objectWorldBox.GetCornerPoints();
                        foreach (var meshObjInHierarchy in meshObjectsInHierarchy)
                        {
                            Mesh hierarchyMesh = meshObjInHierarchy.GetMeshFromFilterOrSkinnedMeshRenderer();
                            if (hierarchyMesh == null)
                            {
                                continue;
                            }

                            Octave3DMesh hierarchyOctave3DMesh = Octave3DMeshDatabase.Get().GetOctave3DMesh(hierarchyMesh);
                            if (hierarchyOctave3DMesh == null)
                            {
                                continue;
                            }

                            List <Vector3> hierarchyMeshOverlappedVerts = hierarchyOctave3DMesh.GetOverlappedWorldVerts(objectQueryBox, meshObjInHierarchy.transform.GetWorldMatrix());
                            foreach (Vector3 hierarchyVertex in hierarchyMeshOverlappedVerts)
                            {
                                foreach (Vector3 spriteCornerPt in spriteWorldCornerPoints)
                                {
                                    float distance = (hierarchyVertex - spriteCornerPt).magnitude;
                                    if (distance < minDistance)
                                    {
                                        minDistance           = distance;
                                        chosenSnapDestination = spriteCornerPt;
                                        chosenSnapPivot       = hierarchyVertex;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                List <Vector3> hierarchyBoxCornerPoints = hierarchyWorldBox.GetCornerPoints();
                foreach (GameObject gameObject in nearbyObjects)
                {
                    Box objectWorldBox = Box.GetInvalid();

                    Mesh objectMesh = gameObject.GetMeshFromFilterOrSkinnedMeshRenderer();
                    if (objectMesh != null)
                    {
                        objectWorldBox = gameObject.GetMeshWorldBox();
                    }
                    if (objectWorldBox.IsInvalid() && gameObject.HasSpriteRendererWithSprite())
                    {
                        objectWorldBox = gameObject.GetNonMeshWorldBox();
                    }

                    if (objectWorldBox.IsInvalid())
                    {
                        continue;
                    }

                    List <Vector3> worldBoxCornerPoints = objectWorldBox.GetCornerPoints();
                    foreach (Vector3 hierarchyBoxPt in hierarchyBoxCornerPoints)
                    {
                        foreach (Vector3 objectMeshBoxPt in worldBoxCornerPoints)
                        {
                            float distance = (hierarchyBoxPt - objectMeshBoxPt).magnitude;
                            if (distance < minDistance)
                            {
                                minDistance           = distance;
                                chosenSnapDestination = objectMeshBoxPt;
                                chosenSnapPivot       = hierarchyBoxPt;
                            }
                        }
                    }
                }
            }

            if (minDistance < snapEpsilon)
            {
                SnapObjectHierarchyPosition(hierarchyRoot, chosenSnapPivot, chosenSnapDestination, projectedBoxFacePivotPoints, 0.0f);
            }
        }
Пример #22
0
        public List <ObjectPlacementData> Calculate()
        {
            if (_block == null || _block.NumberOfSegments == 0 || !ObjectPlacementGuide.ExistsInScene)
            {
                return(new List <ObjectPlacementData>());
            }

            Prefab     placementGuidePrefab        = ObjectPlacementGuide.Instance.SourcePrefab;
            Vector3    placementGuideWorldScale    = ObjectPlacementGuide.Instance.WorldScale;
            Quaternion placementGuideWorldRotation = ObjectPlacementGuide.Instance.WorldRotation;
            float      objectMissChance            = _block.Settings.ManualConstructionSettings.ObjectMissChance;
            ObjectRotationRandomizationSettings blockObjectRotationRandomizationSettings = _block.Settings.ManualConstructionSettings.ObjectRotationRandomizationSettings;
            bool           randomizeRotations = blockObjectRotationRandomizationSettings.RandomizeRotation;
            Vector3        objectOffsetAlongExtensionPlaneNormal = _block.Settings.ManualConstructionSettings.OffsetAlongGrowDirection * _block.ExtensionPlane.normal;
            bool           allowObjectIntersection = ObjectPlacementSettings.Get().ObjectIntersectionSettings.AllowIntersectionForBlockPlacement;
            bool           randomizePrefabs        = _block.Settings.ManualConstructionSettings.RandomizePrefabs;
            PrefabCategory activePrefabCategory    = PrefabCategoryDatabase.Get().ActivePrefabCategory;
            ObjectPlacementBlockProjectionSettings projectionSettings = _block.Settings.BlockProjectionSettings;
            bool canProject = projectionSettings.ProjectOnSurface &&
                              (projectionSettings.CanProjectOnMesh || projectionSettings.CanProjectOnTerrain);

            var objectPlacementDataInstances = new List <ObjectPlacementData>(_block.NumberOfSegments * 10);

            for (int segmentIndex = 0; segmentIndex < _block.NumberOfSegments; ++segmentIndex)
            {
                ObjectPlacementBoxStackSegment segment = _block.GetSegmentByIndex(segmentIndex);
                for (int stackIndex = 0; stackIndex < segment.NumberOfStacks; ++stackIndex)
                {
                    ObjectPlacementBoxStack stack = segment.GetStackByIndex(stackIndex);
                    if (stack.IsOverlappedByAnotherStack || stack.NumberOfBoxes == 0)
                    {
                        continue;
                    }

                    Vector3          projectionOffset     = Vector3.zero;
                    Vector3          projectionDirection  = Vector3.zero;
                    Quaternion       prjAlignRotation     = Quaternion.identity;
                    GameObjectRayHit projectionSurfaceHit = null;

                    if (canProject)
                    {
                        Vector3 rayOrigin = stack.GetBoxByIndex(0).Center;
                        Vector3 rayDir    = Vector3.zero;

                        if (projectionSettings.ProjectionDirection == ObjectBlockProjectionDir.BlockUp)
                        {
                            rayDir = _block.ExtensionPlane.normal;
                        }
                        else
                        {
                            rayDir = -_block.ExtensionPlane.normal;
                        }

                        projectionDirection = rayDir;

                        Ray ray = new Ray(rayOrigin, rayDir);
                        GameObjectRayHit closestMeshHit    = null;
                        GameObjectRayHit closestTerrainHit = null;

                        if (projectionSettings.CanProjectOnMesh)
                        {
                            closestMeshHit = Octave3DScene.Get().RaycastAllMeshClosest(ray);
                        }
                        if (projectionSettings.CanProjectOnTerrain)
                        {
                            closestTerrainHit = Octave3DScene.Get().RaycastAllTerainsClosest(ray);
                        }

                        // Ignore stack if no surface was found and non-projectables must be rejected
                        if (closestMeshHit == null && closestTerrainHit == null)
                        {
                            if (projectionSettings.RejectNonProjectables)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            projectionSurfaceHit = closestMeshHit;
                            if (closestMeshHit == null || (closestTerrainHit != null && closestMeshHit.HitEnter > closestTerrainHit.HitEnter))
                            {
                                projectionSurfaceHit = closestTerrainHit;
                            }
                        }

                        if (projectionSurfaceHit != null)
                        {
                            ObjectPlacementBox projectionBox = stack.GetBoxByIndex(0);
                            projectionOffset = projectionSurfaceHit.HitPoint - stack.GetBoxByIndex(0).Center;

                            if (projectionOffset.sqrMagnitude > (projectionSurfaceHit.HitPoint - stack.GetBoxByIndex(stack.NumberOfBoxes - 1).Center).sqrMagnitude)
                            {
                                projectionBox    = stack.GetBoxByIndex(stack.NumberOfBoxes - 1);
                                projectionOffset = projectionSurfaceHit.HitPoint - projectionBox.Center;
                            }

                            if (!projectionSettings.AlignToSurfaceNormal)
                            {
                                var     oobb      = projectionBox.OrientedBox;
                                Vector3 oldCenter = oobb.Center;
                                GameObjectExtensions.EmbedObjectBoxInSurface(oobb, projectionDirection, projectionSurfaceHit.HitObject);
                                projectionOffset = oobb.Center - oldCenter;
                            }
                        }
                    }

                    for (int stackBoxIndex = 0; stackBoxIndex < stack.NumberOfBoxes; ++stackBoxIndex)
                    {
                        ObjectPlacementBox box = stack.GetBoxByIndex(stackBoxIndex);
                        if (box.IsHidden)
                        {
                            continue;
                        }

                        if (ObjectPlacementMissChance.Missed(objectMissChance, ObjectPlacementBlockManualConstructionSettings.MinObjectMissChance,
                                                             ObjectPlacementBlockManualConstructionSettings.MaxObjectMissChance))
                        {
                            continue;
                        }

                        if (!allowObjectIntersection && ObjectQueries.IntersectsAnyObjectsInScene(box.OrientedBox, true))
                        {
                            continue;
                        }

                        Quaternion worldRotation = placementGuideWorldRotation;
                        if (randomizeRotations)
                        {
                            worldRotation = ObjectRotationRandomization.GenerateRandomRotationQuaternion(blockObjectRotationRandomizationSettings);
                        }

                        Vector3 worldScale = placementGuideWorldScale;
                        Prefab  prefab     = placementGuidePrefab;
                        if (randomizePrefabs && activePrefabCategory.NumberOfPrefabs != 0)
                        {
                            int    randomPrefabIndex = UnityEngine.Random.Range(0, activePrefabCategory.NumberOfPrefabs);
                            Prefab randomPrefab      = activePrefabCategory.GetPrefabByIndex(randomPrefabIndex);
                            if (randomPrefab != null && randomPrefab.UnityPrefab != null)
                            {
                                prefab     = activePrefabCategory.GetPrefabByIndex(randomPrefabIndex);
                                worldScale = prefab.UnityPrefab.transform.lossyScale;
                            }
                        }

                        Vector3 boxCenter = box.Center + objectOffsetAlongExtensionPlaneNormal + projectionOffset;
                        if (projectionSurfaceHit != null)
                        {
                            if (projectionSettings.AlignToSurfaceNormal)
                            {
                                worldRotation = AxisAlignment.CalculateRotationQuaternionForAxisAlignment(worldRotation, projectionSettings.AlignmentAxis, projectionSurfaceHit.HitNormal);
                                OrientedBox prefabWorldOOBB = prefab.UnityPrefab.GetHierarchyWorldOrientedBox();
                                Vector3     oobbSize        = prefabWorldOOBB.ScaledSize;
                                int         axisIndex       = (int)((int)(projectionSettings.AlignmentAxis) * 0.5f);
                                boxCenter = projectionSurfaceHit.HitPoint + projectionSurfaceHit.HitNormal * oobbSize[axisIndex] * 0.5f + (oobbSize[axisIndex] * stackBoxIndex * projectionSurfaceHit.HitNormal);
                            }
                        }

                        var objectPlacementData = new ObjectPlacementData();
                        objectPlacementData.WorldPosition = ObjectPositionCalculator.CalculateObjectHierarchyPosition(prefab, boxCenter, worldScale, worldRotation);
                        objectPlacementData.WorldScale    = worldScale;
                        objectPlacementData.WorldRotation = worldRotation;
                        objectPlacementData.Prefab        = prefab;
                        objectPlacementDataInstances.Add(objectPlacementData);
                    }
                }
            }

            return(objectPlacementDataInstances);
        }
Пример #23
0
        public static SnapResult Snap(List <GameObject> roots, float snapEpsilon, List <GameObject> ignoreDestSnapObjects)
        {
            if (ignoreDestSnapObjects == null)
            {
                ignoreDestSnapObjects = new List <GameObject>();
            }

            Vector3 snapDestPt = Vector3.zero, snapPivotPt = Vector3.zero;
            float   minSnapDistance = float.MaxValue;

            List <GameObject> allSourceObjects = new List <GameObject>();

            foreach (var root in roots)
            {
                allSourceObjects.AddRange(root.GetAllChildrenIncludingSelf());
            }

            foreach (var hierarchyRoot in roots)
            {
                List <GameObject> sourceObjects = hierarchyRoot.GetAllChildrenIncludingSelf();
                if (sourceObjects.Count > MaxSourceObjects)
                {
                    continue;
                }

                List <GameObject> meshObjectsInHierarchy   = hierarchyRoot.GetHierarchyObjectsWithMesh();
                List <GameObject> spriteObjectsInHierarchy = hierarchyRoot.GetHierarchyObjectsWithSprites();
                if (meshObjectsInHierarchy.Count == 0 && spriteObjectsInHierarchy.Count == 0)
                {
                    return(SnapResult.GetWasNotSnapped());
                }

                var object2ObjectSnapDatabase = Object2ObjectBoxSnapDatabase.Instance;
                if (sourceObjects.Count > 1 || spriteObjectsInHierarchy.Count == 0)
                {
                    foreach (var sourceObject in sourceObjects)
                    {
                        Box queryBox = sourceObject.GetWorldBox();
                        queryBox.Size = queryBox.Size + Vector3.one * snapEpsilon;

                        List <GameObject> nearbyObjects = Octave3DScene.Get().OverlapBox(queryBox);
                        if (nearbyObjects.Count == 0)
                        {
                            return(SnapResult.GetWasNotSnapped());
                        }
                        nearbyObjects.RemoveAll(item => allSourceObjects.Contains(item) ||
                                                ignoreDestSnapObjects.Contains(item));

                        Object2ObjectBoxSnapData sourceSnapData = object2ObjectSnapDatabase.GetObject2ObjectBoxSnapData(sourceObject);
                        if (sourceSnapData == null)
                        {
                            continue;
                        }

                        var sourceSnapBoxes = sourceSnapData.GetWorldSnapBoxes();
                        foreach (var destObject in nearbyObjects)
                        {
                            Object2ObjectBoxSnapData destSnapData = object2ObjectSnapDatabase.GetObject2ObjectBoxSnapData(destObject);
                            if (destSnapData == null)
                            {
                                continue;
                            }

                            var destSnapBoxes = destSnapData.GetWorldSnapBoxes();

                            foreach (var sourceSnapBox in sourceSnapBoxes)
                            {
                                var sourceBoxPoints = sourceSnapBox.GetCenterAndCornerPoints();
                                foreach (var destSnapBox in destSnapBoxes)
                                {
                                    var destBoxPoints = destSnapBox.GetCenterAndCornerPoints();
                                    foreach (var srcPt in sourceBoxPoints)
                                    {
                                        foreach (var destPt in destBoxPoints)
                                        {
                                            float distance = (destPt - srcPt).magnitude;
                                            if (distance < minSnapDistance)
                                            {
                                                minSnapDistance = distance;
                                                snapDestPt      = destPt;
                                                snapPivotPt     = srcPt;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    Box hierarchyWorldAABB = hierarchyRoot.GetHierarchyWorldBox();
                    Box hierarchyQueryBox  = hierarchyWorldAABB;
                    hierarchyQueryBox.Size = hierarchyQueryBox.Size + Vector3.one * snapEpsilon;

                    List <GameObject> nearbyObjects = Octave3DScene.Get().OverlapBox(hierarchyQueryBox);
                    if (nearbyObjects.Count == 0)
                    {
                        return(SnapResult.GetWasNotSnapped());
                    }
                    nearbyObjects.RemoveAll(item => allSourceObjects.Contains(item) ||
                                            ignoreDestSnapObjects.Contains(item));

                    List <Vector3> hierarchyBoxCornerPoints = hierarchyWorldAABB.GetCornerPoints();
                    foreach (GameObject gameObject in nearbyObjects)
                    {
                        Box objectWorldBox = Box.GetInvalid();

                        Mesh objectMesh = gameObject.GetMeshFromFilterOrSkinnedMeshRenderer();
                        if (objectMesh != null)
                        {
                            objectWorldBox = gameObject.GetMeshWorldBox();
                        }
                        if (objectWorldBox.IsInvalid() && gameObject.HasSpriteRendererWithSprite())
                        {
                            objectWorldBox = gameObject.GetNonMeshWorldBox();
                        }

                        if (objectWorldBox.IsInvalid())
                        {
                            continue;
                        }

                        List <Vector3> worldBoxCornerPoints = objectWorldBox.GetCornerPoints();
                        foreach (Vector3 hierarchyBoxPt in hierarchyBoxCornerPoints)
                        {
                            foreach (Vector3 objectMeshBoxPt in worldBoxCornerPoints)
                            {
                                float distance = (hierarchyBoxPt - objectMeshBoxPt).magnitude;
                                if (distance < minSnapDistance)
                                {
                                    minSnapDistance = distance;
                                    snapDestPt      = objectMeshBoxPt;
                                    snapPivotPt     = hierarchyBoxPt;
                                }
                            }
                        }
                    }
                }
            }

            if (minSnapDistance < snapEpsilon)
            {
                foreach (var root in roots)
                {
                    ObjectHierarchySnap.Snap(root, snapPivotPt, snapDestPt);
                }
                return(new SnapResult(true, snapPivotPt, snapDestPt));
            }

            return(SnapResult.GetWasNotSnapped());
        }