private void AdjustObjectBoxRotationOnSurface(OrientedBox objectBox, ObjectSurfaceData objectSurfaceData, DecorPaintObjectPlacementBrushElement brushElement) { if (brushElement.AlignToSurface) { objectBox.Rotation = AxisAlignment.CalculateRotationQuaternionForAxisAlignment(objectBox.Rotation, brushElement.AlignmentAxis, objectSurfaceData.SurfaceNormal); } }
public void HandleMouseMoveEvent(Event e) { if (!_objectPlacementPath.IsUnderManualConstruction && ObjectPlacementGuide.ExistsInSceneAndIsActive) { ObjectPlacementGuide.Instance.Snap(); AxisAlignment.AlignObjectAxis(ObjectPlacementGuide.SceneObject, PathObjectPlacementSettings.Get().PlacementGuideSurfaceAlignmentSettings, ObjectSnapping.Get().ObjectSnapSurfacePlane.normal); // Note: This is necessary just in case the placement guide has changed. _objectPlacementPath.SetStartObject(ObjectPlacementGuide.SceneObject); } else if (ObjectPlacementGuide.ExistsInScene) { _objectPlacementPath.UpdateForMouseMoveEvent(); } }
private void AdjustGuidePositionAndRotation() { ObjectPlacementGuide.Instance.Snap(); AxisAlignment.AlignObjectAxis(ObjectPlacementGuide.SceneObject, BlockObjectPlacementSettings.Get().PlacementGuideSurfaceAlignmentSettings, ObjectSnapping.Get().ObjectSnapSurfacePlane.normal); }
private void AlignPlacementGuideAxisWithStrokeSurfaceNormalIfNecessary() { AxisAlignmentSettings surfaceAlignmentSettings = DecorPaintObjectPlacementSettings.Get().SingleDecorPaintModeSettings.PlacementGuideSurfaceAlignmentSettings; AxisAlignment.AlignObjectAxis(ObjectPlacementGuide.SceneObject, surfaceAlignmentSettings, StrokeSurfacePlane.normal); }
public void Update() { if (IsActive) { _currentCursorRayHit = GetCursorRayHit(); if (!_currentCursorRayHit.WasAnythingHit) { return; } if (_currentCursorRayHit.WasAnObjectHit) { GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects); GameObjectRayHit objectRayHit = _currentCursorRayHit.ClosestObjectRayHit; _surfaceHitPoint = objectRayHit.HitPoint; foreach (var grabbedObject in _grabbedObjects) { if (grabbedObject == null) { continue; } Transform objectTransform = grabbedObject.transform; objectTransform.position = objectRayHit.HitPoint + _objectToPivotDir[grabbedObject]; if (objectRayHit.WasTerrainHit) { Ray ray = new Ray(grabbedObject.GetHierarchyWorldOrientedBox().Center + Vector3.up, -Vector3.up); GameObjectRayHit sitPointHit = null; if (objectRayHit.HitObject.RaycastTerrainReverseIfFail(ray, out sitPointHit)) { if (_grabSettings.AlignAxis) { AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, sitPointHit.HitNormal); } grabbedObject.PlaceHierarchyOnPlane(new Plane(sitPointHit.HitNormal, sitPointHit.HitPoint)); if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis) { objectTransform.position += _grabSettings.OffsetFromSurface * sitPointHit.HitNormal; } if (_grabSettings.EmbedInSurfaceWhenNoAlign && !_grabSettings.AlignAxis) { grabbedObject.EmbedInSurfaceByVertex(-Vector3.up, objectRayHit.HitObject); } } } else if (objectRayHit.WasMeshHit) { Ray ray = new Ray(grabbedObject.GetHierarchyWorldOrientedBox().Center + objectRayHit.HitNormal * 2.0f, -objectRayHit.HitNormal); GameObjectRayHit sitPointHit = null; if (objectRayHit.HitObject.RaycastMeshReverseIfFail(ray, out sitPointHit)) { if (_grabSettings.AlignAxis) { AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, sitPointHit.HitNormal); } grabbedObject.PlaceHierarchyOnPlane(new Plane(sitPointHit.HitNormal, sitPointHit.HitPoint)); if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis) { objectTransform.position += _grabSettings.OffsetFromSurface * sitPointHit.HitNormal; } if (_grabSettings.EmbedInSurfaceWhenNoAlign && !_grabSettings.AlignAxis) { grabbedObject.EmbedInSurfaceByVertex(-sitPointHit.HitNormal, objectRayHit.HitObject); } } } } } else if (_currentCursorRayHit.WasACellHit) { GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects); GridCellRayHit cellRayHit = _currentCursorRayHit.GridCellRayHit; _surfaceHitPoint = cellRayHit.HitPoint; foreach (var grabbedObject in _grabbedObjects) { if (grabbedObject == null) { continue; } Transform objectTransform = grabbedObject.transform; objectTransform.position = cellRayHit.HitPoint + _objectToPivotDir[grabbedObject]; if (_grabSettings.AlignAxis) { AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, cellRayHit.HitNormal); } grabbedObject.PlaceHierarchyOnPlane(new Plane(cellRayHit.HitNormal, cellRayHit.HitPoint)); if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis) { objectTransform.position += _grabSettings.OffsetFromSurface * cellRayHit.HitNormal; } } } } }
public void Update() { if (IsActive) { if (AllShortcutCombos.Instance.GrabRotateSelection.IsActive()) { _state = State.Rotating; } else if (AllShortcutCombos.Instance.GrabScaleSelection.IsActive()) { if (_state != State.Scaling) { _objectToWorldScale.Clear(); foreach (var grabbedObject in _grabbedObjects) { if (grabbedObject != null) { _objectToWorldScale.Add(grabbedObject, grabbedObject.transform.lossyScale); } } _cursorPosAtScaleBegin = MouseCursor.Instance.Position; _state = State.Scaling; } } else { // Need to reset the anchor relationships because the cursor was moved without // the objects following it. if (_state == State.Rotating || _state == State.Scaling) { _objectToPivotDir.Clear(); foreach (var grabbedObject in _grabbedObjects) { if (grabbedObject != null) { _objectToPivotDir.Add(grabbedObject, grabbedObject.transform.position - _surfaceHitPoint); } } } _state = State.Moving; } _currentCursorRayHit = GetCursorRayHit(); if (!_currentCursorRayHit.WasAnythingHit) { return; } if (_currentCursorRayHit.WasAnythingHit) { if (_currentCursorRayHit.WasAnObjectHit) { _surfaceHitPoint = _currentCursorRayHit.ClosestObjectRayHit.HitPoint; } else { _surfaceHitPoint = _currentCursorRayHit.GridCellRayHit.HitPoint; } } if (_state == State.Moving || _objectToSurfaceInfo.Count == 0) { if (_currentCursorRayHit.WasAnObjectHit) { GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects); GameObjectRayHit objectRayHit = _currentCursorRayHit.ClosestObjectRayHit; foreach (var grabbedObject in _grabbedObjects) { if (grabbedObject == null) { continue; } Transform objectTransform = grabbedObject.transform; objectTransform.position = objectRayHit.HitPoint + _objectToPivotDir[grabbedObject]; if (objectRayHit.WasTerrainHit) { Ray ray = new Ray(grabbedObject.GetHierarchyWorldOrientedBox().Center + Vector3.up, -Vector3.up); GameObjectRayHit sitPointHit = null; if (objectRayHit.HitObject.RaycastTerrainReverseIfFail(ray, out sitPointHit)) { Plane surfacePlane = new Plane(sitPointHit.HitNormal, sitPointHit.HitPoint); if (_grabSettings.AlignAxis) { AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, sitPointHit.HitNormal); } grabbedObject.PlaceHierarchyOnPlane(surfacePlane); if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis) { objectTransform.position += _grabSettings.OffsetFromSurface * sitPointHit.HitNormal; } if (_grabSettings.EmbedInSurfaceWhenNoAlign && !_grabSettings.AlignAxis) { grabbedObject.EmbedInSurfaceByVertex(-Vector3.up, objectRayHit.HitObject); } ObjectSurfaceInfo surfaceInfo = new ObjectSurfaceInfo(); surfaceInfo.SurfacePlane = surfacePlane; surfaceInfo.SitPoint = sitPointHit.HitPoint; SetObjectSurfaceInfo(grabbedObject, surfaceInfo); } } else if (objectRayHit.WasMeshHit) { Ray ray = new Ray(grabbedObject.GetHierarchyWorldOrientedBox().Center + objectRayHit.HitNormal * 2.0f, -objectRayHit.HitNormal); GameObjectRayHit sitPointHit = null; if (objectRayHit.HitObject.RaycastMeshReverseIfFail(ray, out sitPointHit)) { Plane surfacePlane = new Plane(sitPointHit.HitNormal, sitPointHit.HitPoint); if (_grabSettings.AlignAxis) { AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, sitPointHit.HitNormal); } grabbedObject.PlaceHierarchyOnPlane(surfacePlane); if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis) { objectTransform.position += _grabSettings.OffsetFromSurface * sitPointHit.HitNormal; } if (_grabSettings.EmbedInSurfaceWhenNoAlign && !_grabSettings.AlignAxis) { grabbedObject.EmbedInSurfaceByVertex(-sitPointHit.HitNormal, objectRayHit.HitObject); } ObjectSurfaceInfo surfaceInfo = new ObjectSurfaceInfo(); surfaceInfo.SurfacePlane = surfacePlane; surfaceInfo.SitPoint = sitPointHit.HitPoint; SetObjectSurfaceInfo(grabbedObject, surfaceInfo); } } } } else if (_currentCursorRayHit.WasACellHit) { GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects); GridCellRayHit cellRayHit = _currentCursorRayHit.GridCellRayHit; foreach (var grabbedObject in _grabbedObjects) { if (grabbedObject == null) { continue; } Transform objectTransform = grabbedObject.transform; objectTransform.position = cellRayHit.HitPoint + _objectToPivotDir[grabbedObject]; Plane surfacePlane = new Plane(cellRayHit.HitNormal, cellRayHit.HitPoint); Vector3 sitPoint = surfacePlane.ProjectPoint(grabbedObject.GetWorldOrientedBox().Center); if (_grabSettings.AlignAxis) { AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, cellRayHit.HitNormal); } grabbedObject.PlaceHierarchyOnPlane(surfacePlane); if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis) { objectTransform.position += _grabSettings.OffsetFromSurface * cellRayHit.HitNormal; } ObjectSurfaceInfo surfaceInfo = new ObjectSurfaceInfo(); surfaceInfo.SurfacePlane = surfacePlane; surfaceInfo.SitPoint = sitPoint; SetObjectSurfaceInfo(grabbedObject, surfaceInfo); } } } else if (_state == State.Rotating) { GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects); float rotationSensitivity = _grabSettings.RotationSensitivity; foreach (var grabbedObject in _grabbedObjects) { if (!_objectToSurfaceInfo.ContainsKey(grabbedObject)) { continue; } var surfaceInfo = _objectToSurfaceInfo[grabbedObject]; OrientedBox worldOOBB = grabbedObject.GetHierarchyWorldOrientedBox(); grabbedObject.RotateHierarchyBoxAroundPoint(MouseCursor.Instance.OffsetSinceLastMouseMove.x * rotationSensitivity, _grabSettings.AlignAxis ? surfaceInfo.SurfacePlane.normal : Vector3.up, worldOOBB.Center); } } else if (_state == State.Scaling) { GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects); Vector2 currentCursorPos = MouseCursor.Instance.Position; Vector2 cursorOffsetFromScaleBegin = currentCursorPos - _cursorPosAtScaleBegin; float scaleFactor = 1.0f + _grabSettings.ScaleSensitivity * cursorOffsetFromScaleBegin.x; foreach (var grabbedObject in _grabbedObjects) { if (!_objectToSurfaceInfo.ContainsKey(grabbedObject) || !_objectToWorldScale.ContainsKey(grabbedObject)) { continue; } var surfaceInfo = _objectToSurfaceInfo[grabbedObject]; grabbedObject.SetHierarchyWorldScaleByPivotPoint(_objectToWorldScale[grabbedObject] * scaleFactor, surfaceInfo.SitPoint); } } } }
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); }