/// <summary> /// Add the provided prefabs as new prefab settings using the template specified by name. /// Clear is applied if requested. /// </summary> /// <param name="templateName"></param> /// <param name="prefabs"></param> /// <param name="clear"></param> public void AddPrefabs(string templateName, List <GameObject> prefabs, bool clear) { // find tree template PrefabSettingsTemplate template = editor.FindTemplate(templateName); if (!template) { Debug.LogError("Template not found: " + templateName); return; } // clear the prefab settings list if required if (clear) { editor.GetPainter().prefabSettingsList.Clear(); } // add the prefabs using the given template foreach (GameObject prefab in prefabs) { PrefabSettings prefabSettings = new PrefabSettings(); prefabSettings.prefab = prefab; prefabSettings.ApplyTemplate(template); editor.GetPainter().prefabSettingsList.Add(prefabSettings); } // Apply changes to the serializedProperty - always do this in the end of OnInspectorGUI. editor.serializedObject.ApplyModifiedProperties(); }
public void PersistPrefab(PrefabSettings prefabSettings, PrefabTransform prefabTransform) { // spawn item to vs pro if (editorTarget.brushSettings.spawnToVSPro) { vegetationStudioProIntegration.AddNewPrefab(prefabSettings, prefabTransform.position, prefabTransform.rotation, prefabTransform.scale); } // spawn item to scene else { // new prefab GameObject instance = PrefabUtility.InstantiatePrefab(prefabSettings.prefab) as GameObject; instance.transform.position = prefabTransform.position; instance.transform.rotation = prefabTransform.rotation; instance.transform.localScale = prefabTransform.scale; // attach as child of container instance.transform.parent = editorTarget.container.transform; Undo.RegisterCreatedObjectUndo(instance, "Instantiate Prefab"); if (editorTarget.spawnSettings.autoSimulationType != SpawnSettings.AutoSimulationType.None) { autoPhysicsCollection.Add(instance); } } }
private void AddNewPrefab(PrefabSettings prefabSettings, Vector3 position, Vector3 normal) { PrefabTransform appliedTransform = CreateAppliedTransform(prefabSettings, position, normal); // create instance and apply position / rotation / scale brushModuleEditor.PersistPrefab(prefabSettings, appliedTransform); }
private void QuickRotationSetting(PrefabSettings prefabSettings, float x, float y, float z) { prefabSettings.randomRotation = true; prefabSettings.rotationMinX = 0f * x; prefabSettings.rotationMaxX = 360f * x; prefabSettings.rotationMinY = 0f * y; prefabSettings.rotationMaxY = 360f * y; prefabSettings.rotationMinZ = 0f * z; prefabSettings.rotationMaxZ = 360f * z; }
public void AddPrefab(GameObject prefab, PrefabSettingsTemplate template) { // new settings PrefabSettings prefabSettings = new PrefabSettings(); prefabSettings.ApplyTemplate(template); // initialize with dropped prefab prefabSettings.prefab = prefab; editor.newDraggedPrefabs.Add(prefabSettings); }
public PrefabSettings CreatePrefabSettings() { PrefabSettings selectedItem = GetRandomWeightedPrefab(); if (selectedItem == null) { Debug.LogError("No prefab is active! At least 1 prefab must be active."); return(null); } return(selectedItem); }
/// <summary> /// Add prefabs, mode Center /// </summary> public void AddPrefabs_Center(Vector3 position, Vector3 normal) { // check if a gameobject is already within the brush size // allow only 1 instance per bush size GameObject container = editorTarget.container as GameObject; // check if a prefab already exists within the brush bool prefabExists = false; // check overlap if (!editorTarget.brushSettings.allowOverlap) { float brushRadius = editorTarget.brushSettings.brushSize / 2f; foreach (Transform child in container.transform) { // ignore the preview if (previewPrefab != null && child.gameObject == previewPrefab.prefabInstance) { continue; } float dist = Vector3.Distance(position, child.transform.position); // check against the brush if (dist <= brushRadius) { prefabExists = true; break; } } } // create position vector Vector3 prefabPosition = new Vector3(position.x, position.y, position.z); //// auto physics height offset is moved to AddNewPrefab // prefabPosition = ApplyAutoPhysicsHeightOffset(prefabPosition); if (!prefabExists) { bool isInFilter = filterEvaluator.IsInFilter(position, editorTarget.filterSettings); if (isInFilter) { PrefabSettings prefabSettings = previewPrefab.prefabSettings; AddNewPrefab(prefabSettings, prefabPosition, normal); } } }
private void QuickRotationSetting(PrefabSettings prefabSettings, float x, float y, float z) { float min = prefabSettings.rotationRange.GetMinimum(); float max = prefabSettings.rotationRange.GetMaximum(); prefabSettings.randomRotation = true; prefabSettings.rotationMinX = min * x; prefabSettings.rotationMaxX = max * x; prefabSettings.rotationMinY = min * y; prefabSettings.rotationMaxY = max * y; prefabSettings.rotationMinZ = min * z; prefabSettings.rotationMaxZ = max * z; }
public void AddNewPrefab(PrefabSettings prefabSettings, Vector3 newPosition, Quaternion newRotation, Vector3 newLocalScale) { // brush mode float brushSize = editor.GetPainter().brushSettings.brushSize; // poisson mode: use the discs as brush size if (editor.GetPainter().brushSettings.distribution == BrushSettings.Distribution.Poisson_Any || editor.GetPainter().brushSettings.distribution == BrushSettings.Distribution.Poisson_Terrain) { brushSize = editor.GetPainter().brushSettings.poissonDiscSize; } GameObject prefab = prefabSettings.prefab; bool allowOverlap = editor.GetPainter().brushSettings.allowOverlap; terrainTreeManager.PlacePrefab(prefab, newPosition, newLocalScale, newRotation, brushSize, randomTreeColor, treeColorAdjustment, allowOverlap); }
/// <summary> /// Ensure the prefab has a VegetationItemID /// </summary> /// <param name="prefabSettings"></param> private void updateVSProSettings(PrefabSettings prefabSettings, bool forceVegetationItemIDUpdate) { #if VEGETATION_STUDIO_PRO GameObject prefab = prefabSettings.prefab; // check if we have a VegetationItemID, otherwise create it using the current prefab if (string.IsNullOrEmpty(prefabSettings.vspro_VegetationItemID) || forceVegetationItemIDUpdate) { // get the asset guid if (string.IsNullOrEmpty(prefabSettings.assetGUID)) { string assetPath = AssetDatabase.GetAssetPath(prefab); if (!string.IsNullOrEmpty(assetPath)) { string assetGUID = AssetDatabase.AssetPathToGUID(assetPath); prefabSettings.assetGUID = assetGUID; } } // if we have a guid, get the vs pro id if (!string.IsNullOrEmpty(prefabSettings.assetGUID)) { // get the VegetationItemID prefabSettings.vspro_VegetationItemID = VegetationStudioManager.GetVegetationItemID(prefabSettings.assetGUID); // if the vegetation item id doesn't exist, create a new vegetation item if (string.IsNullOrEmpty(prefabSettings.vspro_VegetationItemID)) { VegetationType vegetationType = VegetationType.Objects; bool enableRuntimeSpawn = false; // no runtime spawn, we want it spawned from persistent storage BiomeType biomeType = BiomeType.Default; prefabSettings.vspro_VegetationItemID = VegetationStudioManager.AddVegetationItem(prefab, vegetationType, enableRuntimeSpawn, biomeType); } } else { Debug.LogError("Can't get assetGUID for prefab " + prefab); } } if (string.IsNullOrEmpty(prefabSettings.vspro_VegetationItemID)) { Debug.LogError("Can't get VegetationItemId for prefab " + prefab); } #endif }
public void PersistPrefab(PrefabSettings prefabSettings, PrefabTransform prefabTransform) { switch (editorTarget.brushSettings.spawnTarget) { case BrushSettings.SpawnTarget.PrefabContainer: // new prefab GameObject instance = PrefabUtility.InstantiatePrefab(prefabSettings.prefab) as GameObject; instance.transform.position = prefabTransform.position; instance.transform.rotation = prefabTransform.rotation; instance.transform.localScale = prefabTransform.scale; // attach as child of container instance.transform.parent = editorTarget.container.transform; Undo.RegisterCreatedObjectUndo(instance, "Instantiate Prefab"); if (editorTarget.spawnSettings.autoSimulationType != SpawnSettings.AutoSimulationType.None) { autoPhysicsCollection.Add(instance); } break; case BrushSettings.SpawnTarget.TerrainTrees: unityTerrainTreesIntegration.AddNewPrefab(prefabSettings, prefabTransform.position, prefabTransform.rotation, prefabTransform.scale); break; case BrushSettings.SpawnTarget.TerrainDetails: Debug.LogError("Not implemented"); break; case BrushSettings.SpawnTarget.VegetationStudioPro: vegetationStudioProIntegration.AddNewPrefab(prefabSettings, prefabTransform.position, prefabTransform.rotation, prefabTransform.scale); break; } }
/// <summary> /// Add prefabs, mode Center /// </summary> public void AddPrefabs_Center(Vector3 position, Vector3 normal) { // check if a gameobject is already within the brush size // allow only 1 instance per bush size GameObject container = editorTarget.container as GameObject; // check if a prefab already exists within the brush bool prefabExists = false; // check overlap if (!editorTarget.brushSettings.allowOverlap) { float brushRadius = editorTarget.brushSettings.brushSize / 2f; foreach (Transform child in container.transform) { // ignore the preview if (previewPrefab != null && child.gameObject == previewPrefab.prefabInstance) { continue; } float dist = Vector3.Distance(position, child.transform.position); // check against the brush if (dist <= brushRadius) { prefabExists = true; break; } } } if (!prefabExists) { PrefabSettings prefabSettings = previewPrefab.prefabSettings; AddNewPrefab(prefabSettings, position, normal); } }
public void AddNewPrefab(PrefabSettings prefabSettings, Vector3 newPosition, Quaternion newRotation, Vector3 newLocalScale) { #if VEGETATION_STUDIO_PRO // ensure the prefab has a VegetationItemID updateVSProSettings(prefabSettings, true); if (!string.IsNullOrEmpty(prefabSettings.vspro_VegetationItemID)) { string vegetationItemID = prefabSettings.vspro_VegetationItemID; Vector3 worldPosition = newPosition; Vector3 scale = newLocalScale; // TODO local or world? Quaternion rotation = newRotation; bool applyMeshRotation = true; // TODO ??? float distanceFalloff = 1f; // TODO ??? bool clearCellCache = true; // TODO ??? byte vegetationSourceID = Constants.VegetationStudioPro_SourceId; VegetationStudioManager.AddVegetationItemInstance(vegetationItemID, worldPosition, scale, rotation, applyMeshRotation, vegetationSourceID, distanceFalloff, clearCellCache); } #endif }
private void ApplyPrefabSettings(int offsetLane, PrefabSettings prefabSettings, GameObject prefab, Vector3 currentPosition, Vector3 direction, List <SplinePoint> splinePoints, int currentSplinePointIndex) { // add prefab's position offset prefab.transform.position += prefabSettings.positionOffset; // auto physics: add additional height offset if (prefabPainter.spawnSettings.autoSimulationType != SpawnSettings.AutoSimulationType.None) { prefab.transform.position += new Vector3(0f, prefabPainter.spawnSettings.autoSimulationHeightOffset, 0f); } // lanes Vector3 splinePosition = prefab.transform.position; Quaternion splineRotation = Quaternion.LookRotation(direction); Vector3 addDistanceToDirection = Vector3.zero; if (offsetLane == 0) { // check if the objects should be aligned next to each other // TODO this is only done for the center lane currently; we don't have the information about the others // ie this only works in center lane mode currently if (prefabPainter.splineSettings.separation == SplineSettings.Separation.PrefabRadiusBounds) { // move along in the spline rotation, considering the radius (/2) addDistanceToDirection = splineRotation * prefab.transform.forward * GetDistanceToMove(prefab) / 2; } else if (prefabPainter.splineSettings.separation == SplineSettings.Separation.PrefabForwardSize) { // move along in the spline rotation, considering the extents (/2) addDistanceToDirection = splineRotation * prefab.transform.forward * GetDistanceToMove(prefab) / 2; } } // lane mode, all lanes except center else { // calculate offset distance to spline float offsetDistance = offsetLane * prefabPainter.splineSettings.laneDistance; // calculate the distance considering the spline direction //Vector3 distance = prefabPainter.splineSettings.lanePositionOffset - go.transform.position; addDistanceToDirection = splineRotation * prefab.transform.right * offsetDistance; } prefab.transform.position += addDistanceToDirection; // size if (prefabSettings.changeScale) { prefab.transform.localScale = Vector3.one * Random.Range(prefabSettings.scaleMin, prefabSettings.scaleMax); } // initial rotation Quaternion rotation = Quaternion.identity; switch (prefabPainter.splineSettings.instanceRotation) { case SplineSettings.Rotation.Spline: // rotation along spline rotation = Quaternion.LookRotation(direction); break; case SplineSettings.Rotation.SplineRandom: // rotation along spline rotation = Quaternion.LookRotation(direction); // add random rotation if (prefabSettings.randomRotation) { float rotationX = rotation.eulerAngles.x + Random.Range(prefabSettings.rotationMinX, prefabSettings.rotationMaxX); float rotationY = rotation.eulerAngles.y + Random.Range(prefabSettings.rotationMinY, prefabSettings.rotationMaxY); float rotationZ = rotation.eulerAngles.z + Random.Range(prefabSettings.rotationMinZ, prefabSettings.rotationMaxZ); rotation = Quaternion.Euler(rotationX, rotationY, rotationZ); } break; case SplineSettings.Rotation.Prefab: // rotation of the prefab if (prefabSettings.randomRotation) { float rotationX = Random.Range(prefabSettings.rotationMinX, prefabSettings.rotationMaxX); float rotationY = Random.Range(prefabSettings.rotationMinY, prefabSettings.rotationMaxY); float rotationZ = Random.Range(prefabSettings.rotationMinZ, prefabSettings.rotationMaxZ); rotation = Quaternion.Euler(rotationX, rotationY, rotationZ); } break; } // lerp rotation between control points along the spline if (prefabPainter.splineSettings.controlPointRotation) { /* * Quaternion controlPointRotation = prefabPainter.splineSettings.controlPoints[currentSplinePointIndex].rotation; * rotation *= controlPointRotation; */ int currentControlPointIndex = splinePoints[currentSplinePointIndex].startControlPointIndex; int nextControlPointIndex = currentControlPointIndex + 1; // check loop if (prefabPainter.splineSettings.loop) { if (nextControlPointIndex > prefabPainter.splineSettings.controlPoints.Count - 1) { nextControlPointIndex = 0; } } Vector3 currentControlPointPosition = prefabPainter.splineSettings.controlPoints[currentControlPointIndex].position; Vector3 nextControlPointPosition = prefabPainter.splineSettings.controlPoints[nextControlPointIndex].position; // the percentage that a spline point is between control points. ranges from 0 to 1 float percentageOnSegment = MathUtils.InverseLerp(currentControlPointPosition, nextControlPointPosition, currentPosition); // calculate lerp roation Quaternion currentControlPointRotation = prefabPainter.splineSettings.controlPoints[currentControlPointIndex].rotation; Quaternion nextControlPointRotation = prefabPainter.splineSettings.controlPoints[nextControlPointIndex].rotation; Quaternion lerpRotation = Quaternion.Lerp(currentControlPointRotation, nextControlPointRotation, percentageOnSegment); // add rotation rotation *= lerpRotation; } prefab.transform.rotation = rotation; // add prefab rotation offset prefab.transform.Rotate(prefabSettings.rotationOffset); }
private PrefabTransform CreateAppliedTransform(PrefabSettings prefabSettings, Vector3 position, Vector3 normal) { /// /// Calculate position / rotation / scale /// // get new position Vector3 newPosition = position; // add offset of brush in up direction newPosition += CalculateBrushOffsetUp(); // add offset of prefab settings newPosition += prefabSettings.positionOffset; // auto physics height offset newPosition = ApplyAutoPhysicsHeightOffset(newPosition); Vector3 newLocalScale = prefabSettings.prefab.transform.localScale; // size // please note that the scale might be change later again (scale to brush size) // which should happen after the rotation if (prefabSettings.changeScale) { newLocalScale = Vector3.one * Random.Range(prefabSettings.scaleMin, prefabSettings.scaleMax); } // rotation Quaternion alignedRotation = Quaternion.identity; Quaternion objectRotation; if (this.editorTarget.brushSettings.alignToTerrain) { alignedRotation = Quaternion.FromToRotation(Vector3.up, normal); } if (prefabSettings.randomRotation) { objectRotation = prefabSettings.instanceRotation; } else { objectRotation = Quaternion.Euler(prefabSettings.rotationOffset); } // additionally consider brush rotation Quaternion brushRotation = Quaternion.Euler(0f, editorTarget.brushSettings.brushRotation, 0f); // combine terrain aligned rotation and object rotation Quaternion newRotation = alignedRotation * objectRotation * brushRotation; // scale to brush size // this uses world bounds and happens after the rotation if (editorTarget.brushSettings.distribution == BrushSettings.Distribution.Fluent) { GameObject prefab = prefabSettings.prefab; Quaternion prevRotation = prefab.transform.rotation; { // we need to rotate the gameobject now in order to calculate the world bounds prefab.transform.rotation = newRotation; float brushSize = editorTarget.brushSettings.brushSize; Bounds worldBounds = BoundsUtils.CalculateBounds(prefab); Vector3 prefabScale = prefab.transform.localScale; float scaleFactorX = brushSize / worldBounds.size.x; float scaleFactorY = brushSize / worldBounds.size.y; float scaleFactorZ = brushSize / worldBounds.size.z; float scaleFactorXYZ = Mathf.Min(scaleFactorX, scaleFactorY, scaleFactorZ); newLocalScale = prefabScale * scaleFactorXYZ; } prefab.transform.rotation = prevRotation; } PrefabTransform prefabTransform = new PrefabTransform(newPosition, newRotation, newLocalScale); return(prefabTransform); }
public void OnSceneGUI() { // paint prefabs on mouse drag. don't do anything if no mode is selected, otherwise e.g. movement in scene view wouldn't work with alt key pressed if (brushComponent.DrawBrush(editorTarget.brushSettings, out BrushMode brushMode, out RaycastHit raycastHit)) { switch (brushMode) { case BrushMode.ShiftDrag: AddPrefabs(raycastHit); needsPhysicsApplied = true; // consume event Event.current.Use(); break; case BrushMode.ShiftCtrlDrag: RemovePrefabs(raycastHit); // consume event Event.current.Use(); break; } } if (IsFluent()) { if (!brushDistribution.HasPreviewPrefab()) { brushDistribution.CreatePreviewPrefab(); } // alt + mousewheel = modify height of preview prefab in transform up direction if (Event.current.modifiers == EventModifiers.Alt) { if (Event.current.isScrollWheel) { PrefabSettings previewPrefabSettings = brushDistribution.GetPreviewPrefabSettings(); // the delta value will be modified (reduced) in the offset calculation; it might be too much as it is previewPrefabSettings.brushOffsetUp += Event.current.delta.y; Event.current.Use(); } } brushDistribution.UpdatePreviewPrefab(raycastHit.point, raycastHit.normal); } // info for the scene gui; used to be dynamic and showing number of prefabs (currently is static until refactoring is done) string[] guiInfo = new string[] { "Add prefabs: shift + drag mouse" + "\nRemove prefabs: shift + ctrl + drag mouse" + "\nBrush size: ctrl + mousewheel, Brush rotation: ctrl + shift + mousewheel" }; brushComponent.Layout(guiInfo); // auto physics bool applyAutoPhysics = needsPhysicsApplied && autoPhysicsCollection.Count > 0 && editorTarget.spawnSettings.autoSimulationType != SpawnSettings.AutoSimulationType.None && Event.current.type == EventType.MouseUp; if (applyAutoPhysics) { AutoPhysicsSimulation.ApplyPhysics(editorTarget.physicsSettings, autoPhysicsCollection, editorTarget.spawnSettings.autoSimulationType); autoPhysicsCollection.Clear(); } }
public void OnInspectorGUI() { GUILayout.BeginVertical("box"); { EditorGUILayout.LabelField("Prefabs", GUIStyles.BoxTitleStyle); #region template drop targets GUILayout.BeginHorizontal(); { GUILayout.BeginVertical(); { // change background color in case there are no prefabs yet if (editorTarget.prefabSettingsList.Count == 0) { EditorGUILayout.HelpBox("Drop prefabs on the prefab template boxes in order to use them.", MessageType.Info); editor.SetErrorBackgroundColor(); } int gridRows = Mathf.CeilToInt((float)templateCollection.templates.Count / Constants.PrefabTemplateGridColumnCount); for (int row = 0; row < gridRows; row++) { GUILayout.BeginHorizontal(); { for (int column = 0; column < Constants.PrefabTemplateGridColumnCount; column++) { int index = column + row * Constants.PrefabTemplateGridColumnCount; PrefabSettingsTemplate template = index < templateCollection.templates.Count ? templateCollection.templates[index] : defaultTemplate; // drop area Rect prefabDropArea = GUILayoutUtility.GetRect(0.0f, 34.0f, GUIStyles.DropAreaStyle, GUILayout.ExpandWidth(true)); bool hasDropArea = index < templateCollection.templates.Count; if (hasDropArea) { // drop area box with background color and info text GUI.color = GUIStyles.DropAreaBackgroundColor; GUI.Box(prefabDropArea, template.templateName, GUIStyles.DropAreaStyle); GUI.color = GUIStyles.DefaultBackgroundColor; Event evt = Event.current; switch (evt.type) { case EventType.DragUpdated: case EventType.DragPerform: if (prefabDropArea.Contains(evt.mousePosition)) { DragAndDrop.visualMode = DragAndDropVisualMode.Copy; if (evt.type == EventType.DragPerform) { DragAndDrop.AcceptDrag(); // list of new prefabs that should be created via drag/drop // we can't do it in the drag/drop code itself, we'd get exceptions like // ArgumentException: Getting control 12's position in a group with only 12 controls when doing dragPerform. Aborting // followed by // Unexpected top level layout group! Missing GUILayout.EndScrollView/EndVertical/EndHorizontal? UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr) // they must be added when everything is done (currently at the end of this method) editor.newDraggedPrefabs = new List <PrefabSettings>(); foreach (Object droppedObject in DragAndDrop.objectReferences) { // allow only prefabs if (PrefabUtility.GetPrefabAssetType(droppedObject) == PrefabAssetType.NotAPrefab) { Debug.Log("Not a prefab: " + droppedObject); continue; } // add the prefab to the list using the template AddPrefab(droppedObject as GameObject, template); } } } break; } } } } GUILayout.EndHorizontal(); } editor.SetDefaultBackgroundColor(); } GUILayout.EndVertical(); } GUILayout.EndHorizontal(); #endregion template drop targets if (editorTarget.prefabSettingsList.Count > 0) { EditorGUILayout.Space(); } for (int i = 0; i < editorTarget.prefabSettingsList.Count; i++) { // horizontal separator editor.AddGUISeparator(i == 0 ? 0f : 10f, 10f); PrefabSettings prefabSettings = this.editorTarget.prefabSettingsList[i]; GUILayout.BeginHorizontal(); { // preview // try to get the asset preview Texture2D previewTexture = AssetPreview.GetAssetPreview(prefabSettings.prefab); // if no asset preview available, try to get the mini thumbnail if (!previewTexture) { previewTexture = AssetPreview.GetMiniThumbnail(prefabSettings.prefab); } // if a preview is available, paint it if (previewTexture) { //GUILayout.Label(previewTexture, EditorStyles.objectFieldThumb, GUILayout.Width(50), GUILayout.Height(50)); // without border, but with size GUILayout.Label(previewTexture, GUILayout.Width(50), GUILayout.Height(50)); // without border, but with size //GUILayout.Box(previewTexture); // with border //GUILayout.Label(previewTexture); // no border //GUILayout.Box(previewTexture, GUILayout.Width(50), GUILayout.Height(50)); // with border and size //EditorGUI.DrawPreviewTexture(new Rect(25, 60, 100, 100), previewTexture); // draws it in absolute coordinates } // right align the buttons GUILayout.FlexibleSpace(); if (GUILayout.Button("Add", EditorStyles.miniButton)) { this.editorTarget.prefabSettingsList.Insert(i + 1, new PrefabSettings()); } if (GUILayout.Button("Duplicate", EditorStyles.miniButton)) { PrefabSettings newPrefabSettings = prefabSettings.Clone(); this.editorTarget.prefabSettingsList.Insert(i + 1, newPrefabSettings); } if (GUILayout.Button("Reset", EditorStyles.miniButton)) { // remove existing this.editorTarget.prefabSettingsList.RemoveAt(i); // add new this.editorTarget.prefabSettingsList.Insert(i, new PrefabSettings()); } if (GUILayout.Button("Remove", EditorStyles.miniButton)) { this.editorTarget.prefabSettingsList.Remove(prefabSettings); } } GUILayout.EndHorizontal(); GUILayout.Space(4); prefabSettings.prefab = (GameObject)EditorGUILayout.ObjectField("Prefab", prefabSettings.prefab, typeof(GameObject), true); prefabSettings.active = EditorGUILayout.Toggle("Active", prefabSettings.active); prefabSettings.probability = EditorGUILayout.Slider("Probability", prefabSettings.probability, 0, 1); // scale if (editorTarget.brushSettings.distribution == BrushSettings.Distribution.Fluent) { // use the brush scale, hide the change scale option } else { prefabSettings.changeScale = EditorGUILayout.Toggle("Change Scale", prefabSettings.changeScale); if (prefabSettings.changeScale) { prefabSettings.scaleMin = EditorGUILayout.FloatField("Scale Min", prefabSettings.scaleMin); prefabSettings.scaleMax = EditorGUILayout.FloatField("Scale Max", prefabSettings.scaleMax); } } // position prefabSettings.positionOffset = EditorGUILayout.Vector3Field("Position Offset", prefabSettings.positionOffset); // rotation prefabSettings.rotationOffset = EditorGUILayout.Vector3Field("Rotation Offset", prefabSettings.rotationOffset); GUILayout.BeginHorizontal(); { prefabSettings.randomRotation = EditorGUILayout.Toggle("Random Rotation", prefabSettings.randomRotation); // right align the buttons GUILayout.FlexibleSpace(); if (GUILayout.Button("X", EditorStyles.miniButton)) { QuickRotationSetting(prefabSettings, 1f, 0f, 0f); } if (GUILayout.Button("Y", EditorStyles.miniButton)) { QuickRotationSetting(prefabSettings, 0f, 1f, 0f); } if (GUILayout.Button("Z", EditorStyles.miniButton)) { QuickRotationSetting(prefabSettings, 0f, 0f, 1f); } if (GUILayout.Button("XYZ", EditorStyles.miniButton)) { QuickRotationSetting(prefabSettings, 1f, 1f, 1f); } if (GUILayout.Button(prefabSettings.rotationRange.GetDisplayName(), EditorStyles.miniButton)) { prefabSettings.rotationRange = prefabSettings.rotationRange.GetNext(); } } GUILayout.EndHorizontal(); // rotation limits if (prefabSettings.randomRotation) { float min = prefabSettings.rotationRange.GetMinimum(); float max = prefabSettings.rotationRange.GetMaximum(); EditorGuiUtilities.MinMaxEditor(" Rotation Limit X", ref prefabSettings.rotationMinX, ref prefabSettings.rotationMaxX, min, max); EditorGuiUtilities.MinMaxEditor(" Rotation Limit Y", ref prefabSettings.rotationMinY, ref prefabSettings.rotationMaxY, min, max); EditorGuiUtilities.MinMaxEditor(" Rotation Limit Z", ref prefabSettings.rotationMinZ, ref prefabSettings.rotationMaxZ, min, max); } // VS Pro Id #if VEGETATION_STUDIO_PRO EditorGUI.BeginDisabledGroup(true); EditorGUILayout.TextField("Asset GUID", prefabSettings.assetGUID); EditorGUILayout.TextField("VSPro Id", prefabSettings.vspro_VegetationItemID); EditorGUI.EndDisabledGroup(); #endif } } GUILayout.EndVertical(); }
/// <summary> /// Add a new prefab to the spline /// </summary> // TODO: rewrite, use different approach: Use fake splines around the current spline. That way the separation distance doesn't matter // and you could have small prefabs on the outer spline, and big prefabs on the inner spline and they would distribute better private GameObject AddPrefab(ref int prefabInstanceIndex, Vector3 position, Vector3 direction, List <SplinePoint> splinePoints, int currentSplinePointIndex) { GameObject instance = null; // offset for lanes: lanes are from left to right, center is the spline. // so a spline with 5 lanes has these offset lanes: -2, -1, 0, 1, 2 int offsetLane = -prefabPainter.splineSettings.lanes / 2; for (var lane = 1; lane <= prefabPainter.splineSettings.lanes; lane++) { // skip center lane if requested if (prefabPainter.splineSettings.skipCenterLane && offsetLane == 0) { offsetLane++; continue; } // get settings for the prefab to instantiate PrefabSettings prefabSettings = prefabPainter.CreatePrefabSettings(); // check if we have settings at all if (prefabSettings == null) { return(null); } // instance will be created or used => advance index prefabInstanceIndex++; // reset the instance; check later if we should reuse one or create a new one instance = null; // check if we have to create a new instance or use an existing one if (prefabPainter.splineSettings.reusePrefabs) { if (prefabInstanceIndex < prefabPainter.splineSettings.prefabInstances.Count) { instance = prefabPainter.splineSettings.prefabInstances[prefabInstanceIndex]; } } // create instance if we don't have one yet if (instance == null) { // instantiate gameobject clone (lose reference to prefab //instance = GameObject.Instantiate(prefabSettings.prefab); // instantiate prefab instance = PrefabUtility.InstantiatePrefab(prefabSettings.prefab) as GameObject; prefabPainter.splineSettings.prefabInstances.Add(instance); } // reset position & rotation instance.transform.position = position; instance.transform.rotation = Quaternion.identity; ApplyPrefabSettings(offsetLane, prefabSettings, instance, position, direction, splinePoints, currentSplinePointIndex); // reparent the child to the container instance.transform.parent = prefabPainter.container.transform; offsetLane++; } return(instance); }