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); } } } }
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); }
private void RenderRefreshSceneButton() { if (GUILayout.Button(GetContentForRefreshSceneButton(), GUILayout.Width(EditorGUILayoutEx.PreferedActionButtonWidth * 0.45f))) { Octave3DScene.Get().Refresh(true); } }
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(); } } }
private void PlaceBlock() { List <GameObject> placedHierarchyRoots = Octave3DScene.Get().InstantiateObjectHirarchiesFromPlacementDataCollection(_objectPlacementBlock.EndManualConstruction()); ObjectHierarchyRootsWerePlacedInSceneMessage.SendToInterestedListeners(placedHierarchyRoots, ObjectHierarchyRootsWerePlacedInSceneMessage.PlacementType.ObjectPlacement); ObjectPlacementGuide.Active = true; }
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(); }
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); }
private List <GameObject> GetPotentiallyVisibleGameObjects() { var visibilitySphere = new CameraPotentialVisibleObjectsSphere(); visibilitySphere.Calculate(Camera, GetViewVolume()); return(Octave3DScene.Get().OverlapSphere(visibilitySphere.Sphere)); }
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)); }
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); }
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); } }
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(); }
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; }
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); }
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."); } } }
/// <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); }
public static Octave3DMeshDatabase Get() { return(Octave3DScene.Get().Octave3DMeshDatabase); }
public List <GameObject> GetPotentialyOverlappedGameObjects() { Sphere overlapSphere = new Sphere(Center, CalculateObjectOverlapSphereRadius()); return(Octave3DScene.Get().OverlapSphere(overlapSphere)); }
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); } }
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); }
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()); }