Example #1
0
 private void RaycastAllTerrainObjects(Ray ray, List <GameObjectRayHit> terrainHits)
 {
     // Can we pick terrains?
     if (!IsObjectPickMaskFlagSet(MouseCursorObjectPickFlags.ObjectTerrain))
     {
         // We will use Unity's 'Physics' API for terrain picking because it is reasonable enough
         // to expect users to attach terrain colliders to their terrain objects.
         RaycastHit[] rayHits = Physics.RaycastAll(ray);
         if (rayHits.Length != 0)
         {
             // Identify all terrain colliders which were picked
             foreach (RaycastHit rayHit in rayHits)
             {
                 // Picked a terrain collider?
                 if (rayHit.collider.GetType() == typeof(TerrainCollider))
                 {
                     // Create a game object hit instance and add it to the list
                     var terrainRayHit    = new TerrainRayHit(ray, rayHit);
                     var gameObjectRayHit = new GameObjectRayHit(ray, rayHit.collider.gameObject, null, null, terrainRayHit, null);
                     terrainHits.Add(gameObjectRayHit);
                 }
             }
         }
     }
 }
 private bool ValidateGameObjectRayHit(GameObjectRayHit gameObjectRayHit)
 {
     if (gameObjectRayHit.WasBoxHit)
     {
         return(false);
     }
     return(true);
 }
 private void AcquireCursorRayHitOnStrokeStart()
 {
     if (HasCursorPickedAnything())
     {
         _strokeGameObjectRayHit = _cursorRayHit.ClosestObjectRayHit;
         _strokeGridCellRayHit   = _cursorRayHit.GridCellRayHit;
     }
 }
        public void FromGameObjectRayHit(GameObjectRayHit gameObjectRayHit)
        {
            _isValid = false;

            if (!ValidateGameObjectRayHit(gameObjectRayHit))
            {
                return;
            }
            ExtractData(gameObjectRayHit);
        }
Example #5
0
 private void ExtractData(GameObjectRayHit objectRayHit)
 {
     if (objectRayHit.WasBoxHit)
     {
         _isValid = true;
         _mouseCursorPickPoint = objectRayHit.HitPoint;
         CalculateSurfaceQuad(objectRayHit.ObjectBoxHit);
         _objectBoxSnapSurfaceGrid.FromXZOrientedQuad(_surfaceQuad);
         _type          = SnapSurfaceType.ObjectCollider;
         _surfaceObject = objectRayHit.HitObject;
     }
 }
Example #6
0
        public MouseCursorRayHit(GridCellRayHit gridCellRayHit, List <GameObjectRayHit> sortedObjectRayHits)
        {
            _gridCellRayHit      = gridCellRayHit;
            _sortedObjectRayHits = sortedObjectRayHits != null ? new List <GameObjectRayHit>(sortedObjectRayHits) : new List <GameObjectRayHit>();

            int firstLightHit          = _sortedObjectRayHits.FindIndex(item => item.HitObject.HasLight());
            int firstParticleSystemHit = _sortedObjectRayHits.FindIndex(item => item.HitObject.HasParticleSystem());

            if (firstLightHit >= 0)
            {
                _wasLightObjectHit     = true;
                _closestLightObjectHit = _sortedObjectRayHits[firstLightHit];
            }
            if (firstParticleSystemHit >= 0)
            {
                _wasParticleSystemHit           = true;
                _closestParticleSystemObjectHit = _sortedObjectRayHits[firstParticleSystemHit];
            }
        }
        private void ExtractData(GameObjectRayHit gameObjectRayHit)
        {
            _isValid = true;
            _mouseCursorPickPoint = gameObjectRayHit.HitPoint;
            _normal = gameObjectRayHit.HitNormal;

            if (gameObjectRayHit.WasTerrainHit)
            {
                _type = DecorPaintStrokeSurfaceType.Terrain;
            }
            else if (gameObjectRayHit.WasSpriteHit)
            {
                _type = DecorPaintStrokeSurfaceType.Sprite;
            }
            else
            {
                _type = DecorPaintStrokeSurfaceType.Mesh;
            }

            _surfaceObject = gameObjectRayHit.HitObject;
        }
        /// <summary>
        /// Performs a raycast and returns a list of hits for all sprite objects intersected
        /// by the ray.
        /// </summary>
        public List <GameObjectRayHit> RaycastAllSprite(Ray ray)
        {
            // First, retrieve a list of the sphere tree nodes which were hit by the ray.
            // If no nodes were hit, it means no object was hit either.
            List <SphereTreeNodeRayHit <GameObject> > allNodeHits = _sphereTree.RaycastAll(ray);

            if (allNodeHits.Count == 0)
            {
                return(new List <GameObjectRayHit>());
            }

            // Loop through all nodes which were hit by the ray. For each node, we have to detect
            // if the ray hits the sprite object.
            var gameObjectHits = new List <GameObjectRayHit>();

            foreach (SphereTreeNodeRayHit <GameObject> nodeHit in allNodeHits)
            {
                // Retrieve the object which resides in the node
                GameObject gameObject = nodeHit.HitNode.Data;
                if (gameObject == null || !gameObject.activeInHierarchy)
                {
                    continue;
                }
                if (!gameObject.HasSpriteRendererWithSprite())
                {
                    continue;
                }

                // If the ray intersects the object's sprite, add the hit to the list
                GameObjectRayHit gameObjectRayHit = null;
                if (gameObject.RaycastSprite(ray, out gameObjectRayHit))
                {
                    gameObjectHits.Add(gameObjectRayHit);
                }
            }

            return(gameObjectHits);
        }
        public void FromMouseCursorRayHit(MouseCursorRayHit cursorRayHit)
        {
            _isValid = false;

            if (!cursorRayHit.WasAnythingHit)
            {
                return;
            }

            if (cursorRayHit.WasAnObjectHit)
            {
                GameObjectRayHit objectRayHit = FindClosestHitObjectWhichCanBeUsedAsPaintSurface(cursorRayHit);
                if (objectRayHit != null && ValidateGameObjectRayHit(objectRayHit))
                {
                    ExtractData(objectRayHit);
                }
            }

            if (!_isValid && cursorRayHit.WasACellHit)
            {
                ExtractData(cursorRayHit.GridCellRayHit);
            }
        }
