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(); } } }
public void BeginMouseRotationSession(Vector3 customRotationAxis) { if (!IsAnyMouseSessionActive) { _mouseRotationSession.BeginRotationAroundCustomAxis(gameObject, ObjectPlacementSettings.Get().ObjectPlacementGuideSettings.MouseRotationSettings, customRotationAxis); } }
public void BeginMouseRotationSession(TransformAxis rotationAxis) { if (!IsAnyMouseSessionActive) { _mouseRotationSession.BeginRotationAroundAxis(gameObject, ObjectPlacementSettings.Get().ObjectPlacementGuideSettings.MouseRotationSettings, rotationAxis); } }
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 void RenderContentInScrollView() { ObjectPlacementSettings objectPlacementSettings = ObjectPlacementSettings.Get(); EditorGUILabelWidth.Push(EditorGUILayoutEx.PreferedEditorWindowLabelWidth); objectPlacementSettings.ObjectPlacementGuideSettings.View.Render(); EditorGUILabelWidth.Pop(); }
public void BeginMouseScaleSession(Vector3 scalePivotPoint) { if (!IsAnyMouseSessionActive) { _mouseUniformScaleSession.PivotPoint = scalePivotPoint; _mouseUniformScaleSession.Begin(gameObject, ObjectPlacementSettings.Get().ObjectPlacementGuideSettings.MouseUniformScaleSettings); } }
private void OnEnable() { if (!_wasInitialized) { InitializeBrushDecorPaintStroke(); ObjectPlacementSettings.Get().DecorPaintObjectPlacementSettings.SingleDecorPaintModeSettings.PlacementGuideSurfaceAlignmentSettings.IsEnabled = true; _wasInitialized = true; } }
public static ObjectPlacementGuide InstantiateObjectPlacementGuide(Prefab prefab, string name) { GameObject guideObject = Octave3DWorldBuilder.Instantiate(prefab.UnityPrefab) as GameObject; guideObject.name = name; ObjectPlacementGuide objectPlacementGuide = guideObject.AddComponent <ObjectPlacementGuide>(); guideObject.transform.parent = Octave3DWorldBuilder.ActiveInstance.transform; guideObject.SetSelectedHierarchyWireframeHidden(ObjectPlacementSettings.Get().HideWireframeWhenPlacingObjects); return(objectPlacementGuide); }
public static List <GameObject> ReplaceSelectedObjectsPrefabOnMouseClick() { MouseCursorRayHit cursorRayHit = ObjectSelection.Get().GetObjectPickedByCursor(); if (cursorRayHit.WasAnObjectHit && !ObjectSelection.Get().IsGameObjectSelected(cursorRayHit.ClosestObjectRayHit.HitObject)) { GameObject hitObject = cursorRayHit.ClosestObjectRayHit.HitObject; hitObject = Octave3DWorldBuilder.ActiveInstance.GetRoot(hitObject); if (hitObject == null) { return(new List <GameObject>()); } GameObject newPrefabForSelectedObjects = hitObject.GetSourcePrefab(); if (newPrefabForSelectedObjects == null) { List <GameObject> allSelectedObjects = ObjectSelection.Get().GetAllSelectedGameObjects(); ObjectSelection.Get().RemoveGameObjectCollectionFromSelection(allSelectedObjects); List <GameObject> selectedRoots = Octave3DWorldBuilder.ActiveInstance.GetRoots(allSelectedObjects); var newObjects = new List <GameObject>(); foreach (var root in selectedRoots) { Transform rootTransform = root.transform; GameObject newObject = GameObjectExtensions.CloneAsWorkingObject(hitObject, hitObject.transform.parent, true); if (newObject != null) { Transform objectTransform = newObject.transform; objectTransform.position = rootTransform.position; objectTransform.rotation = rootTransform.rotation; objectTransform.SetWorldScale(rootTransform.lossyScale); newObject.SetSelectedHierarchyWireframeHidden(ObjectPlacementSettings.Get().HideWireframeWhenPlacingObjects); UndoEx.DestroyObjectImmediate(root); newObjects.Add(newObject); } } return(newObjects); } else { List <GameObject> allSelectedObjects = ObjectSelection.Get().GetAllSelectedGameObjects(); ObjectSelection.Get().RemoveGameObjectCollectionFromSelection(allSelectedObjects); List <GameObject> newObjects = ObjectActions.ReplaceGameObjectHierarchyCollectionPrefab(allSelectedObjects, newPrefabForSelectedObjects); newObjects.RemoveAll(item => item == null); return(newObjects); } } return(new List <GameObject>()); }
public static GameObject GetSurfaceObject() { ObjectPlacementSettings objectPlacementSettings = ObjectPlacementSettings.Get(); if (objectPlacementSettings.ObjectPlacementMode == ObjectPlacementMode.DecorPaint) { return(ObjectPlacement.Get().DecorPaintObjectPlacement.DecorPaintSurfaceObject); } else { return(ObjectSnapping.Get().ObjectSnapSurfaceObject); } }
private void AdjustBrushShapeSizeForMouseWheelScroll(Event e) { DecorPaintObjectPlacementBrush activeBrush = DecorPaintObjectPlacementBrushDatabase.Get().ActiveBrush; if (activeBrush != null) { BrushDecorPaintModeObjectPlacementSettings brushDecorPaintSettings = ObjectPlacementSettings.Get().DecorPaintObjectPlacementSettings.BrushDecorPaintModeSettings; int sizeAdjustAmount = (int)(-e.delta.y * brushDecorPaintSettings.ScrollWheelCircleRadiusAdjustmentSpeed); UndoEx.RecordForToolAction(activeBrush); activeBrush.Radius += sizeAdjustAmount; Octave3DWorldBuilder.ActiveInstance.Inspector.EditorWindow.Repaint(); SceneView.RepaintAll(); } }
public static GameObject InstantiateObjectHierarchyFromPrefab(GameObject prefab, Vector3 worldPosition, Quaternion worldRotation, Vector3 worldScale) { GameObject instantiatedObject = PrefabUtility.InstantiatePrefab(prefab) as GameObject; UndoEx.RegisterCreatedGameObject(instantiatedObject); instantiatedObject.name = prefab.name; Transform objectTransform = instantiatedObject.transform; objectTransform.position = worldPosition; objectTransform.rotation = worldRotation; objectTransform.localScale = worldScale; instantiatedObject.SetSelectedHierarchyWireframeHidden(ObjectPlacementSettings.Get().HideWireframeWhenPlacingObjects); SceneViewCamera.Instance.SetObjectVisibilityDirty(); return(instantiatedObject); }
public override void Render() { if (ObjectPlacement.Get().IsPlacementLocked) { string helpMessage = "Object placement is currently locked. Press \'" + AllShortcutCombos.Instance.LockObjectPlacement.ToString() + "\' to toggle the lock state."; EditorGUILayout.HelpBox(helpMessage, UnityEditor.MessageType.Warning); } RenderXZGridRotationField(); ObjectPlacement.Get().MirrorView.Render(); Octave3DWorldBuilder.ActiveInstance.PlacementObjectGroupDatabase.View.Render(); ObjectPlacementSettings.Get().View.Render(); if (ObjectPlacementSettings.Get().ObjectPlacementMode == ObjectPlacementMode.DecorPaint) { RenderControlsForDecorPaintPlacementMode(); } _objectPlacementLookAndFeelSettingsView.Render(); }
public List <ObjectPlacementData> Calculate() { if (_path == null || _path.NumberOfSegments == 0 || !ObjectPlacementGuide.ExistsInScene) { return(new List <ObjectPlacementData>()); } Prefab placementGuidePrefab = ObjectPlacementGuide.Instance.SourcePrefab; Vector3 placementGuideWorldScale = ObjectPlacementGuide.Instance.WorldScale; float objectMissChance = _path.Settings.ManualConstructionSettings.ObjectMissChance; Vector3 yOffsetVector = _path.ExtensionPlane.normal * _path.Settings.ManualConstructionSettings.OffsetAlongGrowDirection; bool allowObjectIntersection = ObjectPlacementSettings.Get().ObjectIntersectionSettings.AllowIntersectionForPathPlacement; Quaternion placementGuideRotation = ObjectPlacementGuide.Instance.WorldRotation; bool rotateObjectsToFollowPath = _path.Settings.ManualConstructionSettings.RotateObjectsToFollowPath; Vector3 pathExtensionPlaneNormal = _path.ExtensionPlane.normal; Vector3 firstSegmentExtensionDir = _path.GetSegmentByIndex(0).ExtensionDirection; Quaternion firstSegmentRotation = Quaternion.LookRotation(firstSegmentExtensionDir, pathExtensionPlaneNormal); bool randomizePrefabs = _path.Settings.ManualConstructionSettings.RandomizePrefabs; PrefabCategory activePrefabCategory = PrefabCategoryDatabase.Get().ActivePrefabCategory; var objectPlacementDataInstances = new List <ObjectPlacementData>(_path.NumberOfSegments * 10); for (int segmentIndex = 0; segmentIndex < _path.NumberOfSegments; ++segmentIndex) { ObjectPlacementBoxStackSegment segment = _path.GetSegmentByIndex(segmentIndex); Quaternion worldRotation = placementGuideRotation; if (rotateObjectsToFollowPath) { // Note: ObjectPlacementPathManualConstructionSession.cs line 451. The design is a wreck. AGAIN :) if ((segmentIndex == 0 && _path.NumberOfSegments > 1 && segment.NumberOfStacks == 1)) { Vector3 dirBetweenStacks = segment.GetStackByIndex(0).BasePosition - _path.GetSegmentByIndex(1).GetStackByIndex(0).BasePosition; dirBetweenStacks.Normalize(); Quaternion segmentRotation = Quaternion.LookRotation(dirBetweenStacks, pathExtensionPlaneNormal); Quaternion fromPlacementGuideRotationToThis = QuaternionExtensions.GetRelativeRotation(placementGuideRotation, segmentRotation); worldRotation = fromPlacementGuideRotationToThis * worldRotation; } else if (segmentIndex != 0) { Quaternion segmentRotation = Quaternion.LookRotation(segment.ExtensionDirection, pathExtensionPlaneNormal); Quaternion fromFirstToThis = QuaternionExtensions.GetRelativeRotation(firstSegmentRotation, segmentRotation); worldRotation = fromFirstToThis * worldRotation; } } for (int stackIndex = 0; stackIndex < segment.NumberOfStacks; ++stackIndex) { ObjectPlacementBoxStack stack = segment.GetStackByIndex(stackIndex); if (stack.IsOverlappedByAnotherStack) { continue; } for (int stackBoxIndex = 0; stackBoxIndex < stack.NumberOfBoxes; ++stackBoxIndex) { ObjectPlacementBox box = stack.GetBoxByIndex(stackBoxIndex); if (box.IsHidden) { continue; } if (ObjectPlacementMissChance.Missed(objectMissChance, ObjectPlacementPathManualConstructionSettings.MinObjectMissChance, ObjectPlacementPathManualConstructionSettings.MaxObjectMissChance)) { continue; } if (!allowObjectIntersection && ObjectQueries.IntersectsAnyObjectsInScene(box.OrientedBox, true)) { continue; } 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; } } var objectPlacementData = new ObjectPlacementData(); objectPlacementData.WorldPosition = ObjectPositionCalculator.CalculateObjectHierarchyPosition(prefab, box.Center + yOffsetVector, worldScale, worldRotation); objectPlacementData.WorldScale = worldScale; objectPlacementData.WorldRotation = worldRotation; objectPlacementData.Prefab = prefab; objectPlacementDataInstances.Add(objectPlacementData); } } } return(objectPlacementDataInstances); }
protected override int GetActiveButtonIndex() { return((int)ObjectPlacementSettings.Get().ObjectPlacementMode); }
protected override void HandleButtonClick(int buttonIndex) { UndoEx.RecordForToolAction(ObjectPlacementSettings.Get()); ObjectPlacementSettings.Get().ObjectPlacementMode = (ObjectPlacementMode)buttonIndex; }
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; 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) { continue; } 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; } } var objectPlacementData = new ObjectPlacementData(); objectPlacementData.WorldPosition = ObjectPositionCalculator.CalculateObjectHierarchyPosition(prefab, box.Center + objectOffsetAlongExtensionPlaneNormal, worldScale, placementGuideWorldRotation); objectPlacementData.WorldScale = worldScale; objectPlacementData.WorldRotation = worldRotation; objectPlacementData.Prefab = prefab; objectPlacementDataInstances.Add(objectPlacementData); } } } return(objectPlacementDataInstances); }
public List <ObjectPlacementData> Calculate(Quaternion rotationToApplyForStrokeAlignment) { if (!ValidateCalculationRequirements()) { return(new List <ObjectPlacementData>()); } _objectNodeNetwork.Clear(); _rotationToApplyForStrokeAlignment = rotationToApplyForStrokeAlignment; CreateSurfaceColliderProjector(); _elementToNewPrefabRotation.Clear(); _allowObjectIntersection = ObjectPlacementSettings.Get().ObjectIntersectionSettings.AllowIntersectionForDecorPaintBrushModeDrag; int currentObjectIndex = 0; var objectPlacementDataInstances = new List <ObjectPlacementData>(_workingBrush.MaxNumberOfObjects); while (currentObjectIndex < _workingBrush.MaxNumberOfObjects) { DecorPaintObjectPlacementBrushElement brushElement = _brushElementSpawnChanceTable.PickEntity(UnityEngine.Random.Range(0.0f, 1.0f)); int brushElementIndex = _allValidBrushElements.FindIndex(item => item == brushElement); ++currentObjectIndex; // No object nodes were created yet? if (_objectNodeNetwork.NumberOfNodes == 0) { // Create the first node at a random position inside the brush circle Vector3 randomPositionInsideCircle = _workingBrushCircle.GetRandomPointInside(); ObjectSurfaceData objectSurfaceData = CalculateObjectSurfaceData(randomPositionInsideCircle); MatrixObjectBoxPair matrixObjectBoxPair = CalculateMatrixObjectBoxPair(brushElementIndex, objectSurfaceData); // We need to know if the normal of the surface on which the object resides lies within the desired slope range bool passesSlopeTest = DoesObjectSurfacePassSlopeTest(objectSurfaceData, brushElement); // Note: Even if the slope test is not passed, we will still create an object node. The reason for this is that // we want to have some kind of continuity in the algorithm. Imagine that the brush circle is large and is // divided by a large terrain mountain which sits in the middle. If the object generation starts on one side // of the mountain, the algorithm might never get a chance to go over the other side if the slope condition // is not satisifed. We want to spread objects as much as possible so even though this object will not be // placed in the scene, we will still add it to the node network. _objectNodeNetwork.AddNodeToEnd(matrixObjectBoxPair.ObjectBox, objectSurfaceData); if (passesSlopeTest && DoesBoxPassObjectIntersectionTest(matrixObjectBoxPair.ObjectBox, brushElement.Prefab.UnityPrefab, matrixObjectBoxPair.ObjectMatrix)) { objectPlacementDataInstances.Add(new ObjectPlacementData(matrixObjectBoxPair.ObjectMatrix, brushElement.Prefab, brushElement.MustEmbedInSurface)); } } else { // Are there any node segments available? if (_objectNodeNetwork.NumberOfSegments != 0) { // The first step is to generate a random node index and store references to that node and its immediate neighbour _objectNodeNetwork.RemoveAllNodesWhichGenerateConcavities(_workingBrushCircle.Plane); int randomNodeIndex = _objectNodeNetwork.GetRandomNodeIndex(); ObjectNode firstNode = _objectNodeNetwork.GetNodeByIndex(randomNodeIndex); ObjectNode secondNode = _objectNodeNetwork.GetNodeByIndex(randomNodeIndex + 1); // Calculate the plane of the segment which unites the 2 nodes. We will also store the // actual segment and the middle point on the segment. We will use this middle point to // generate the initial object position. Segment3D nodeSegment = ObjectNodeNetwork.CalculateSegmentBetweenNodes(firstNode, secondNode); Vector3 segmentMidPoint = nodeSegment.GetPoint(0.5f); Plane segmentPlane = ObjectNodeNetwork.CalculateSegmentPlaneNormal(firstNode, secondNode); OrientedBox firstNodeBox = firstNode.ObjectBox; OrientedBox secondNodeBox = secondNode.ObjectBox; // Calculate the furthest point in front of the plane using the corner points of the // 2 nodes. The idea is to move the new object as much as possible from the bulk of // objects that have already been generated. Vector3 furthestPointFromPlane; List <Vector3> nodeCornerPoints = firstNodeBox.GetCornerPoints(); nodeCornerPoints.AddRange(secondNodeBox.GetCornerPoints()); if (!segmentPlane.GetFurthestPointInFront(nodeCornerPoints, out furthestPointFromPlane)) { continue; } // Use the calculated furthest point from plane and the the existing plane normal to calculate the // pivot plane. The new object will reside at some distance away from this plane. Plane pivotPlane = new Plane(segmentPlane.normal, furthestPointFromPlane); // Calculate the new object transform data. We will use the segment's mid point to generate the // initial object position. ObjectSurfaceData objectSurfaceData = CalculateObjectSurfaceData(segmentMidPoint); MatrixObjectBoxPair matrixObjectBoxPair = CalculateMatrixObjectBoxPair(brushElementIndex, objectSurfaceData); OrientedBox objectBox = matrixObjectBoxPair.ObjectBox; // Identify the objects's furthest point behind the plane Vector3 objectBoxPivotPoint; List <Vector3> objectBoxCornerPoints = objectBox.GetCornerPoints(); if (!pivotPlane.GetFurthestPointBehind(objectBoxCornerPoints, out objectBoxPivotPoint)) { continue; } // Use the furthest point to move the object in front of the plane and take the distance between objects into account Vector3 fromPivotPointToCenter = objectBox.Center - objectBoxPivotPoint; Vector3 projectedPivotPoint = pivotPlane.ProjectPoint(objectBoxPivotPoint); objectBox.Center = projectedPivotPoint + fromPivotPointToCenter + pivotPlane.normal * _workingBrush.DistanceBetweenObjects; // Generate the object surface data objectSurfaceData = CalculateObjectSurfaceData(objectBox.Center); bool passesSlopeTest = DoesObjectSurfacePassSlopeTest(objectSurfaceData, brushElement); // Now we need to adjust the orientation and center of the box. If the calculated center // lies outside the brush circle, we will ignore this node. AdjustObjectBoxRotationOnSurface(objectBox, objectSurfaceData, brushElement); AdjustObjectBoxCenterToSitOnSurface(objectBox, objectSurfaceData, brushElement); if (!_workingBrushCircle.ContainsPoint(_workingBrushCircle.Plane.ProjectPoint(objectBox.Center))) { continue; } // Recalculate the object matrix using the new box data TransformMatrix objectMatrix = matrixObjectBoxPair.ObjectMatrix; objectMatrix.Rotation = objectBox.Rotation; objectMatrix.Translation = ObjectPositionCalculator.CalculateObjectHierarchyPosition(brushElement.Prefab, objectBox.Center, objectMatrix.Scale, objectBox.Rotation); // We have been modifying the matrix and box data independently so we will ensure that the box uses the latest data OrientedBox finalBox = new OrientedBox(objectBox); finalBox.SetTransformMatrix(objectMatrix); // If the slope test passed, we will calculate an object placement data instance. Otherwise, we will just insert a new node. if (passesSlopeTest && DoesBoxPassObjectIntersectionTest(finalBox, brushElement.Prefab.UnityPrefab, objectMatrix)) { objectPlacementDataInstances.Add(new ObjectPlacementData(objectMatrix, brushElement.Prefab, brushElement.MustEmbedInSurface)); } _objectNodeNetwork.InsertAfterNode(objectBox, objectSurfaceData, randomNodeIndex); } else { // When there are no segments available it means we have only one node. We will use this node to generate // a new one at some distance away from it. First we will store some data that we will need during the entire // procedure. ObjectNode pivotNode = _objectNodeNetwork.GetFirstNode(); Vector3 pivotNodeSurfaceTangent = pivotNode.ObjectSurfaceData.GetSurfaceTangentVector(); OrientedBox pivotNodeObjectBox = pivotNode.ObjectBox; // We will place the new node at some distance away from the first node's face which points // along the calculated tangent vector. We will call this the pivot face. BoxFace pivotBoxFace = pivotNodeObjectBox.GetBoxFaceMostAlignedWithNormal(pivotNodeSurfaceTangent); Plane pivotFacePlane = pivotNodeObjectBox.GetBoxFacePlane(pivotBoxFace); // Generate the data for the new node in the same position as the first node. // Note: Although the same position is used, the rotation and scale will differ and they will // be established by 'CalculateMatrixObjectBoxPair'. MatrixObjectBoxPair matrixObjectBoxPair = CalculateMatrixObjectBoxPair(brushElementIndex, pivotNode.ObjectSurfaceData); OrientedBox objectBox = matrixObjectBoxPair.ObjectBox; // At this point we have to start moving the generated object box to its new positino along the // tangent vector. We will do this by calculating the furthest box point which lies behind the // pivot plane and then move the box so that this point resides on that plane. We will call this // the pivot point. // Note: We will perform a safety check to see if this point could not be calculated and use the // closest point in front if necessary. However, this check should not be necessary. Because // we are placing te object box in the center of the previous box, we can be usre that there // will always be a point which lies behind the pivot plane. Vector3 objectBoxPivotPoint; List <Vector3> objectBoxCornerPoints = objectBox.GetCornerPoints(); if (!pivotFacePlane.GetFurthestPointBehind(objectBoxCornerPoints, out objectBoxPivotPoint) && !pivotFacePlane.GetClosestPointInFront(objectBoxCornerPoints, out objectBoxPivotPoint)) { continue; } // Project the pivot point onto the pivot plane. We will also store a vector which goes from the // original pivot point to the box center. This will allow us to maintain the relationship between // the projected pivot point and the box center so that the center can be adjusted accordingly. Vector3 fromPivotPointToCenter = objectBox.Center - objectBoxPivotPoint; Vector3 projectedPivotPoint = pivotFacePlane.ProjectPoint(objectBoxPivotPoint); // Adjust the center using the projected pivot point and also take the distance between objects into account objectBox.Center = projectedPivotPoint + fromPivotPointToCenter + pivotNodeSurfaceTangent * _workingBrush.DistanceBetweenObjects; // Generate the object surface data at the current box position. // Note: This is the step which can actually cause objects to intersect a little bit. The surface data is // calculated by projecting along the brush circle plane normal. If we are placing objects on a terrain // and the center of the circle lies somewhere at the base of the terrain where the normal points straight // up, but the center of the box resides somewhere on a clif, the new center might move the box closer // or even further away from the pivot node. This however, should not be a problem especially if the distance // between objects is not 0. ObjectSurfaceData objectSurfaceData = CalculateObjectSurfaceData(objectBox.Center); bool passesSlopeTest = DoesObjectSurfacePassSlopeTest(objectSurfaceData, brushElement); // Now we need to adjust the orientation and center of the box. If the calculated center // lies outside the brush circle, we will ignore this node. AdjustObjectBoxRotationOnSurface(objectBox, objectSurfaceData, brushElement); AdjustObjectBoxCenterToSitOnSurface(objectBox, objectSurfaceData, brushElement); if (!_workingBrushCircle.ContainsPoint(_workingBrushCircle.Plane.ProjectPoint(objectBox.Center))) { continue; } // Recalculate the object matrix using the new box data TransformMatrix objectMatrix = matrixObjectBoxPair.ObjectMatrix; objectMatrix.Rotation = objectBox.Rotation; objectMatrix.Translation = ObjectPositionCalculator.CalculateObjectHierarchyPosition(brushElement.Prefab, objectBox.Center, objectMatrix.Scale, objectBox.Rotation); // We have been modifying the matrix and box data independently so we will ensure that the box uses the latest data OrientedBox finalBox = new OrientedBox(objectBox); finalBox.SetTransformMatrix(objectMatrix); // If the slope test passed, we will calculate an object placement data instance. Otherwise, we will just insert a new node. if (passesSlopeTest && DoesBoxPassObjectIntersectionTest(finalBox, brushElement.Prefab.UnityPrefab, objectMatrix)) { objectPlacementDataInstances.Add(new ObjectPlacementData(objectMatrix, brushElement.Prefab, brushElement.MustEmbedInSurface)); } _objectNodeNetwork.InsertAfterNode(objectBox, objectSurfaceData, 0); } } } // Adjust the prefab rotations for the next time the function is called if (_elementToNewPrefabRotation.Count != 0) { foreach (var prefabRotationPair in _elementToNewPrefabRotation) { DecorPaintObjectPlacementBrushElement brushElement = prefabRotationPair.Key; if (_elementToCurrentPrefabRotation.ContainsKey(brushElement)) { _elementToCurrentPrefabRotation[brushElement] = prefabRotationPair.Value; } } } return(objectPlacementDataInstances); }
private void RenderPrefabPreviewRows() { for (int prefabIndex = 0; prefabIndex < _filteredPrefabs.Count; ++prefabIndex) { // Start a new row? if (prefabIndex % ViewData.NumberOfPrefabsPerRow == 0) { if (prefabIndex != 0) { EditorGUILayout.EndHorizontal(); } EditorGUILayout.BeginHorizontal(); } // Render the prefab entry Prefab prefab = _filteredPrefabs[prefabIndex]; var previewButtonRenderData = new PrefabPreviewButtonRenderData(); previewButtonRenderData.ExtractFromPrefab(prefab, ViewData.PrefabPreviewScale); EditorGUILayout.BeginVertical(GUILayout.Width(previewButtonRenderData.ButtonWidth)); // Render the prefab preview button EditorGUIColor.Push(prefab == _prefabCategory.ActivePrefab ? ViewData.ActivePrefabTint : Color.white); if (EditorGUILayoutEx.PrefabPreview(prefab, true, previewButtonRenderData)) { ObjectPlacementSettings placementSettings = ObjectPlacementSettings.Get(); if (placementSettings.ObjectPlacementMode == ObjectPlacementMode.DecorPaint && placementSettings.DecorPaintObjectPlacementSettings.DecorPaintMode == DecorPaintMode.Brush && DecorPaintObjectPlacementBrushDatabase.Get().ActiveBrush != null && Event.current.button == (int)MouseButton.Right) { UndoEx.RecordForToolAction(DecorPaintObjectPlacementBrushDatabase.Get().ActiveBrush); DecorPaintObjectPlacementBrushElement brushElement = DecorPaintObjectPlacementBrushDatabase.Get().ActiveBrush.CreateNewElement(); brushElement.Prefab = prefab; Octave3DWorldBuilder.ActiveInstance.RepaintAllEditorWindows(); Octave3DWorldBuilder.ActiveInstance.Inspector.Repaint(); } else if (Octave3DWorldBuilder.ActiveInstance.Inspector.ActiveInspectorGUIIdentifier == InspectorGUIIdentifier.ObjectSelection && AllShortcutCombos.Instance.ReplacePrefabsForSelectedObjects.IsActive()) { ObjectSelection.Get().ReplaceSelectedObjectsWithPrefab(prefab); } else { UndoEx.RecordForToolAction(_prefabCategory); _prefabCategory.SetActivePrefab(prefab); } } EditorGUIColor.Pop(); // Render the prefab name labels if necessary if (ViewData.ShowPrefabNames) { Rect previewRectangle = GUILayoutUtility.GetLastRect(); EditorGUILayoutEx.LabelInMiddleOfControlRect(previewRectangle, prefab.Name, previewButtonRenderData.ButtonHeight, GetStyleForPrefabNameLabel()); } // Render the remove prefab button if (GUILayout.Button(GetRemovePrefabButtonContent())) { UndoEx.RecordForToolAction(_prefabCategory); _prefabCategory.RemoveAndDestroyPrefab(prefab); Octave3DWorldBuilder.ActiveInstance.Inspector.Repaint(); } EditorGUILayout.EndVertical(); } // End the last row (if any) if (_filteredPrefabs.Count != 0) { EditorGUILayout.EndHorizontal(); } }
public static PathObjectPlacementSettings Get() { return(ObjectPlacementSettings.Get().PathPlacementSettings); }
public override void Initialize() { base.Initialize(); if (Octave3DWorldBuilder.ActiveInstance == null) { return; } ObjectPlacementSettings.Get().ObjectIntersectionSettings.View.IsVisible = false; _objectPlacementLookAndFeelSettingsView.IsVisible = false; _objectPlacementLookAndFeelSettingsView.BlockObjectPlacementLookAndFeelSettingsView.ToggleVisibilityBeforeRender = true; _objectPlacementLookAndFeelSettingsView.BlockObjectPlacementLookAndFeelSettingsView.VisibilityToggleLabel = "Block"; _objectPlacementLookAndFeelSettingsView.BlockObjectPlacementLookAndFeelSettingsView.IndentContent = true; _objectPlacementLookAndFeelSettingsView.BlockObjectPlacementLookAndFeelSettingsView.IsVisible = false; _objectPlacementLookAndFeelSettingsView.PathObjectPlacementLookAndFeelSettingsView.ToggleVisibilityBeforeRender = true; _objectPlacementLookAndFeelSettingsView.PathObjectPlacementLookAndFeelSettingsView.VisibilityToggleLabel = "Path"; _objectPlacementLookAndFeelSettingsView.PathObjectPlacementLookAndFeelSettingsView.IndentContent = true; _objectPlacementLookAndFeelSettingsView.PathObjectPlacementLookAndFeelSettingsView.IsVisible = false; _objectPlacementLookAndFeelSettingsView.DecorPaintLookAndFeelSettingsView.ToggleVisibilityBeforeRender = true; _objectPlacementLookAndFeelSettingsView.DecorPaintLookAndFeelSettingsView.VisibilityToggleLabel = "Decor Paint"; _objectPlacementLookAndFeelSettingsView.DecorPaintLookAndFeelSettingsView.IndentContent = true; _objectPlacementLookAndFeelSettingsView.DecorPaintLookAndFeelSettingsView.IsVisible = false; ObjectGroupDatabaseView objectGroupDatabaseView = Octave3DWorldBuilder.ActiveInstance.PlacementObjectGroupDatabase.View; objectGroupDatabaseView.ToggleVisibilityBeforeRender = true; objectGroupDatabaseView.VisibilityToggleLabel = "Object Groups"; objectGroupDatabaseView.IsVisible = false; objectGroupDatabaseView.SurroundWithBox = true; ObjectPlacementGuideSettings objectPlacementGuideSettings = ObjectPlacementSettings.Get().ObjectPlacementGuideSettings; objectPlacementGuideSettings.KeyboardRotationSettings.XAxisRotationSettings.View.VisibilityToggleLabel = objectPlacementGuideSettings.KeyboardRotationSettings.XAxisRotationSettings.RotationAxis.ToString() + " Axis Settings"; objectPlacementGuideSettings.KeyboardRotationSettings.YAxisRotationSettings.View.VisibilityToggleLabel = objectPlacementGuideSettings.KeyboardRotationSettings.YAxisRotationSettings.RotationAxis.ToString() + " Axis Settings"; objectPlacementGuideSettings.KeyboardRotationSettings.ZAxisRotationSettings.View.VisibilityToggleLabel = objectPlacementGuideSettings.KeyboardRotationSettings.ZAxisRotationSettings.RotationAxis.ToString() + " Axis Settings"; objectPlacementGuideSettings.KeyboardRotationSettings.CustomAxisRotationSettings.View.VisibilityToggleLabel = "Placement Surface Normal Settings"; objectPlacementGuideSettings.KeyboardRotationSettings.XAxisRotationSettings.View.IsVisible = false; objectPlacementGuideSettings.KeyboardRotationSettings.YAxisRotationSettings.View.IsVisible = false; objectPlacementGuideSettings.KeyboardRotationSettings.ZAxisRotationSettings.View.IsVisible = false; objectPlacementGuideSettings.KeyboardRotationSettings.CustomAxisRotationSettings.View.IsVisible = false; objectPlacementGuideSettings.MouseRotationSettings.XAxisRotationSettings.View.VisibilityToggleLabel = objectPlacementGuideSettings.MouseRotationSettings.XAxisRotationSettings.RotationAxis.ToString() + " Axis Settings"; objectPlacementGuideSettings.MouseRotationSettings.YAxisRotationSettings.View.VisibilityToggleLabel = objectPlacementGuideSettings.MouseRotationSettings.YAxisRotationSettings.RotationAxis.ToString() + " Axis Settings"; objectPlacementGuideSettings.MouseRotationSettings.ZAxisRotationSettings.View.VisibilityToggleLabel = objectPlacementGuideSettings.MouseRotationSettings.ZAxisRotationSettings.RotationAxis.ToString() + " Axis Settings"; objectPlacementGuideSettings.MouseRotationSettings.CustomAxisRotationSettings.View.VisibilityToggleLabel = "Placement Surface Normal Settings"; objectPlacementGuideSettings.MouseRotationSettings.XAxisRotationSettings.View.IsVisible = false; objectPlacementGuideSettings.MouseRotationSettings.YAxisRotationSettings.View.IsVisible = false; objectPlacementGuideSettings.MouseRotationSettings.ZAxisRotationSettings.View.IsVisible = false; objectPlacementGuideSettings.MouseRotationSettings.CustomAxisRotationSettings.View.IsVisible = false; ObjectPlacement.Get().MirrorView.IsVisible = false; InteractableMirrorSettings mirrorSettings = ObjectPlacement.Get().MirrorSettings; mirrorSettings.View.IsVisible = false; mirrorSettings.View.ToggleVisibilityBeforeRender = true; mirrorSettings.View.VisibilityToggleLabel = "More settings"; mirrorSettings.View.VisibilityToggleIndent = 1; mirrorSettings.View.IndentContent = true; mirrorSettings.KeyboardRotationSettings.XAxisRotationSettings.View.VisibilityToggleLabel = mirrorSettings.KeyboardRotationSettings.XAxisRotationSettings.RotationAxis.ToString() + " Axis Settings"; mirrorSettings.KeyboardRotationSettings.YAxisRotationSettings.View.VisibilityToggleLabel = mirrorSettings.KeyboardRotationSettings.YAxisRotationSettings.RotationAxis.ToString() + " Axis Settings"; mirrorSettings.KeyboardRotationSettings.ZAxisRotationSettings.View.VisibilityToggleLabel = mirrorSettings.KeyboardRotationSettings.ZAxisRotationSettings.RotationAxis.ToString() + " Axis Settings"; mirrorSettings.KeyboardRotationSettings.CustomAxisRotationSettings.View.VisibilityToggleLabel = "Hover Surface Normal Settings"; mirrorSettings.KeyboardRotationSettings.XAxisRotationSettings.View.IsVisible = false; mirrorSettings.KeyboardRotationSettings.YAxisRotationSettings.View.IsVisible = false; mirrorSettings.KeyboardRotationSettings.ZAxisRotationSettings.View.IsVisible = false; mirrorSettings.KeyboardRotationSettings.CustomAxisRotationSettings.View.IsVisible = false; mirrorSettings.MouseRotationSettings.XAxisRotationSettings.View.VisibilityToggleLabel = mirrorSettings.MouseRotationSettings.XAxisRotationSettings.RotationAxis.ToString() + " Axis Settings"; mirrorSettings.MouseRotationSettings.YAxisRotationSettings.View.VisibilityToggleLabel = mirrorSettings.MouseRotationSettings.YAxisRotationSettings.RotationAxis.ToString() + " Axis Settings"; mirrorSettings.MouseRotationSettings.ZAxisRotationSettings.View.VisibilityToggleLabel = mirrorSettings.MouseRotationSettings.ZAxisRotationSettings.RotationAxis.ToString() + " Axis Settings"; mirrorSettings.MouseRotationSettings.CustomAxisRotationSettings.View.VisibilityToggleLabel = "Hover Surface Normal Settings"; mirrorSettings.MouseRotationSettings.XAxisRotationSettings.View.IsVisible = false; mirrorSettings.MouseRotationSettings.YAxisRotationSettings.View.IsVisible = false; mirrorSettings.MouseRotationSettings.ZAxisRotationSettings.View.IsVisible = false; mirrorSettings.MouseRotationSettings.CustomAxisRotationSettings.View.IsVisible = false; InteractableMirrorRenderSettingsView mirrorRenderSettingsView = ObjectPlacement.Get().MirrorRenderSettings.View; mirrorRenderSettingsView.VisibilityToggleLabel = "Look and feel"; mirrorRenderSettingsView.ToggleVisibilityBeforeRender = true; mirrorRenderSettingsView.IndentContent = true; mirrorRenderSettingsView.VisibilityToggleIndent = 1; mirrorRenderSettingsView.IsVisible = false; ObjectRotationRandomizationSettings placementGuideRotationRandomizationSettings = PointAndClickObjectPlacementSettings.Get().PlacementGuideRotationRandomizationSettings; ObjectRotationRandomizationSettingsView placementGuideRotationRandomizationSettingsView = placementGuideRotationRandomizationSettings.View; placementGuideRotationRandomizationSettingsView.VisibilityToggleIndent = 1; placementGuideRotationRandomizationSettingsView.VisibilityToggleLabel = "Rotation Randomization Settings"; placementGuideRotationRandomizationSettingsView.IsVisible = false; placementGuideRotationRandomizationSettings.XAxisRandomizationSettings.View.VisibilityToggleLabel = placementGuideRotationRandomizationSettings.XAxisRandomizationSettings.Axis + " Axis Settings"; placementGuideRotationRandomizationSettings.XAxisRandomizationSettings.View.IsVisible = false; placementGuideRotationRandomizationSettings.YAxisRandomizationSettings.View.VisibilityToggleLabel = placementGuideRotationRandomizationSettings.YAxisRandomizationSettings.Axis + " Axis Settings"; placementGuideRotationRandomizationSettings.YAxisRandomizationSettings.View.IsVisible = false; placementGuideRotationRandomizationSettings.ZAxisRandomizationSettings.View.VisibilityToggleLabel = placementGuideRotationRandomizationSettings.ZAxisRandomizationSettings.Axis + " Axis Settings"; placementGuideRotationRandomizationSettings.ZAxisRandomizationSettings.View.IsVisible = false; placementGuideRotationRandomizationSettings.CustomAxisRandomizationSettings.View.VisibilityToggleLabel = "Placement Surface Normal Settings"; placementGuideRotationRandomizationSettings = DecorPaintObjectPlacementSettings.Get().SingleDecorPaintModeSettings.PlacementGuideRotationRandomizationSettings; placementGuideRotationRandomizationSettingsView = placementGuideRotationRandomizationSettings.View; placementGuideRotationRandomizationSettingsView.VisibilityToggleIndent = 1; placementGuideRotationRandomizationSettingsView.VisibilityToggleLabel = "Rotation Randomization Settings"; placementGuideRotationRandomizationSettingsView.IsVisible = false; placementGuideRotationRandomizationSettings.XAxisRandomizationSettings.View.VisibilityToggleLabel = placementGuideRotationRandomizationSettings.XAxisRandomizationSettings.Axis + " Axis Settings"; placementGuideRotationRandomizationSettings.XAxisRandomizationSettings.View.IsVisible = false; placementGuideRotationRandomizationSettings.YAxisRandomizationSettings.View.VisibilityToggleLabel = placementGuideRotationRandomizationSettings.YAxisRandomizationSettings.Axis + " Axis Settings"; placementGuideRotationRandomizationSettings.YAxisRandomizationSettings.View.IsVisible = false; placementGuideRotationRandomizationSettings.ZAxisRandomizationSettings.View.VisibilityToggleLabel = placementGuideRotationRandomizationSettings.ZAxisRandomizationSettings.Axis + " Axis Settings"; placementGuideRotationRandomizationSettings.ZAxisRandomizationSettings.View.IsVisible = false; placementGuideRotationRandomizationSettings.CustomAxisRandomizationSettings.View.VisibilityToggleLabel = "Placement Surface Normal Settings"; ObjectScaleRandomizationSettings placementGuideScaleRandomizationSettings = PointAndClickObjectPlacementSettings.Get().PlacementGuideScaleRandomizationSettings; ObjectScaleRandomizationSettingsView guideScaleRandomizationSettingsView = placementGuideScaleRandomizationSettings.View; guideScaleRandomizationSettingsView.VisibilityToggleIndent = 1; guideScaleRandomizationSettingsView.VisibilityToggleLabel = "Scale Randomization Settings"; guideScaleRandomizationSettingsView.IsVisible = false; guideScaleRandomizationSettingsView.IndentContent = true; placementGuideScaleRandomizationSettings = DecorPaintObjectPlacementSettings.Get().SingleDecorPaintModeSettings.PlacementGuideScaleRandomizationSettings; guideScaleRandomizationSettingsView = placementGuideScaleRandomizationSettings.View; guideScaleRandomizationSettingsView.VisibilityToggleIndent = 1; guideScaleRandomizationSettingsView.VisibilityToggleLabel = "Scale Randomization Settings"; guideScaleRandomizationSettingsView.IsVisible = false; guideScaleRandomizationSettingsView.IndentContent = true; AxisAlignmentSettingsView placementGuideSurfaceAlignmentSettingsView = PointAndClickObjectPlacementSettings.Get().PlacementGuideSurfaceAlignmentSettings.View; placementGuideSurfaceAlignmentSettingsView.VisibilityToggleIndent = 1; placementGuideSurfaceAlignmentSettingsView.VisibilityToggleLabel = "Surface Alignment Settings"; placementGuideSurfaceAlignmentSettingsView = PathObjectPlacementSettings.Get().PlacementGuideSurfaceAlignmentSettings.View; placementGuideSurfaceAlignmentSettingsView.VisibilityToggleIndent = 1; placementGuideSurfaceAlignmentSettingsView.VisibilityToggleLabel = "Surface Alignment Settings"; placementGuideSurfaceAlignmentSettingsView = BlockObjectPlacementSettings.Get().PlacementGuideSurfaceAlignmentSettings.View; placementGuideSurfaceAlignmentSettingsView.VisibilityToggleIndent = 1; placementGuideSurfaceAlignmentSettingsView.VisibilityToggleLabel = "Surface Alignment Settings"; placementGuideSurfaceAlignmentSettingsView = DecorPaintObjectPlacementSettings.Get().SingleDecorPaintModeSettings.PlacementGuideSurfaceAlignmentSettings.View; placementGuideSurfaceAlignmentSettingsView.VisibilityToggleIndent = 1; placementGuideSurfaceAlignmentSettingsView.VisibilityToggleLabel = "Surface Alignment Settings"; ObjectRotationRandomizationSettings blockObjectRotationRandomizationSettings = ObjectPlacement.Get().BlockObjectPlacement.BlockSettings.ManualConstructionSettings.ObjectRotationRandomizationSettings; ObjectRotationRandomizationSettingsView blockObjectRotationRandomizationSettingsView = blockObjectRotationRandomizationSettings.View; blockObjectRotationRandomizationSettings.CustomAxisRandomizationSettings.View.ToggleVisibilityBeforeRender = false; blockObjectRotationRandomizationSettings.CustomAxisRandomizationSettings.View.IsVisible = false; blockObjectRotationRandomizationSettings.CustomAxisRandomizationSettings.Randomize = false; blockObjectRotationRandomizationSettingsView.SurroundWithBox = false; blockObjectRotationRandomizationSettingsView.VisibilityToggleIndent = 1; blockObjectRotationRandomizationSettings.XAxisRandomizationSettings.View.VisibilityToggleLabel = blockObjectRotationRandomizationSettings.XAxisRandomizationSettings.Axis + " Axis Settings"; blockObjectRotationRandomizationSettings.YAxisRandomizationSettings.View.VisibilityToggleLabel = blockObjectRotationRandomizationSettings.YAxisRandomizationSettings.Axis + " Axis Settings"; blockObjectRotationRandomizationSettings.ZAxisRandomizationSettings.View.VisibilityToggleLabel = blockObjectRotationRandomizationSettings.ZAxisRandomizationSettings.Axis + " Axis Settings"; XZOrientedEllipseShapeRenderSettingsView xzOrientedElipseShapeRenderSettingsView = DecorPaintObjectPlacement.Get().BrushCircleRenderSettings.View; xzOrientedElipseShapeRenderSettingsView.ToggleVisibilityBeforeRender = true; xzOrientedElipseShapeRenderSettingsView.IndentContent = true; xzOrientedElipseShapeRenderSettingsView.VisibilityToggleLabel = "Brush Circle"; xzOrientedElipseShapeRenderSettingsView.IsVisible = false; ObjectPivotPointsRenderSettingsView guidePivotPointsSettingsView = ObjectPlacement.Get().GuidePivotPointsRenderSettings.View; guidePivotPointsSettingsView.ToggleVisibilityBeforeRender = true; guidePivotPointsSettingsView.IndentContent = true; guidePivotPointsSettingsView.VisibilityToggleLabel = "Guide Pivot Points"; guidePivotPointsSettingsView.IsVisible = false; ObjectPlacement.Get().ObjectVertexSnapSessionRenderSettings.View.IsVisible = false; ProjectedBoxFacePivotPointsRenderSettings projectedBoxFacePointsRenderSettings = ObjectPlacement.Get().GuidePivotPointsRenderSettings.ProjectedBoxFacePivotPointsRenderSettings; ProjectedBoxFacePivotPointsRenderSettingsView projectedBoxFacePointsRenderSettingsView = projectedBoxFacePointsRenderSettings.View; projectedBoxFacePointsRenderSettingsView.ToggleVisibilityBeforeRender = true; projectedBoxFacePointsRenderSettingsView.IndentContent = true; projectedBoxFacePointsRenderSettingsView.VisibilityToggleLabel = "Projected Guide Pivot Points"; projectedBoxFacePointsRenderSettingsView.IsVisible = false; SingleObjectPivotPointRenderSettingsView activePivotPointRenderSettingsView = projectedBoxFacePointsRenderSettings.ActivePivotPointRenderSettings.View; activePivotPointRenderSettingsView.ToggleVisibilityBeforeRender = true; activePivotPointRenderSettingsView.VisibilityToggleLabel = "Active Pivot Point"; activePivotPointRenderSettingsView.IndentContent = true; activePivotPointRenderSettingsView.VisibilityToggleIndent = 1; SingleObjectPivotPointRenderSettingsView inactivePivotPointRenderSettingsView = projectedBoxFacePointsRenderSettings.InactivePivotPointRenderSettings.View; inactivePivotPointRenderSettingsView.ToggleVisibilityBeforeRender = true; inactivePivotPointRenderSettingsView.VisibilityToggleLabel = "Inactive Pivot Point"; inactivePivotPointRenderSettingsView.IndentContent = true; inactivePivotPointRenderSettingsView.VisibilityToggleIndent = 1; ObjectMaskView objectMaskView = DecorPaintObjectPlacement.Get().DecorPaintMask.View; objectMaskView.SurroundWithBox = true; ObjectLayerObjectMaskView objectLayerObjectMaskView = DecorPaintObjectPlacement.Get().DecorPaintMask.ObjectLayerObjectMask.View; objectLayerObjectMaskView.IsVisible = false; objectLayerObjectMaskView.ToggleVisibilityBeforeRender = true; objectLayerObjectMaskView.VisibilityToggleIndent = 1; objectLayerObjectMaskView.VisibilityToggleLabel = "Object Layer Decor Paint Mask"; ObjectCollectionMaskView objectCollectionMaskView = DecorPaintObjectPlacement.Get().DecorPaintMask.ObjectCollectionMask.View; objectCollectionMaskView.IsVisible = false; objectCollectionMaskView.ToggleVisibilityBeforeRender = true; objectCollectionMaskView.VisibilityToggleIndent = 1; objectCollectionMaskView.VisibilityToggleLabel = "Object Decor Paint Mask"; LabelRenderSettings labelRenderSettings = ObjectPlacement.Get().BlockObjectPlacement.BlockRenderSettings.ManualConstructionRenderSettings.DimensionsLabelRenderSettings; labelRenderSettings.Bold = true; labelRenderSettings.FontSize = 15; labelRenderSettings.TextColor = Color.white; LabelRenderSettingsView labelRenderSettingsView = labelRenderSettings.View; labelRenderSettingsView.ToggleVisibilityBeforeRender = true; labelRenderSettingsView.VisibilityToggleLabel = "Dimensions Label"; labelRenderSettingsView.IndentContent = true; }
public void HandleSceneViewEvent(Event e) { if (e.IsUndoRedo()) { SceneViewCamera.Instance.SetObjectVisibilityDirty(); UndoRedoWasPerformedMessage.SendToInterestedListeners(e); // Last step necessary. We have to ensure that all objects have their wireframe hidden. // Otherwise, rendering with the 'Gizmos' API becomes corrupted (meshes are not rendered // anymore and some other entities like the snap grid becomes darker). Possibly a bug. if (ObjectPlacementSettings.Get().HideWireframeWhenPlacingObjects) { Octave3DWorldBuilder.ActiveInstance.HideWireframeForSceneObjectsAndPlacementGuide(); } return; } switch (e.type) { case EventType.Ignore: MouseButtonStates.Instance.ClearStates(); break; case EventType.Repaint: HandleRepaintEvent(e); break; case EventType.MouseMove: MouseCursor.Instance.HandleMouseMoveEvent(e); HandleMouseMoveEvent(e); break; case EventType.MouseDrag: HandleMouseDragEvent(e); break; case EventType.MouseDown: // Always disable the left mouse button down event in order to avoid deselecting the Octave3D object. MouseButtonStates.Instance.OnMouseButtonPressed((MouseButton)e.button); if (!e.alt && e.type == EventType.MouseDown && e.button == (int)MouseButton.Left && MouseButtonStates.Instance.GetNumberOfPressedButtons() <= 1) { e.DisableInSceneView(); } HandleMouseButtonDownEvent(e); break; case EventType.MouseUp: MouseButtonStates.Instance.OnMouseButtonReleased((MouseButton)e.button); HandleMouseButtonUpEvent(e); break; case EventType.ScrollWheel: HandleMouseScrollWheelEvent(e); break; case EventType.KeyDown: KeyboardButtonStates.Instance.OnKeyboardButtonPressed(e.keyCode); if (HandleGeneralShortcutKeys(e)) { return; } // Always disable the 'Delete' key in order to avoid deleting the Octave3D object from the scene. if (e.type == EventType.KeyDown && e.keyCode == KeyCode.Delete) { e.DisableInSceneView(); } if (e.keyCode == KeyCode.F) { Octave3DWorldBuilder activeInstance = Octave3DWorldBuilder.ActiveInstance; if (activeInstance != null) { List <GameObject> selectedObjects = new List <GameObject>(activeInstance.ObjectSelection.GetAllSelectedGameObjects()); Selection.objects = selectedObjects.ToArray(); if (SceneView.lastActiveSceneView != null) { SceneView.lastActiveSceneView.FrameSelected(); } activeInstance.OnCamFocused(); } break; } HandleKeyboardButtonDownEvent(e); break; case EventType.KeyUp: KeyboardButtonStates.Instance.OnKeyboardButtonReleased(e.keyCode); HandleKeyboardButtonUpEvent(e); break; case EventType.ExecuteCommand: HandleExecuteCommandEvent(e); break; } }
public static ObjectPlacementGuideSettings Get() { return(ObjectPlacementSettings.Get().ObjectPlacementGuideSettings); }
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 DecorPaintObjectPlacementSettings Get() { return(ObjectPlacementSettings.Get().DecorPaintObjectPlacementSettings); }
public static PointAndClickObjectPlacementSettings Get() { return(ObjectPlacementSettings.Get().PointAndClickPlacementSettings); }
public static BlockObjectPlacementSettings Get() { return(ObjectPlacementSettings.Get().BlockObjectPlacementSettings); }
public List <ObjectPlacementData> Calculate() { if (!ValidatePlacementDataCalculationConditions()) { return(new List <ObjectPlacementData>()); } _allowObjectIntersection = ObjectPlacementSettings.Get().ObjectIntersectionSettings.AllowIntersectionForPathPlacement; List <ObjectPlacementBoxStackSegment> allPathSegments = _path.GetAllSegments(); float objectMissChance = _path.Settings.ManualConstructionSettings.ObjectMissChance; bool usingSprites = _path.Settings.TileConnectionSettings.UsesSprites(); var tileConnectionDetector = new ObjectPlacementPathTileConnectionDetector(); var tileConnectionRotationCalculator = new ObjectPlacementPathTileConnectionRotationCalculator(); List <ObjectPlacementPathTileConnectionGridCell> tileConnectionGridCells = tileConnectionDetector.Detect(_path, _tileConnectionXZSize); if (tileConnectionGridCells.Count == 0) { return(new List <ObjectPlacementData>()); } List <Prefab> tileConnectionPrefabsExceptAutofill = PathObjectPlacement.Get().PathSettings.TileConnectionSettings.GetAllTileConnectionPrefabs(true); List <Vector3> tileConnectionWorldScaleValuesExceptAutofill = CalculateWorldScaleForAllTileConnectionPrefabsExceptAutofill(PrefabQueries.GetTransformsForAllPrefabs(tileConnectionPrefabsExceptAutofill), PrefabQueries.GetHierarchyWorldOrientedBoxesForAllPrefabs(tileConnectionPrefabsExceptAutofill)); List <Vector3> tileConnectionOffsetsExceptAutofill = CalculateOffsetsForAllTileConnectionsExceptAutofill(); var objectPlacementDataInstances = new List <ObjectPlacementData>(allPathSegments.Count * 10); foreach (ObjectPlacementPathTileConnectionGridCell tileConnectionGridCell in tileConnectionGridCells) { ObjectPlacementPathTileConnectionType tileConnectionType = tileConnectionGridCell.TileConnectionType; ObjectPlacementBoxStack tileConnectionStack = tileConnectionGridCell.TileConnectionStack; if (tileConnectionStack.IsOverlappedByAnotherStack) { continue; } Prefab tileConnectionPrefab = tileConnectionPrefabsExceptAutofill[(int)tileConnectionType]; Quaternion tileConnectionRotation = tileConnectionRotationCalculator.Calculate(tileConnectionGridCell); Vector3 tileConnectionWorldScale = tileConnectionWorldScaleValuesExceptAutofill[(int)tileConnectionType]; Vector3 tileConnectionOffset = tileConnectionOffsetsExceptAutofill[(int)tileConnectionType]; for (int stackBoxIndex = 0; stackBoxIndex < tileConnectionStack.NumberOfBoxes; ++stackBoxIndex) { ObjectPlacementBox box = tileConnectionStack.GetBoxByIndex(stackBoxIndex); if (box.IsHidden) { continue; } if (ObjectPlacementMissChance.Missed(objectMissChance, ObjectPlacementPathManualConstructionSettings.MinObjectMissChance, ObjectPlacementPathManualConstructionSettings.MaxObjectMissChance)) { continue; } if (!_allowObjectIntersection && ObjectQueries.IntersectsAnyObjectsInScene(box.OrientedBox, true)) { continue; } var objectPlacementData = new ObjectPlacementData(); objectPlacementData.WorldPosition = ObjectPositionCalculator.CalculateObjectHierarchyPosition(tileConnectionPrefab, box.Center, tileConnectionWorldScale, tileConnectionRotation); objectPlacementData.WorldPosition += tileConnectionOffset; objectPlacementData.WorldScale = tileConnectionWorldScale; objectPlacementData.WorldRotation = tileConnectionRotation; objectPlacementData.Prefab = tileConnectionPrefab; objectPlacementDataInstances.Add(objectPlacementData); } // Apply extrusion if necessary if (!usingSprites) { List <OrientedBox> extrusionOrientedBoxes = ObjectPlacementPathTileConnectionExtrusion.GetTileConnectionExtrusionOrientedBoxes(tileConnectionGridCell); foreach (OrientedBox extrusionBox in extrusionOrientedBoxes) { if (ObjectPlacementMissChance.Missed(objectMissChance, ObjectPlacementPathManualConstructionSettings.MinObjectMissChance, ObjectPlacementPathManualConstructionSettings.MaxObjectMissChance)) { continue; } if (!_allowObjectIntersection && ObjectQueries.IntersectsAnyObjectsInScene(extrusionBox, true)) { continue; } var objectPlacementData = new ObjectPlacementData(); objectPlacementData.WorldPosition = ObjectPositionCalculator.CalculateObjectHierarchyPosition(tileConnectionPrefab, extrusionBox.Center, tileConnectionWorldScale, tileConnectionRotation); objectPlacementData.WorldScale = tileConnectionWorldScale; objectPlacementData.WorldRotation = tileConnectionRotation; objectPlacementData.Prefab = tileConnectionPrefab; objectPlacementDataInstances.Add(objectPlacementData); } } } ObjectPlacementPathTileConnectionSettings tileConnectionSettings = _path.Settings.TileConnectionSettings; if (tileConnectionSettings.DoesAutofillTileConnectionHavePrefabAssociated()) { objectPlacementDataInstances.AddRange(GetPlacementDataForAutofillTiles(tileConnectionGridCells[0].ParentGrid)); } return(objectPlacementDataInstances); }