Exemple #1
0
        /// <summary>
        /// Checks to see if neighbors around a grid position match the rules neighbor conditional check.
        /// </summary>
        /// <param name="gridPosition">The column and row to check.</param>
        /// <param name="layer">The layer to check.</param>
        /// <param name="ignoreCenter">If true the center will be ignored.</param>
        /// <param name="rule">The rule that will be used to compare neighbors.</param>
        /// <param name="getPrefabCallback">A callback that returns a prefab at a given grid location.</param>
        /// <returns>True if the rule neighbors match the prefabs on the grid.</returns>
        public static bool CheckNeighborsPassed(Point gridPosition, int layer, bool ignoreCenter, DrawRuleModel rule, Func<int, int, int, GameObject> getPrefabCallback)
        {
            if (getPrefabCallback == null)
            {
                throw new ArgumentNullException("getPrefabCallback");
            }

            // check if neighbors match the rule
            var indexes = new[]
                {
                    new Point(-1, 1), new Point(0, 1), new Point(1, 1), 
                    new Point(-1, 0),  new Point(0, 0),  new Point(1, 0), 
                    new Point(-1, -1),  new Point(0, -1),  new Point(1, -1)
                };

            var passed = true;

            // check for each layer
            for (var i = 0; i < indexes.Length; i++)
            {
                // ignore index 4
                if (i == 4 && ignoreCenter)
                {
                    continue;
                }

                // get position
                var position = gridPosition + indexes[i];

                // check if neighbor specified and if there is a prefab at the neighbor index
                passed = rule.Neighbors[i] == (getPrefabCallback(position.X, position.Y, layer) != null);

                // if did not pass the test exit the loop
                if (!passed)
                {
                    break;
                }
            }

            return passed;
        }