Example #10
0
        private void CreateSurfaceColliderProjector()
        {
            MouseCursorRayHit brushCursorRayHit = _workingBrushCircle.CursorRayHit;

            if (brushCursorRayHit.WasAnObjectHit)
            {
                GameObjectRayHit objectRayHit = brushCursorRayHit.ClosestObjectRayHit;
                if (objectRayHit.WasMeshHit)
                {
                    _surfaceColliderProjector = new PointsOnColliderProjector(objectRayHit.ObjectMeshHit.HitCollider, _workingBrushCircle.Plane);
                }
                else
                if (objectRayHit.WasTerrainHit)
                {
                    _surfaceColliderProjector = new PointsOnColliderProjector(objectRayHit.ObjectTerrainHit.HitCollider, _workingBrushCircle.Plane);
                }
                else
                if (objectRayHit.WasSpriteHit)
                {
                    _surfaceColliderProjector = new PointsOnColliderProjector(objectRayHit.ObjectSpriteHit.HitCollider, _workingBrushCircle.Plane);
                }
            }
        }
Example #11
0
        public void Update()
        {
            if (IsActive)
            {
                if (AllShortcutCombos.Instance.GrabRotateSelection.IsActive())
                {
                    _state = State.Rotating;
                }
                else if (AllShortcutCombos.Instance.GrabScaleSelection.IsActive())
                {
                    if (_state != State.Scaling)
                    {
                        _objectToWorldScale.Clear();
                        foreach (var grabbedObject in _grabbedObjects)
                        {
                            if (grabbedObject != null)
                            {
                                _objectToWorldScale.Add(grabbedObject, grabbedObject.transform.lossyScale);
                            }
                        }
                        _cursorPosAtScaleBegin = MouseCursor.Instance.Position;
                        _state = State.Scaling;
                    }
                }
                else
                {
                    // Need to reset the anchor relationships because the cursor was moved without
                    // the objects following it.
                    if (_state == State.Rotating || _state == State.Scaling)
                    {
                        _objectToPivotDir.Clear();
                        foreach (var grabbedObject in _grabbedObjects)
                        {
                            if (grabbedObject != null)
                            {
                                _objectToPivotDir.Add(grabbedObject, grabbedObject.transform.position - _surfaceHitPoint);
                            }
                        }
                    }
                    _state = State.Moving;
                }

                _currentCursorRayHit = GetCursorRayHit();
                if (!_currentCursorRayHit.WasAnythingHit)
                {
                    return;
                }

                if (_currentCursorRayHit.WasAnythingHit)
                {
                    if (_currentCursorRayHit.WasAnObjectHit)
                    {
                        _surfaceHitPoint = _currentCursorRayHit.ClosestObjectRayHit.HitPoint;
                    }
                    else
                    {
                        _surfaceHitPoint = _currentCursorRayHit.GridCellRayHit.HitPoint;
                    }
                }

                if (_state == State.Moving || _objectToSurfaceInfo.Count == 0)
                {
                    if (_currentCursorRayHit.WasAnObjectHit)
                    {
                        GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects);
                        GameObjectRayHit objectRayHit = _currentCursorRayHit.ClosestObjectRayHit;
                        foreach (var grabbedObject in _grabbedObjects)
                        {
                            if (grabbedObject == null)
                            {
                                continue;
                            }

                            Transform objectTransform = grabbedObject.transform;
                            objectTransform.position = objectRayHit.HitPoint + _objectToPivotDir[grabbedObject];
                            if (objectRayHit.WasTerrainHit)
                            {
                                Ray ray = new Ray(grabbedObject.GetHierarchyWorldOrientedBox().Center + Vector3.up, -Vector3.up);
                                GameObjectRayHit sitPointHit = null;
                                if (objectRayHit.HitObject.RaycastTerrainReverseIfFail(ray, out sitPointHit))
                                {
                                    Plane surfacePlane = new Plane(sitPointHit.HitNormal, sitPointHit.HitPoint);
                                    if (_grabSettings.AlignAxis)
                                    {
                                        AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, sitPointHit.HitNormal);
                                    }
                                    grabbedObject.PlaceHierarchyOnPlane(surfacePlane);
                                    if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis)
                                    {
                                        objectTransform.position += _grabSettings.OffsetFromSurface * sitPointHit.HitNormal;
                                    }
                                    if (_grabSettings.EmbedInSurfaceWhenNoAlign && !_grabSettings.AlignAxis)
                                    {
                                        grabbedObject.EmbedInSurfaceByVertex(-Vector3.up, objectRayHit.HitObject);
                                    }

                                    ObjectSurfaceInfo surfaceInfo = new ObjectSurfaceInfo();
                                    surfaceInfo.SurfacePlane = surfacePlane;
                                    surfaceInfo.SitPoint     = sitPointHit.HitPoint;
                                    SetObjectSurfaceInfo(grabbedObject, surfaceInfo);
                                }
                            }
                            else
                            if (objectRayHit.WasMeshHit)
                            {
                                Ray ray = new Ray(grabbedObject.GetHierarchyWorldOrientedBox().Center + objectRayHit.HitNormal * 2.0f, -objectRayHit.HitNormal);
                                GameObjectRayHit sitPointHit = null;
                                if (objectRayHit.HitObject.RaycastMeshReverseIfFail(ray, out sitPointHit))
                                {
                                    Plane surfacePlane = new Plane(sitPointHit.HitNormal, sitPointHit.HitPoint);
                                    if (_grabSettings.AlignAxis)
                                    {
                                        AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, sitPointHit.HitNormal);
                                    }
                                    grabbedObject.PlaceHierarchyOnPlane(surfacePlane);
                                    if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis)
                                    {
                                        objectTransform.position += _grabSettings.OffsetFromSurface * sitPointHit.HitNormal;
                                    }
                                    if (_grabSettings.EmbedInSurfaceWhenNoAlign && !_grabSettings.AlignAxis)
                                    {
                                        grabbedObject.EmbedInSurfaceByVertex(-sitPointHit.HitNormal, objectRayHit.HitObject);
                                    }

                                    ObjectSurfaceInfo surfaceInfo = new ObjectSurfaceInfo();
                                    surfaceInfo.SurfacePlane = surfacePlane;
                                    surfaceInfo.SitPoint     = sitPointHit.HitPoint;
                                    SetObjectSurfaceInfo(grabbedObject, surfaceInfo);
                                }
                            }
                        }
                    }
                    else
                    if (_currentCursorRayHit.WasACellHit)
                    {
                        GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects);
                        GridCellRayHit cellRayHit = _currentCursorRayHit.GridCellRayHit;
                        foreach (var grabbedObject in _grabbedObjects)
                        {
                            if (grabbedObject == null)
                            {
                                continue;
                            }

                            Transform objectTransform = grabbedObject.transform;
                            objectTransform.position = cellRayHit.HitPoint + _objectToPivotDir[grabbedObject];

                            Plane   surfacePlane = new Plane(cellRayHit.HitNormal, cellRayHit.HitPoint);
                            Vector3 sitPoint     = surfacePlane.ProjectPoint(grabbedObject.GetWorldOrientedBox().Center);

                            if (_grabSettings.AlignAxis)
                            {
                                AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, cellRayHit.HitNormal);
                            }
                            grabbedObject.PlaceHierarchyOnPlane(surfacePlane);
                            if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis)
                            {
                                objectTransform.position += _grabSettings.OffsetFromSurface * cellRayHit.HitNormal;
                            }

                            ObjectSurfaceInfo surfaceInfo = new ObjectSurfaceInfo();
                            surfaceInfo.SurfacePlane = surfacePlane;
                            surfaceInfo.SitPoint     = sitPoint;
                            SetObjectSurfaceInfo(grabbedObject, surfaceInfo);
                        }
                    }
                }
                else
                if (_state == State.Rotating)
                {
                    GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects);
                    float rotationSensitivity = _grabSettings.RotationSensitivity;
                    foreach (var grabbedObject in _grabbedObjects)
                    {
                        if (!_objectToSurfaceInfo.ContainsKey(grabbedObject))
                        {
                            continue;
                        }

                        var         surfaceInfo = _objectToSurfaceInfo[grabbedObject];
                        OrientedBox worldOOBB   = grabbedObject.GetHierarchyWorldOrientedBox();
                        grabbedObject.RotateHierarchyBoxAroundPoint(MouseCursor.Instance.OffsetSinceLastMouseMove.x * rotationSensitivity, _grabSettings.AlignAxis ? surfaceInfo.SurfacePlane.normal : Vector3.up, worldOOBB.Center);
                    }
                }
                else
                if (_state == State.Scaling)
                {
                    GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects);
                    Vector2 currentCursorPos           = MouseCursor.Instance.Position;
                    Vector2 cursorOffsetFromScaleBegin = currentCursorPos - _cursorPosAtScaleBegin;

                    float scaleFactor = 1.0f + _grabSettings.ScaleSensitivity * cursorOffsetFromScaleBegin.x;
                    foreach (var grabbedObject in _grabbedObjects)
                    {
                        if (!_objectToSurfaceInfo.ContainsKey(grabbedObject) ||
                            !_objectToWorldScale.ContainsKey(grabbedObject))
                        {
                            continue;
                        }

                        var surfaceInfo = _objectToSurfaceInfo[grabbedObject];
                        grabbedObject.SetHierarchyWorldScaleByPivotPoint(_objectToWorldScale[grabbedObject] * scaleFactor, surfaceInfo.SitPoint);
                    }
                }
            }
        }
 private void ResetStrokePickInfo()
 {
     _strokeGameObjectRayHit = null;
     _strokeGridCellRayHit   = null;
 }
 private void AdjustShapeWhenSittingOnTerrain(GameObjectRayHit objectRayHit)
 {
     Normal = Vector3.up;
     Center = objectRayHit.HitPoint;
 }
        public void Update()
        {
            if (IsActive)
            {
                _currentCursorRayHit = GetCursorRayHit();
                if (!_currentCursorRayHit.WasAnythingHit)
                {
                    return;
                }

                if (_currentCursorRayHit.WasAnObjectHit)
                {
                    GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects);
                    GameObjectRayHit objectRayHit = _currentCursorRayHit.ClosestObjectRayHit;
                    _surfaceHitPoint = objectRayHit.HitPoint;
                    foreach (var grabbedObject in _grabbedObjects)
                    {
                        if (grabbedObject == null)
                        {
                            continue;
                        }

                        Transform objectTransform = grabbedObject.transform;
                        objectTransform.position = objectRayHit.HitPoint + _objectToPivotDir[grabbedObject];
                        if (objectRayHit.WasTerrainHit)
                        {
                            Ray ray = new Ray(grabbedObject.GetHierarchyWorldOrientedBox().Center + Vector3.up, -Vector3.up);
                            GameObjectRayHit sitPointHit = null;
                            if (objectRayHit.HitObject.RaycastTerrainReverseIfFail(ray, out sitPointHit))
                            {
                                if (_grabSettings.AlignAxis)
                                {
                                    AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, sitPointHit.HitNormal);
                                }
                                grabbedObject.PlaceHierarchyOnPlane(new Plane(sitPointHit.HitNormal, sitPointHit.HitPoint));
                                if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis)
                                {
                                    objectTransform.position += _grabSettings.OffsetFromSurface * sitPointHit.HitNormal;
                                }
                                if (_grabSettings.EmbedInSurfaceWhenNoAlign && !_grabSettings.AlignAxis)
                                {
                                    grabbedObject.EmbedInSurfaceByVertex(-Vector3.up, objectRayHit.HitObject);
                                }
                            }
                        }
                        else
                        if (objectRayHit.WasMeshHit)
                        {
                            Ray ray = new Ray(grabbedObject.GetHierarchyWorldOrientedBox().Center + objectRayHit.HitNormal * 2.0f, -objectRayHit.HitNormal);
                            GameObjectRayHit sitPointHit = null;
                            if (objectRayHit.HitObject.RaycastMeshReverseIfFail(ray, out sitPointHit))
                            {
                                if (_grabSettings.AlignAxis)
                                {
                                    AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, sitPointHit.HitNormal);
                                }
                                grabbedObject.PlaceHierarchyOnPlane(new Plane(sitPointHit.HitNormal, sitPointHit.HitPoint));
                                if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis)
                                {
                                    objectTransform.position += _grabSettings.OffsetFromSurface * sitPointHit.HitNormal;
                                }
                                if (_grabSettings.EmbedInSurfaceWhenNoAlign && !_grabSettings.AlignAxis)
                                {
                                    grabbedObject.EmbedInSurfaceByVertex(-sitPointHit.HitNormal, objectRayHit.HitObject);
                                }
                            }
                        }
                    }
                }
                else
                if (_currentCursorRayHit.WasACellHit)
                {
                    GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects);
                    GridCellRayHit cellRayHit = _currentCursorRayHit.GridCellRayHit;
                    _surfaceHitPoint = cellRayHit.HitPoint;

                    foreach (var grabbedObject in _grabbedObjects)
                    {
                        if (grabbedObject == null)
                        {
                            continue;
                        }

                        Transform objectTransform = grabbedObject.transform;
                        objectTransform.position = cellRayHit.HitPoint + _objectToPivotDir[grabbedObject];

                        if (_grabSettings.AlignAxis)
                        {
                            AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, cellRayHit.HitNormal);
                        }
                        grabbedObject.PlaceHierarchyOnPlane(new Plane(cellRayHit.HitNormal, cellRayHit.HitPoint));
                        if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis)
                        {
                            objectTransform.position += _grabSettings.OffsetFromSurface * cellRayHit.HitNormal;
                        }
                    }
                }
            }
        }
        public void UpdateForMouseMovement()
        {
            if (!_isActive)
            {
                return;
            }

            if (MouseButtonStates.Instance.IsMouseButtonDown(MouseButton.Left))
            {
                _state = ObjectVertexSnapSessionState.SnapToDestination;
            }
            else
            {
                _state = ObjectVertexSnapSessionState.SelectSourceVertex;
            }

            if (_state == ObjectVertexSnapSessionState.SelectSourceVertex)
            {
                if (_sourceObjects == null || _sourceObjects.Count == 0)
                {
                    _objectMask.ObjectCollectionMask.UnmaskAll();
                    MouseCursorRayHit cursorRayHit = GetCursorRayHit();
                    if (cursorRayHit.WasAnObjectHit)
                    {
                        GameObjectRayHit objectRayHit = cursorRayHit.ClosestObjectRayHit;
                        MeshRayHit       meshRayHit   = objectRayHit.ObjectMeshHit;
                        if (meshRayHit != null)
                        {
                            Octave3DMesh octaveMesh = meshRayHit.HitMesh;

                            Triangle3D sourceTriangle = octaveMesh.GetTriangle(meshRayHit.HitTriangleIndex);
                            sourceTriangle.TransformPoints(objectRayHit.HitObject.transform.localToWorldMatrix);

                            _sourceVertex = sourceTriangle.GetPointClosestToPoint(meshRayHit.HitPoint);
                            _sourceObject = objectRayHit.HitObject;
                            _objectMask.ObjectCollectionMask.Mask(_sourceObject.transform.root.gameObject.GetAllChildrenIncludingSelf());
                        }
                        else
                        {
                            SpriteRenderer spriteRenderer = objectRayHit.HitObject.GetComponent <SpriteRenderer>();
                            if (spriteRenderer != null)
                            {
                                _sourceObject = objectRayHit.HitObject;
                                _sourceVertex = Vector3Extensions.GetClosestPointToPoint(objectRayHit.ObjectBoxHit.HitBox.GetCenterAndCornerPoints(), objectRayHit.HitPoint);
                                _objectMask.ObjectCollectionMask.Mask(_sourceObject.transform.root.gameObject.GetAllChildrenIncludingSelf());
                            }
                        }
                    }
                }
                else
                {
                    MouseCursorRayHit cursorRayHit = GetCursorRayHit();
                    if (cursorRayHit.WasAnObjectHit)
                    {
                        GameObjectRayHit objectRayHit = cursorRayHit.ClosestObjectRayHit;
                        MeshRayHit       meshRayHit   = objectRayHit.ObjectMeshHit;
                        if (meshRayHit != null)
                        {
                            Octave3DMesh octaveMesh = meshRayHit.HitMesh;

                            Triangle3D sourceTriangle = octaveMesh.GetTriangle(meshRayHit.HitTriangleIndex);
                            sourceTriangle.TransformPoints(objectRayHit.HitObject.transform.localToWorldMatrix);
                            _sourceVertex = sourceTriangle.GetPointClosestToPoint(meshRayHit.HitPoint);
                        }
                        else
                        {
                            SpriteRenderer spriteRenderer = objectRayHit.HitObject.GetComponent <SpriteRenderer>();
                            if (spriteRenderer != null)
                            {
                                _sourceVertex = Vector3Extensions.GetClosestPointToPoint(objectRayHit.ObjectBoxHit.HitBox.GetCenterAndCornerPoints(), objectRayHit.HitPoint);
                            }
                        }
                    }

                    foreach (var parent in _sourceParents)
                    {
                        _objectMask.ObjectCollectionMask.Mask(parent.GetAllChildrenIncludingSelf());
                    }
                }
            }
            else
            {
                MouseCursorRayHit cursorRayHit = GetCursorRayHit();
                if (cursorRayHit.WasAnythingHit)
                {
                    bool useGridCellHit = false;
                    if (!cursorRayHit.WasAnObjectHit)
                    {
                        useGridCellHit = true;
                    }
                    else
                    if (cursorRayHit.WasAnObjectHit && cursorRayHit.WasACellHit)
                    {
                        float gridCellHitEnter = cursorRayHit.GridCellRayHit.HitEnter;
                        float objectHitEnter   = cursorRayHit.ClosestObjectRayHit.HitEnter;
                        if (gridCellHitEnter < Mathf.Max(0.0f, (objectHitEnter - 1e-3f)))
                        {
                            useGridCellHit = true;
                        }
                    }

                    if (useGridCellHit)
                    {
                        XZGridCell       hitCell  = cursorRayHit.GridCellRayHit.HitCell;
                        XZOrientedQuad3D cellQuad = hitCell.Quad;

                        _destinationObject   = null;
                        _destinationGridCell = hitCell;

                        _snapPosition = cellQuad.GetPointClosestToPoint(cursorRayHit.GridCellRayHit.HitPoint, true);
                        SnapToDestination();
                    }
                    else
                    {
                        GameObjectRayHit objectRayHit = cursorRayHit.ClosestObjectRayHit;
                        MeshRayHit       meshRayHit   = objectRayHit.ObjectMeshHit;
                        if (meshRayHit != null)
                        {
                            _destinationObject = objectRayHit.HitObject;
                            Triangle3D destinationTriangle = meshRayHit.HitMesh.GetTriangle(meshRayHit.HitTriangleIndex);
                            destinationTriangle.TransformPoints(_destinationObject.transform.localToWorldMatrix);
                            _destinationGridCell = null;

                            _snapPosition = destinationTriangle.GetPointClosestToPoint(meshRayHit.HitPoint);
                            SnapToDestination();
                        }
                        else
                        {
                            SpriteRenderer spriteRenderer = objectRayHit.HitObject.GetComponent <SpriteRenderer>();
                            if (spriteRenderer != null)
                            {
                                _destinationGridCell = null;
                                _destinationObject   = objectRayHit.HitObject;

                                _snapPosition = Vector3Extensions.GetClosestPointToPoint(objectRayHit.ObjectBoxHit.HitBox.GetCenterAndCornerPoints(), objectRayHit.HitPoint);
                                SnapToDestination();
                            }
                        }
                    }
                }
            }
        }
Example #16
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);
        }
 private void AdjustShapeWhenSittingOnSprite(GameObjectRayHit objectRayHit)
 {
     Normal = objectRayHit.HitNormal;
     Center = objectRayHit.HitPoint;
 }