/// <summary> /// Draws a prefab at the pre-calculated mouse hit position /// </summary> private void DrawThePrefab() { #if PERFORMANCE var perf = PerformanceTesting <PerformanceID> .Instance; perf.Start(PerformanceID.Draw); #endif // do not draw if not the view tool if (Tools.current != Tool.View) { #if PERFORMANCE perf.Stop(PerformanceID.Draw); #endif return; } // checked if layer locked or not visible var layerModel = this.map.Layers[this.editor.ActiveLayer]; if (layerModel.Locked || !layerModel.Visible || !this.isDrawing) { #if PERFORMANCE perf.Stop(PerformanceID.Draw); #endif return; } // Calculate the position of the mouse over the grid layer var gridPosition = this.editor.GetMouseGridPosition(); // if grid position is the same as the last just exit if (gridPosition == this.lastPosition || this.drawRecord[gridPosition.X, gridPosition.Y] == Color.White) { #if PERFORMANCE perf.Stop(PerformanceID.Draw); #endif return; } // record last position this.lastPosition = gridPosition; // create the prefab var prefab = Helpers.CreatePrimitivePrefab(this.editor); Undo.RegisterCreatedObjectUndo(prefab, prefab.name); // apply drawing rules to the prefab var rulePrefab = this.ApplyDrawingRules(prefab, gridPosition, this.editor.ActiveLayer); // get grid mapping service var gridMappingService = GridMappingService.Instance; // if rulePrefab is null we check if prefab is null and destroy it if necessary GameObject existing; if (rulePrefab == null) { if (prefab != null) { UnityEngine.Object.DestroyImmediate(prefab); } // destroy existing prefab existing = this.editor.GameObjects.Get(gridPosition.X, gridPosition.Y, this.editor.ActiveLayer); if (existing != null) { Undo.DestroyObjectImmediate(prefab); } // make sure to erase before exiting this.editor.GameObjects.Set(gridPosition.X, gridPosition.Y, this.editor.ActiveLayer, null); // records the erase action in the draw record this.drawRecord[gridPosition.X, gridPosition.Y] = Color.White; // we can now exit #if PERFORMANCE perf.Stop(PerformanceID.Draw); #endif return; } // get reference to the settings manager var settings = SettingsManager.Instance; // check if original prefab and returned rulePrefab are not the same reference if (prefab != null && rulePrefab.GetInstanceID() != prefab.GetInstanceID()) { // check if users wants output rule information to console if (settings.GetSetting(GlobalConstants.DrawingRulesOutputToConsoleKey, false)) { Debug.Log(LocalizationManager.Instance.Get("DestroyingOriginallyCreatedPrefab")); } // destroy originally created prefab UnityEngine.Object.DestroyImmediate(prefab); } // assign prefab the reference to rulePrefab prefab = rulePrefab; // make sure to erase any existing prefab before drawing any new prefab existing = this.editor.GameObjects.Get(gridPosition.X, gridPosition.Y, this.editor.ActiveLayer); if (existing != null) { Undo.DestroyObjectImmediate(existing); } var nameFormat = settings.GetSetting(GlobalConstants.PrefabNameFormatKey, "{0}_l{1}_c{2}_r{3}"); // give the prefab a name that represents it's location within the grid map prefab.name = string.Format(nameFormat, prefab.name, this.editor.ActiveLayer, gridPosition.X, gridPosition.Y); // set local rotation first so the GetBoundWithChildren calculates properly var transform = prefab.transform; transform.localEulerAngles = new Vector3( this.editor.GetSelectedRotationValue(this.editor.SelectedXRotationIndex), this.editor.GetSelectedRotationValue(this.editor.SelectedYRotationIndex), this.editor.GetSelectedRotationValue(this.editor.SelectedZRotationIndex)); // position the prefab on the map this.map.PositionPrefabOnMap(this.editor.ActiveLayer, gridPosition.X, gridPosition.Y, prefab, this.editor.AutoCenterPrefab, this.editor.AutoScalePrefab); // update game object tracker this.editor.GameObjects.Set(gridPosition.X, gridPosition.Y, this.editor.ActiveLayer, prefab); // determine whether to hide the prefab in the hierarchy based on settings if (!SettingsManager.Instance.GetSetting(GlobalConstants.ShowPrefabsInHierarchyKey, true)) { prefab.hideFlags |= HideFlags.HideInHierarchy; EditorApplication.RepaintHierarchyWindow(); } EditorUtility.SetDirty(prefab); // get grid mapping service gridMappingService.OnPrefabDrawn(this.map, gridPosition.X, gridPosition.Y, this.editor.ActiveLayer, prefab); #if PERFORMANCE perf.Stop(PerformanceID.Draw); #endif }
/// <summary> /// Applies drawing rules to the prefab. /// </summary> /// <param name="prefab">The prefab to apply the drawing rules against.</param> /// <param name="gridPosition">The grid position where the prefab will be drawn at.</param> /// <param name="layer">The destination layer where the prefab will be drawn to.</param> /// <returns>Returns the original prefab or a new prefab that should be drawn.</returns> private GameObject ApplyDrawingRules(GameObject prefab, Point gridPosition, int layer) { // get reference to localization manager var local = LocalizationManager.Instance; var prefabToReturn = prefab; var random = new Random((int)DateTime.Now.Ticks); var settings = SettingsManager.Instance; var consoleOutput = settings.GetSetting(GlobalConstants.DrawingRulesOutputToConsoleKey, false); var consoleText = string.Empty; // for each enabled rule foreach (var pair in this.drawingRules) { if (!pair.Value.IsChecked) { continue; } // check if xml rule file has changed since last read if (File.GetLastWriteTime(pair.Key) > pair.Value.LastLoaded) { consoleText += local.Get("LoadingUpdatedRulesFromDisk") + "\r\n"; // reload the rules var rules = DrawingRulesEditor.LoadRulesFromFile(pair.Key, false); // if returned null there may have been an error reading the file if (rules == null) { return(null); } pair.Value.Rules = rules; pair.Value.LastLoaded = DateTime.Now; } foreach (var rule in pair.Value.Rules) { consoleText += string.Format(local.Get("PerformingRuleCheck") + "\r\n", rule.Name); // skip if rule not enabled if (!rule.Enabled) { consoleText += string.Format(local.Get("InitialRuleCheckFailedNotEnabled") + "\r\n", rule.Name); continue; } // skip if there are no alternates and not allowed to use original if (rule.Alternates == null || (rule.Alternates.Count == 0 && !rule.AllowOriginal)) { consoleText += string.Format(local.Get("InitialRuleCheckFailedOriginalNotAllowed") + "\r\n", rule.Name); continue; } // check if prefabs have a reference and there asset paths match var sourceRulePrefab = GridMapping.Helpers.GetSourcePrefab(rule.Prefab); var sourcePrefab = GridMapping.Helpers.GetSourcePrefab(prefab); if (sourceRulePrefab != sourcePrefab) { var text = string.Format(local.Get("InitialRuleCheckFailedAssetPaths"), rule.Name); text += "\r\n" + local.Get("RuleSource") + sourceRulePrefab; text += "\r\n" + local.Get("PrefabSource") + sourcePrefab; consoleText += text + "\r\n"; continue; } consoleText += local.Get("InitialCheckPassed") + "\r\n"; // callback for checking the existence of a prefab at a given grid location var callback = new Func <int, int, int, GameObject>((column, row, layerIndex) => this.editor.GameObjects.Get(column, row, layerIndex)); // check if presence of neighbors match var lower = !rule.NeighborsUpperEnabled || Helpers.CheckNeighborsPassed(gridPosition, layer - 1, false, rule, callback); var upper = !rule.NeighborsUpperEnabled || Helpers.CheckNeighborsPassed(gridPosition, layer + 1, false, rule, callback); var passed = Helpers.CheckNeighborsPassed(gridPosition, layer, true, rule, callback); consoleText += string.Format( local.Get("RulePassed") + "\r\n", rule.Name, passed & lower & upper, passed, lower, upper); // check if passed the neighbor tests if (passed && lower && upper) { if ((rule.Alternates == null || rule.Alternates.Count == 0) && !rule.AllowOriginal) { if (consoleOutput) { consoleText += string.Format(local.Get("ReturningOriginal") + "\r\n", prefabToReturn.name); Debug.Log(consoleText); } return(prefabToReturn); } // select from a random alternative prefab var index = random.Next(rule.Alternates.Count + (rule.AllowOriginal ? 1 : 0)); // return the alternate prefab var gameObject = index > rule.Alternates.Count - 1 ? prefabToReturn : rule.Alternates[index].Prefab; if (gameObject == null) { if (consoleOutput) { consoleText += local.Get("ReturningNullResponseNoPrefabToReturn") + "\r\n"; Debug.Log(consoleText); } return(null); } prefabToReturn = GridMapping.Helpers.PerformInstantiation(gameObject); var prefabType = PrefabUtility.GetPrefabType(gameObject); consoleText += string.Format(local.Get("ReturningAlternatePrefab") + "\r\n", index, gameObject.name, prefabType); if (consoleOutput && !string.IsNullOrEmpty(consoleText.Trim())) { Debug.Log(consoleText); } return(prefabToReturn); } } } if (consoleOutput && !string.IsNullOrEmpty(consoleText.Trim())) { Debug.Log(consoleText); } return(prefabToReturn); }