Exemple #2
0
        /// <summary>
        /// Creates a clone of the object.
        /// </summary>
        /// <returns>Returns a clone of the object.</returns>
        public DrawRuleModel Clone()
        {
            var rule = new DrawRuleModel();

            rule.AllowOriginal         = this.AllowOriginal;
            rule.Description           = this.Description;
            rule.Enabled               = this.Enabled;
            rule.Name                  = this.Name;
            rule.NeighborsLowerEnabled = this.NeighborsLowerEnabled;
            rule.NeighborsUpperEnabled = this.NeighborsUpperEnabled;
            rule.Prefab                = this.Prefab;
            rule.neighbors             = this.neighbors;
            rule.neighborsLower        = this.neighborsLower;
            rule.neighborsUpper        = this.neighborsUpper;

            foreach (var alternate in this.Alternates)
            {
                rule.Alternates.Add(alternate.Clone());
            }

            return(rule);
        }
        /// <summary>
        /// Responsible for drawing rule name, description, asset path, enabled state etc.
        /// </summary>
        /// <param name="rule">The rule to draw the information for.</param>
        private void DrawRuleData(DrawRuleModel rule)
        {
            if (rule == null)
            {
                return;
            }

            GUILayout.BeginVertical();   // top wrapper

            // draws a header for the neighbor grids
            GUILayout.BeginHorizontal(GUI.skin.box);
            GUILayout.FlexibleSpace();
            GUILayout.Label("Rule information");
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

            GUILayout.BeginVertical();
            GUILayout.BeginHorizontal(); // top check boxes
            GUILayout.FlexibleSpace();

            // provide a enabled check box and determine if its state changed and if so set IsDirty
            GUI.SetNextControlName("chkEnabled");
            var enabledState = GUILayout.Toggle(rule.Enabled, "Enabled", GUILayout.ExpandWidth(false));
            if (enabledState != rule.Enabled)
            {
                rule.Enabled = enabledState;
                this.IsDirty = true;
            }

            // put some spacing between controls
            GUILayout.Space(16);

            // provide check box indicating whether or not the prefab being drawn is also allowed to be considered for drawing
            GUI.SetNextControlName("chkAllowOriginal");
            enabledState = GUILayout.Toggle(rule.AllowOriginal, "Allow Original", GUILayout.ExpandWidth(false));

            // if its state changed set IsDirty
            if (enabledState != rule.AllowOriginal)
            {
                rule.AllowOriginal = enabledState;
                this.IsDirty = true;
            }

            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal(); // top check boxes

            // show path to asset
            var sourcePrefab = Helpers.GetSourcePrefab(rule.Prefab);
            sourcePrefab = string.IsNullOrEmpty(sourcePrefab) ? string.Empty : sourcePrefab;

            GUILayout.BeginHorizontal();
            GUILayout.Label("Asset Path:", GUILayout.ExpandWidth(false));
           
            GUI.SetNextControlName("txtAssetPath");
            GUILayout.TextArea(sourcePrefab);
            EditorGUIUtility.LookLikeControls();
            GUILayout.EndHorizontal();

            // show category controls
            GUILayout.BeginHorizontal();   // category

            // provide button for toggling category display style
            GUI.SetNextControlName("chkCategory");
            var categoryPopup = GUILayout.Toggle(this.showCategoryPopup, "Category", GUI.skin.button, GUILayout.ExpandWidth(false));
            if (categoryPopup != this.showCategoryPopup)
            {
                this.showCategoryPopup = categoryPopup;

                // try to find index
                var index = Array.IndexOf(this.ruleCategories, rule.Category, 0);
                if (index != -1)
                {
                    this.selectedCategoryIndex = index;
                }
            }

            // get list of categories
            if (this.showCategoryPopup)
            {
                GUI.SetNextControlName("CategoryPopup");
                var index = EditorGUILayout.Popup(this.selectedCategoryIndex, this.ruleCategories);

                // detect category selection change and if so update rule category
                if (index != this.selectedCategoryIndex)
                {
                    this.selectedCategoryIndex = index;
                    rule.Category = this.ruleCategories[index];
                    this.IsDirty = true;
                }
            }
            else
            {
                GUI.SetNextControlName("txtCategory");
                var value = GUILayout.TextField(rule.Category ?? string.Empty);
                if (value != rule.Category)
                {
                    rule.Category = value;
                    this.IsDirty = true;
                }
            }

            GUILayout.EndHorizontal();  // category

            // show rule name controls
            GUILayout.BeginHorizontal();
            GUILayout.Label("Rule Name:", GUILayout.ExpandWidth(false));
            GUI.SetNextControlName("txtRuleName");
            var ruleName = GUILayout.TextField(rule.Name ?? string.Empty);
            GUILayout.EndHorizontal();

            // if its state changed set IsDirty
            if (ruleName != rule.Name)
            {
                rule.Name = ruleName;
                this.IsDirty = true;
            }

            // provide controls to set the rule description and allow for scrolling
            GUILayout.Label("Description:");
            this.descriptionScroll = GUILayout.BeginScrollView(this.descriptionScroll, false, false);
            GUI.SetNextControlName("txtDescription");
            var description = GUILayout.TextArea(rule.Description ?? string.Empty);
            GUILayout.EndScrollView();

            // if its state changed set IsDirty
            if (description != rule.Description)
            {
                rule.Description = description;
                this.IsDirty = true;
            }

            GUILayout.EndVertical(); // top wrapper
        }
        /// <summary>
        /// Draws the neighbor grids for the upper, lower and same layer neighbors.
        /// </summary>
        /// <param name="rule">The source rule to get the neighbor info from.</param>
        private void DrawNeighborGrids(DrawRuleModel rule)
        {
            GUILayout.BeginVertical();

            // draws a header for the neighbor grids
            GUILayout.BeginHorizontal(GUI.skin.box);
            GUILayout.FlexibleSpace();
            GUILayout.Label("Surrounding neighbors");
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal(GUILayout.MinHeight(125));
            GUILayout.FlexibleSpace();

            // setup default content for the upper and lower neighbor grids
            var emptyContent = new[]
                {
                    GUIContent.none, GUIContent.none, GUIContent.none, GUIContent.none, GUIContent.none, GUIContent.none,
                    GUIContent.none, GUIContent.none, GUIContent.none
                };

            GUILayout.BeginVertical(GUILayout.MinWidth(128));

            // provides a check box to indicate whether this rule takes into account the prefabs on the layer above
            GUI.SetNextControlName("chkUpperNeighbors");
            var enabled = GUILayout.Toggle(rule.NeighborsUpperEnabled, "Upper Neighbors");

            // determine if the state changed and if so set IsDirty
            if (enabled != rule.NeighborsUpperEnabled)
            {
                rule.NeighborsUpperEnabled = enabled;
                this.IsDirty = true;
            }

            // draw the upper neighbor grid
            rule.NeighborsUpper = this.DrawGrid(rule.NeighborsUpper, emptyContent);
            GUILayout.EndVertical();

            // put some spacing between grids
            GUILayout.Space(8);

            GUILayout.BeginVertical(GUILayout.MinWidth(128));
            GUILayout.Label("Neighbors", GUILayout.MinHeight(GUI.skin.toggle.CalcHeight(GUIContent.none, 100)));

            // setup neighbor grid content with center grid indicating the prefab that is drawn
            var image = AssetPreview.GetMiniTypeThumbnail(typeof(GameObject));
            var content = new[]
                {
                    GUIContent.none, GUIContent.none, GUIContent.none, GUIContent.none, new GUIContent(image),
                    GUIContent.none, GUIContent.none, GUIContent.none, GUIContent.none
                };

            // draw neighbor grid
            rule.Neighbors = this.DrawGrid(rule.Neighbors, content);
            rule.Neighbors[4] = false;
            GUILayout.EndVertical();

            // put some spacing between grids
            GUILayout.Space(8);

            // provides a check box to indicate whether this rule takes into account the prefabs on the layer below
            GUILayout.BeginVertical(GUILayout.MinWidth(128));
            GUI.SetNextControlName("chkLowerNeighbors");
            enabled = GUILayout.Toggle(rule.NeighborsLowerEnabled, "Lower Neighbors");

            // determine if the state changed and if so set IsDirty
            if (enabled != rule.NeighborsLowerEnabled)
            {
                rule.NeighborsLowerEnabled = enabled;
                this.IsDirty = true;
            }

            // draw lower neighbor grid
            rule.NeighborsLower = this.DrawGrid(rule.NeighborsLower, emptyContent);
            GUILayout.EndVertical();

            GUILayout.FlexibleSpace();

            GUILayout.EndHorizontal();
            GUILayout.EndVertical();
        }
        /// <summary>
        /// Draws the alternate prefab list for a rule.
        /// </summary>
        /// <param name="rule">The source rule whose alternate prefabs will be displayed in the list.</param>
        private void DrawAlternatePrefabsList(DrawRuleModel rule)
        {
            GUILayout.BeginVertical();    // top encapsulation

            // draw the header
            GUILayout.BeginHorizontal(GUI.skin.box);
            GUILayout.FlexibleSpace();
            GUILayout.Label("Alternate prefabs to draw");
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

            // draw alternate list controls
            this.DrawAlternateListHeaderControls(rule);

            // provide some spacing between the filter controls and the alternate prefab list
            GUILayout.Space(4);

            // draw alternate prefab list
            this.alternatePrefabListScroll = GUILayout.BeginScrollView(this.alternatePrefabListScroll, false, false, GUILayout.ExpandWidth(true));  // scroll view

            // calculate the number of columns to show
            var columns = (int)(this.lastRect.width / 154) - 1;
            columns = columns < 2 ? 2 : columns;

            GUILayout.BeginVertical();   // items in the list wrapper
            GUILayout.BeginHorizontal();  // rows
            var index = 0;
            var currentColumn = 0;
            while (index < rule.Alternates.Count)
            {
                // get reference to alternate prefab
                var alternate = rule.Alternates[index];

                // ensure alternate is not null and if it is remove it and continue
                if (alternate == null)
                {
                    rule.Alternates.RemoveAt(index);
                    continue;
                }

                // ensure that the reference is not null and that the name of the alternate prefab contains 
                // portions of the filter text if specified
                if (string.IsNullOrEmpty(this.alternateListFilter) || (!string.IsNullOrEmpty(alternate.Name) && alternate.Name.ToLower().Contains(this.alternateListFilter)))
                {
                    // draw the alternate item
                    this.DrawAlternateItem(alternate);

                    // determine if a different alternate prefab was selected
                    if (alternate.IsChecked && this.selectedAlternateIndex != index)
                    {
                        this.selectedAlternateIndex = index;
                    }
                }

                // check to see if we need to move to next row
                currentColumn++;
                if (currentColumn > columns)
                {
                    currentColumn = 0;
                    GUILayout.FlexibleSpace();
                    GUILayout.EndHorizontal(); // end row
                    GUILayout.BeginHorizontal(); // start a new row     
                }

                // move to next item
                index++;
            }

            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();   // rows
            GUILayout.EndVertical();   // items in the list wrapper

            GUILayout.EndScrollView();  // scroll view

            // calculate the layout width that we have to work with
            if (Event.current.type == EventType.Repaint)
            {
                this.lastRect = GUILayoutUtility.GetLastRect();
            }

            GUILayout.EndVertical();    // top encapsulation
        }
        /// <summary>
        /// Draw header controls for the alternate list.
        /// </summary>
        /// <param name="rule">A reference to the currently selected rule.</param>
        private void DrawAlternateListHeaderControls(DrawRuleModel rule)
        {
            // Draw controls for the alternate prefab list
            GUILayout.BeginHorizontal(); // control header bar
            var selectedPrefab = EditorGUILayout.ObjectField(this.alternatePrefab, typeof(GameObject), true, GUILayout.ExpandWidth(false)) as GameObject;
            if (selectedPrefab != this.alternatePrefab)
            {
                this.alternatePrefab = selectedPrefab;
                if (this.autoAddAlternate)
                {
                    this.AddAlternatePrefab(rule);
                }
            }

            // provides a add button to add the currently selected alternate prefab to the list
            if (GUILayout.Button("Add"))
            {
                this.AddAlternatePrefab(rule);
            }

            // provide a check box indicating whether or not alternate prefabs are added to the list simply by 
            // selecting them in the asset selection window
            this.autoAddAlternate = GUILayout.Toggle(this.autoAddAlternate, "Automatically add");
            GUILayout.FlexibleSpace();

            // provides a button for generating a preview of the selected alternate prefab in the off
            // chance unity is unable to generate a preview for us
            if (GUILayout.Button("Generate Preview"))
            {
                // not yet implemented!
                EditorUtility.DisplayDialog("Information", "Not implemented yet!", "Close");
            }

            // provides a remove button for removing alternate prefabs from the list
            if (GUILayout.Button("Remove"))
            {
                this.RemoveAlternatePrefab(rule);
            }

            GUILayout.EndHorizontal(); // control header bar

            // provide some spacing between the upper and lower controls
            GUILayout.Space(4);

            // draw a filter controls for filtering the list of displayed alternate prefabs
            GUILayout.BeginHorizontal(); // filtering controls
            GUILayout.FlexibleSpace();

            // draw filter label and text field
            GUILayout.Label("Filter", GUILayout.ExpandWidth(false));
            this.alternateListFilter = GUILayout.TextField(this.alternateListFilter ?? string.Empty, GUILayout.MinWidth(128));

            // provides a clear button to clear the filter
            if (GUILayout.Button("X", GUILayout.ExpandWidth(false)))
            {
                this.alternateListFilter = string.Empty;
            }

            // put some spacing between controls
            GUILayout.Space(8);

            // provide a none button to check all alternates
            if (GUILayout.Button("All"))
            {
                foreach (var alt in rule.Alternates)
                {
                    alt.IsChecked = true;
                }
            }

            // put some spacing between controls     
            GUILayout.Space(2);

            // provide a none button to uncheck all alternates
            if (GUILayout.Button("None"))
            {
                foreach (var alt in rule.Alternates)
                {
                    alt.IsChecked = false;
                }
            }

            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal(); // filtering controls
        }
        /// <summary>
        /// Adds a alternate prefab for the selected rule.
        /// </summary>
        /// <param name="rule">A reference to the rule where the alternate prefab will be added to.</param>
        private void AddAlternatePrefab(DrawRuleModel rule)
        {
            // do not allow null references to be added
            if (this.alternatePrefab == null)
            {
                return;
            }

            // if alternate prefab selection is not null and not already added then add it
            if (this.alternatePrefab != null)
            {
                rule.Alternates.Add(new PrefabListItem { Prefab = this.alternatePrefab });
            }

            // ensure that there is a alternate prefab selected
            this.selectedAlternateIndex = rule.Alternates.Count == 1 ? 0 : this.selectedAlternateIndex;

            // ensure the alternate prefab list is scrolled to view the added rule at the bottom of the list
            this.alternatePrefabListScroll.y = float.MaxValue;

            // we added a alternate prefab so record the rule change
            this.IsDirty = true;
        }
        /// <summary>
        /// Removes the currently selected alternate prefab.
        /// </summary>
        /// <param name="rule">The rule whose alternate prefab will be removed.</param>
        private void RemoveAlternatePrefab(DrawRuleModel rule)
        {
            if (rule.Alternates == null)
            {
                return;
            }

            var index = 0;
            while (index < rule.Alternates.Count)
            {
                if (rule.Alternates[index].IsChecked)
                {
                    rule.Alternates.RemoveAt(index);

                    // the rules set has changed so set IsDirty       
                    this.IsDirty = true;

                    continue;
                }

                index++;
            }
        }
        /// <summary>
        /// Draws a rule item in the rule list.
        /// </summary>
        /// <param name="rule">A reference to the rule to be drawn.</param>
        /// <param name="index">The index of the rule being drawn.</param>      
        /// <returns>Returns true if the rule has been checked.</returns>
        private bool DrawRuleListItem(DrawRuleModel rule, int index)
        {
            // setup button style to use
            var buttonStyle = new GUIStyle(GUI.skin.button) { alignment = TextAnchor.UpperCenter, imagePosition = ImagePosition.ImageAbove };

            // get asset preview
            var assetPreview = rule.Prefab == null ? null : AssetPreview.GetAssetPreview(rule.Prefab);
            assetPreview = assetPreview == null ? AssetPreview.GetMiniTypeThumbnail(typeof(GameObject)) : assetPreview;

            // draw asset preview
            GUILayout.BeginVertical(GUI.skin.box); // entry list item

            // if there is something to show then show it
            if (!string.IsNullOrEmpty(rule.Name) || rule.Prefab != this.prefab)
            {
                GUILayout.BeginHorizontal(); // top name and update button   

                // show the rule name above
                GUILayout.Label(rule.Name);

                // provide a button to update the rule prefab to the currently selected prefab
                if (rule.Prefab != null && GUILayout.Button("S", GUILayout.ExpandWidth(false)))
                {
                    Selection.objects = new Object[] { rule.Prefab };
                    EditorGUIUtility.PingObject(rule.Prefab);
                }

                // provide a button to update the rule prefab to the currently selected prefab
                if (Helpers.GetSourcePrefab(rule.Prefab) != Helpers.GetSourcePrefab(this.prefab) && GUILayout.Button("U", GUILayout.ExpandWidth(false)))
                {
                    rule.Prefab = this.prefab;
                    this.IsDirty = true;
                }

                GUILayout.EndHorizontal(); // top name and update button
            }

            // draw the actual toggle button for the entry
            var isChecked = GUILayout.Toggle(this.selectedRuleIndex == index, new GUIContent(rule.Prefab == null ? string.Empty : rule.Prefab.name, assetPreview), buttonStyle);

            GUILayout.EndVertical(); // entry list item
            return isChecked;
        }
        /// <summary>
        /// Creates a clone of the object.
        /// </summary>
        /// <returns>Returns a clone of the object.</returns>
        public DrawRuleModel Clone()
        {
            var rule = new DrawRuleModel();
            rule.AllowOriginal = this.AllowOriginal;
            rule.Description = this.Description;
            rule.Enabled = this.Enabled;
            rule.Name = this.Name;
            rule.NeighborsLowerEnabled = this.NeighborsLowerEnabled;
            rule.NeighborsUpperEnabled = this.NeighborsUpperEnabled;
            rule.Prefab = this.Prefab;
            rule.neighbors = this.neighbors;
            rule.neighborsLower = this.neighborsLower;
            rule.neighborsUpper = this.neighborsUpper;

            foreach (var alternate in this.Alternates)
            {
                rule.Alternates.Add(alternate.Clone());
            }

            return rule;
        }