private void OnEnable() { PoissonPlacer placer = (PoissonPlacer)target; _helper = new PoissonHelper(placer); _helper.Init(); }
public void InitVisual(PoissonModeData modeData, PoissonData data, PoissonPlacer placer, bool isWindow, bool refreshTopMaterial) { if (!isWindow && HelperVisual && refreshTopMaterial) { // Always create new TopMaterial, because when we copy the placer, we don't want the TopMaterial shared TopMaterial = new Material(TopMaterial); UpdateVisualMode(modeData); } if (!HelperVisual) { CreateBoxMesh(); CreateCylinderMesh(); Shader shader = Shader.Find("Poisson/PoissonHelperShader"); TopMaterial = new Material(shader); TopMaterial.SetColor("_OuterColor", new Color(0.0f, 1.0f, 0.0f, 0.8f)); TopMaterial.SetColor("_InnerColor", new Color(1.0f, 0.0f, 0.0f, 0.8f)); TopMaterial.hideFlags = HideFlags.HideInInspector; FaceMaterial = new Material(shader); FaceMaterial.SetColor("_OuterColor", new Color(0.0f, 1.0f, 0.0f, 0.5f)); FaceMaterial.SetColor("_InnerColor", new Color(1.0f, 0.0f, 0.0f, 0.5f)); FaceMaterial.hideFlags = HideFlags.HideInInspector; GameObject parentObj = new GameObject(); if (placer) { parentObj.transform.parent = placer.transform; parentObj.transform.SetAsFirstSibling(); parentObj.transform.parent = parentObj.transform; parentObj.transform.localPosition = Vector3.zero; parentObj.transform.localRotation = Quaternion.identity; parentObj.transform.localScale = Vector3.one; } HelperVisual = new GameObject(); HelperVisual.transform.parent = parentObj.transform; HelperVisual.gameObject.SetActive(false); MeshFilter = HelperVisual.AddComponent <MeshFilter>(); Renderer = HelperVisual.AddComponent <MeshRenderer>(); if (!isWindow) { DeleteHelper = HelperVisual.AddComponent <PoissonDeleteHelper>(); } RefreshVisual(modeData, data, isWindow); } if (placer && !isWindow) { DeleteHelper.Placer = placer; } }
private static bool GetBounds(GameObject obj, EBoundsMode boundsMode, Vector3 position, Quaternion rotation, Vector3 scale, out Bounds bounds) { PoissonPlacer placer = obj.GetComponent <PoissonPlacer>(); if (placer != null) { Vector3 placerScale = placer.ModeData.Scale; placerScale.y = 0.5f; Matrix4x4 placerMat = Matrix4x4.TRS(placer.ModeData.Position, placer.ModeData.Rotation, placerScale); Matrix4x4 parentMat = Matrix4x4.TRS(position, rotation, scale); Matrix4x4 finalMat = parentMat * placerMat; bounds = CalculateBoundsFromMatrix(finalMat); return(true); } return(CalculateUnscaledBounds(obj, boundsMode, position, rotation, scale, out bounds)); }
public static void CleanupPlacedObjects(PoissonInternalEditorData editorData, int start) { for (int i = start; i <= editorData.PlacedObjects.Count - 1; ++i) { foreach (GameObject gameObject in editorData.PlacedObjects[i]) { if (gameObject) { PoissonPlacer placer = gameObject.GetComponent <PoissonPlacer>(); if (placer != null) { PoissonHelperInternalStorage.Instance.Remove(placer); CleanupPlacedObjects(placer.EditorData, 0); placer.EditorData.DestroyVisual(placer.ModeData); } Object.DestroyImmediate(gameObject); } } editorData.PlacedObjects[i].Clear(); } }
private bool CreateRandomObjectAtLoc(Vector2 loc, float finalMinDistSqrd, out bool objectPlaced, WeightedArray weightedObjects, ObjectOptions[] objectOptions, bool preview) { objectPlaced = false; if (InBounds(loc)) { bool toCloseToProcess = true; // Don't do InNeighbourhood for clumping algorithm if (finalMinDistSqrd <= 0 || (!InNeighbourhood(loc, finalMinDistSqrd, out toCloseToProcess) && !InInnerBounds(loc))) { RaycastHit hit; if (CastRay(loc, out hit)) { int index = weightedObjects.GetRandomObjectIndex(); ObjectOptions options = objectOptions[index]; float dotResult = Vector3.Dot(hit.normal, Vector3.up); if (dotResult >= options.MinDot && dotResult <= options.MaxDot) { Vector3 pos = hit.point; Quaternion rot; Vector3 scale; ApplySettingsToObject(options, hit.normal, ref pos, out rot, out scale); GameObject newObject = weightedObjects.GetGameObject(index); if (newObject != null) { if (_activeData.SphereCollisionCheck || _activeData.BoxCollisionCheck) { Bounds bounds; if (GetBounds(newObject, _activeData.BoundsMode, pos, rot, scale, out bounds)) { if (ModeData.Mode == DistributionMode.Surface) { ModeData.Surface.gameObject.SetActive(false); } bool hasOverlap = true; LayerMask correctedMask = InternalEditorUtility.ConcatenatedLayersMaskToLayerMask(_activeData.OverlapLayerMask); if (_activeData.SphereCollisionCheck) { hasOverlap = CheckSphereOverlap(bounds, correctedMask); } if (_activeData.BoxCollisionCheck && hasOverlap) { hasOverlap = CheckBoxOverlap(bounds, rot, correctedMask); } if (ModeData.Mode == DistributionMode.Surface) { ModeData.Surface.gameObject.SetActive(true); } if (hasOverlap) { return(!toCloseToProcess); } } } } else { return(!toCloseToProcess); } objectPlaced = true; GameObject obj = (GameObject)PrefabUtility.InstantiatePrefab(newObject); obj.transform.position = pos; obj.transform.rotation = rot; obj.transform.localScale = scale; // When not doing this the colliders aren't properly initialized and OverlapXXX won't work obj.SetActive(false); obj.SetActive(true); obj.transform.parent = options.Parent; EditorData.PlacedObjects[_activeLevel].Add(obj); if (_currNestingLevel < _maxNestingLevel) { PoissonPlacer placer = obj.GetComponent <PoissonPlacer>(); if (placer != null && placer.enabled) { PoissonHelper helper = new PoissonHelper(placer); helper.Init(); bool isValidSurface, preValid, currValid, postValid; int highestValid; helper.LoadDataHolder(); helper.ValidateSettings(false, out isValidSurface, out preValid, out currValid, out postValid, out highestValid); placer.EditorData.LastFrameValid = isValidSurface && preValid && currValid && postValid; if (highestValid >= 0) { Random.State randState = Random.state; helper.DistributePoisson(0, highestValid, preview, _currNestingLevel + 1, _maxNestingLevel); Random.state = randState; } helper.StoreDataHolder(); } } } } } return(!toCloseToProcess || objectPlaced); } return(false); }