├── .editorconfig
├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── assets
├── Editor.meta
└── Editor
│ ├── EditorMenu.cs
│ ├── EditorMenu.cs.meta
│ ├── EditorMenuCommandBinder.cs
│ ├── EditorMenuCommandBinder.cs.meta
│ ├── EditorMenuCommandEntry.cs
│ ├── EditorMenuCommandEntry.cs.meta
│ ├── EditorMenuEntry.cs
│ ├── EditorMenuEntry.cs.meta
│ ├── EditorMenuInternalUtility.cs
│ ├── EditorMenuInternalUtility.cs.meta
│ ├── EditorMenuPresenterUtility.cs
│ ├── EditorMenuPresenterUtility.cs.meta
│ ├── EditorMenuPresenter_GenericMenu.cs
│ ├── EditorMenuPresenter_GenericMenu.cs.meta
│ ├── EditorMenuSeparatorBinder.cs
│ ├── EditorMenuSeparatorBinder.cs.meta
│ ├── EditorMenuSeparatorEntry.cs
│ ├── EditorMenuSeparatorEntry.cs.meta
│ ├── EditorMenuSettings.cs
│ ├── EditorMenuSettings.cs.meta
│ ├── IEditorMenuEntry.cs
│ ├── IEditorMenuEntry.cs.meta
│ ├── IEditorMenuEntryParameter.cs
│ ├── IEditorMenuEntryParameter.cs.meta
│ ├── IEditorMenuPresenter.cs
│ ├── IEditorMenuPresenter.cs.meta
│ ├── _assembly.asmdef
│ └── _assembly.asmdef.meta
├── index.js
└── package.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | ; Grab the EditorConfig extension for Visual Studio:
2 | ; https://visualstudiogallery.msdn.microsoft.com/c8bccfe2-650c-4b42-bc5c-845e21f96328
3 |
4 | ; Top-most EditorConfig file
5 | root = true
6 |
7 | ; Unix-style newlines with a newline ending every file
8 | [*]
9 | end_of_line = LF
10 | insert_final_newline = true
11 | indent_style = space
12 | indent_size = 4
13 | trim_trailing_whitespace = true
14 |
15 | [*.{md,yaml}]
16 | trim_trailing_whitespace = false
17 |
18 | [*.{js,json,yaml,html,css,styl}]
19 | indent_size = 2
20 |
21 | [Makefile]
22 | indent_style = tab
23 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Apply native OS line-endings on checkout of these files...
2 | *.boo text
3 | *.c text
4 | *.cginc text
5 | *.config text
6 | *.contentproj text
7 | *.cpp text
8 | *.cs text
9 | *.css text
10 | *.dae text
11 | *.DAE text
12 | *.dtd text
13 | *.fx text
14 | *.glsl text
15 | *.h text
16 | *.htm text
17 | *.html text
18 | *.inc text
19 | *.ini text
20 | *.js text
21 | *.JSFL text
22 | *.jsfl text
23 | *.json text
24 | *.log text
25 | *.md text
26 | *.mel text
27 | *.php text
28 | *.po text
29 | *.shader text
30 | *.txt text
31 | *.TXT text
32 | *.xaml text
33 | *.xml text
34 | *.xsd text
35 | .gitattributes text
36 | .gitignore text
37 | COPYING text
38 | INSTALL* text
39 | KEYS* text
40 | LICENSE* text
41 | NEWS* text
42 | NOTICE* text
43 | README* text
44 | TODO* text
45 | WHATSNEW* text
46 |
47 | # Apply Unix-style LF line-endings on checkout for these files since Unity
48 | # project has been configured to force text output for them...
49 | *.anim text eol=lf
50 | *.asset text eol=lf
51 | *.controller text eol=lf
52 | *.cubemap text eol=lf
53 | *.guiskin text eol=lf
54 | *.mat text eol=lf
55 | *.prefab text eol=lf
56 | *.physicMaterial text eol=lf
57 | *.physicmaterial text eol=lf
58 | *.unity text eol=lf
59 |
60 | # Apply Unix-style LF line-endings on checkout of these files...
61 | *.meta text eol=lf
62 | *.sh text eol=lf
63 | *.vspscc text eol=lf
64 | .htaccess text eol=lf
65 |
66 | # Apply Windows/DOS-style CR-LF line-endings on checkout of these files...
67 | *.bat text eol=crlf
68 | *.cmd text eol=crlf
69 | *.csproj text eol=crlf
70 | *.sln text eol=crlf
71 | *.user text eol=crlf
72 | *.vcproj text eol=crlf
73 |
74 | # No end-of-line conversions are applied (i.e., "-text -diff") to these files...
75 | *.7z binary
76 | *.ai binary
77 | *.apk binary
78 | *.bin binary
79 | *.bmp binary
80 | *.BMP binary
81 | *.com binary
82 | *.COM binary
83 | *.dex binary
84 | *.dll binary
85 | *.DLL binary
86 | *.dylib binary
87 | *.eps binary
88 | *.exe binary
89 | *.EXE binary
90 | *.exr binary
91 | *.fbx binary
92 | *.FBX binary
93 | *.fla binary
94 | *.flare binary
95 | *.flv binary
96 | *.gif binary
97 | *.gz binary
98 | *.ht binary
99 | *.ico binary
100 | *.jpeg binary
101 | *.jpg binary
102 | *.keystore binary
103 | *.mask binary
104 | *.mb binary
105 | *.mo binary
106 | *.mp3 binary
107 | *.mp4 binary
108 | *.mpg binary
109 | *.ogg binary
110 | *.PCX binary
111 | *.pcx binary
112 | *.pdb binary
113 | *.pdf binary
114 | *.png binary
115 | *.ps binary
116 | *.psd binary
117 | *.qt binary
118 | *.so binary
119 | *.swf binary
120 | *.tga binary
121 | *.tif binary
122 | *.tiff binary
123 | *.ttf binary
124 | *.TTF binary
125 | *.unitypackage binary
126 | *.unityPackage binary
127 | *.wav binary
128 | *.wmv binary
129 | *.zip binary
130 | *.ZIP binary
131 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Derived From:
2 | # http://kleber-swf.com/the-definitive-gitignore-for-unity-projects/
3 |
4 | # ============= #
5 | # Working Files #
6 | # ============= #
7 | node_modules/
8 | npm-debug.log
9 |
10 | # ===================== #
11 | # Working Files - Unity #
12 | # ===================== #
13 | /Temp/
14 | /Library/
15 | /Packages/
16 | /ProjectSettings/
17 | /assets/Plugins/
18 | /assets/Plugins.meta
19 | /*.csproj
20 | /*.sln
21 |
22 | # ===================================== #
23 | # Visual Studio / MonoDevelop generated #
24 | # ===================================== #
25 | /.vs/
26 | bin
27 | obj
28 | ExportedObj/
29 | *.svd
30 | *.userprefs
31 | *.pidb
32 | *.suo
33 | *.user
34 | *.unityproj
35 | *.booproj
36 | *.pdb
37 | *.pdb.meta
38 |
39 | # ============ #
40 | # OS generated #
41 | # ============ #
42 | .DS_Store
43 | .DS_Store?
44 | *~
45 | ._*
46 | .Spotlight-V100
47 | .Trashes
48 | Icon?
49 | ehthumbs.db
50 | Thumbs.db
51 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014-2017 Rotorz Limited
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # unity3d-editor-menu
2 |
3 | Fluent style API for constructing custom editor menus presented using `GenericMenu` by
4 | default although alternative presentation can be configured for project.
5 |
6 | ```sh
7 | $ yarn add rotorz/unity3d-editor-menu
8 | ```
9 |
10 | This package is compatible with the [unity3d-package-syncer][tool] tool. Refer to the
11 | tools' [README][tool] for information on syncing packages into a Unity project.
12 |
13 | [tool]: https://github.com/rotorz/unity3d-package-syncer
14 |
15 |
16 | ## Usage Example
17 |
18 | Here is a basic example of building an editor menu:
19 |
20 | ```csharp
21 | var menu = new EditorMenu();
22 |
23 | menu.AddCommand("Open in Designer...")
24 | .Enabled(selection is IDesignable)
25 | .Action(this.OnContextMenu_OpenInDesigner);
26 |
27 | menu.AddSeparator();
28 |
29 | menu.AddCommand("Duplicate")
30 | .Action(this.OnContextMenu_Duplicate);
31 | menu.AddCommand("Delete")
32 | .Action(this.OnContextMenu_Delete);
33 |
34 | menu.ShowAsContext();
35 | ```
36 |
37 |
38 | Selections can be shown by checking (ticking / selecting) the menu command; for example:
39 |
40 | ```csharp
41 | if (EditorGUI.DropdownButton(new GUIContent("Menu Button"), FocusType.Keyboard)) {
42 | var menu = new EditorMenu();
43 |
44 | menu.AddCommand("Show Grid")
45 | .Checked(this.ShowGrid)
46 | .Action(() => this.ShowGrid = !this.ShowGrid);
47 |
48 | menu.ShowAsDropdown(GUILayoutUtility.GetLastRect());
49 | }
50 | ```
51 |
52 |
53 | ## Setting up a Custom Presentation
54 |
55 | By default editor menus are presented using the Unity `GenericMenu` API although this can
56 | be overridden on a per-instance or project-wide basis if desired.
57 |
58 | To override the default presentation create a JSON settings file at the path illustrated
59 | below and specify the implementation type that you would like to use in your project:
60 |
61 | **/Assets/Plugins/PackageData/@rotorz/unity3d-editor-menu/EditorMenuSettings.json**
62 | ```json
63 | {
64 | "DefaultPresenterTypeName": "MyNamespace.CustomEditorMenuPresenter"
65 | }
66 | ```
67 |
68 | Packages that provide alternative editor menu presentations should not attempt to override
69 | the setting automatically; the end-user should make a conscious effort to opt-in.
70 |
71 |
72 | ## Contribution Agreement
73 |
74 | This project is licensed under the MIT license (see LICENSE). To be in the best
75 | position to enforce these licenses the copyright status of this project needs to
76 | be as simple as possible. To achieve this the following terms and conditions
77 | must be met:
78 |
79 | - All contributed content (including but not limited to source code, text,
80 | image, videos, bug reports, suggestions, ideas, etc.) must be the
81 | contributors own work.
82 |
83 | - The contributor disclaims all copyright and accepts that their contributed
84 | content will be released to the public domain.
85 |
86 | - The act of submitting a contribution indicates that the contributor agrees
87 | with this agreement. This includes (but is not limited to) pull requests, issues,
88 | tickets, e-mails, newsgroups, blogs, forums, etc.
89 |
--------------------------------------------------------------------------------
/assets/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ab2ce05f30975f94b8fd1f7e5698e8e1
3 | folderAsset: yes
4 | timeCreated: 1498840470
5 | licenseType: Pro
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenu.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Rotorz Limited. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using UnityEngine;
7 |
8 | namespace Rotorz.Games.UnityEditorExtensions
9 | {
10 | ///
11 | /// Essentially the model of a custom editor menu.
12 | ///
13 | ///
14 | ///
15 | public class EditorMenu
16 | {
17 | private readonly List entries = new List();
18 | private readonly IEditorMenuPresenter presenter;
19 |
20 |
21 | ///
22 | /// Initializes a new instance of the class.
23 | ///
24 | /// An object that somehow presents the
25 | /// to the end-user.
26 | ///
27 | /// If is null.
28 | ///
29 | public EditorMenu(IEditorMenuPresenter presenter)
30 | {
31 | if (presenter == null) {
32 | throw new ArgumentNullException("presenter");
33 | }
34 |
35 | this.presenter = presenter;
36 | }
37 |
38 | ///
39 | /// Initializes a new instance of the class with the
40 | /// default implementation.
41 | ///
42 | ///
43 | /// The default presenter can be overridden project-wide if desired. Refer
44 | /// to for more information regarding this.
45 | ///
46 | public EditorMenu()
47 | : this(EditorMenuPresenterUtility.GetDefaultPresenterInstance())
48 | {
49 | }
50 |
51 |
52 | ///
53 | /// Gets the editable list of entries that make up the .
54 | ///
55 | ///
56 | /// Non-supported entry types may be ignored or highlighted.
57 | ///
58 | public IList Entries {
59 | get { return this.entries; }
60 | }
61 |
62 |
63 | ///
64 | /// Adds a command to the .
65 | ///
66 | ///
67 | /// Add command with a straightforward action:
68 | /// {
72 | /// Debug.Log("Woot!");
73 | /// });
74 | /// ]]>
75 | ///
76 | /// Add a command that is always disabled:
77 | ///
81 | ///
82 | /// Add a command that is conditionally disabled:
83 | /// {
88 | /// Undo.DestroyObjectImmediate(selectedObject);
89 | /// });
90 | /// ]]>
91 | ///
92 | /// Add a command that is conditionally visible:
93 | /// {
98 | /// var tilesetBrush = selectedObject as TilesetBrush;
99 | /// ToolUtility.ShowTilesetInDesigner(tilesetBrush.Tileset);
100 | /// });
101 | /// ]]>
102 | ///
103 | /// Add commands to a sub-menu:
104 | /// this.SortMode = SortMode.Ascending);
109 | /// menu.AddCommand("Sort/Descending")
110 | /// .Checked(this.SortMode == SortMode.Descending)
111 | /// .Action(() => this.SortMode = SortMode.Descending);
112 | /// ]]>
113 | ///
114 | /// Full path of the menu command.
115 | ///
116 | /// Fluid style API to further define the new command entry.
117 | ///
118 | ///
119 | /// If is null.
120 | ///
121 | ///
122 | /// If is an empty string or starts with a slash.
123 | ///
124 | ///
125 | public virtual EditorMenuCommandBinder AddCommand(string fullPath)
126 | {
127 | var entry = new EditorMenuCommandEntry(fullPath);
128 | this.entries.Add(entry);
129 | return new EditorMenuCommandBinder(entry);
130 | }
131 |
132 | ///
133 | /// Adds a separator to the .
134 | ///
135 | ///
136 | /// Add separator between two logical groups of commands:
137 | ///
145 | ///
146 | /// Add a separator in a sub-menu:
147 | ///
155 | ///
156 | /// Path to the separator.
157 | ///
158 | /// Fluid style API to further define the new separator entry.
159 | ///
160 | ///
161 | /// If is an empty string or starts with a slash.
162 | ///
163 | ///
164 | public virtual EditorMenuSeparatorBinder AddSeparator(string path = "")
165 | {
166 | var entry = new EditorMenuSeparatorEntry(path);
167 | this.entries.Add(entry);
168 | return new EditorMenuSeparatorBinder(entry);
169 | }
170 |
171 |
172 | ///
173 | /// Derived implementations can override this method to
174 | /// perform custom actions each time before the is shown
175 | /// with or .
176 | ///
177 | protected virtual void PrepareToShow()
178 | {
179 | }
180 |
181 |
182 | ///
183 | /// Shows the as a context menu.
184 | ///
185 | ///
186 | public void ShowAsContext()
187 | {
188 | this.PrepareToShow();
189 | this.presenter.ShowAsContext(this);
190 | }
191 |
192 | ///
193 | /// Shows the as a drop-down from a GUI control.
194 | ///
195 | /// Absolute position of GUI drop-down control.
196 | ///
197 | public void ShowAsDropdown(Rect position)
198 | {
199 | this.PrepareToShow();
200 | this.presenter.ShowAsDropdown(position, this);
201 | }
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenu.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5c750dda6844d3140955b9876a607fe3
3 | timeCreated: 1499131236
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuCommandBinder.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Rotorz Limited. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root.
3 |
4 | using System;
5 |
6 | namespace Rotorz.Games.UnityEditorExtensions
7 | {
8 | ///
9 | /// Binds additional information to an command entry.
10 | ///
11 | public class EditorMenuCommandBinder
12 | {
13 | ///
14 | /// Initializes a new instance of the class.
15 | ///
16 | /// The associated command entry.
17 | ///
18 | /// If is null.
19 | ///
20 | public EditorMenuCommandBinder(EditorMenuCommandEntry entry)
21 | {
22 | ExceptionUtility.CheckArgumentNotNull(entry, "entry");
23 |
24 | this.Entry = entry;
25 | }
26 |
27 |
28 | ///
29 | /// Gets the associated which can be
30 | /// modified as further information is provided.
31 | ///
32 | protected EditorMenuCommandEntry Entry { get; private set; }
33 |
34 |
35 | ///
36 | /// Sets whether the command entry is visible.
37 | ///
38 | /// Value indicating visibility.
39 | ///
40 | /// Fluid style API to further define the new command entry.
41 | ///
42 | public EditorMenuCommandBinder Visible(bool isVisible)
43 | {
44 | return this.Visible(isVisible
45 | ? EditorMenuInternalUtility.AlwaysTruePredicate
46 | : EditorMenuInternalUtility.AlwaysFalsePredicate
47 | );
48 | }
49 |
50 | ///
51 | /// Sets the predicate that is used to determine whether the
52 | /// command entry is visible.
53 | ///
54 | /// Predicate that returns a value of true for a
55 | /// visible command or a value of false to hide it.
56 | ///
57 | /// Fluid style API to further define the new command entry.
58 | ///
59 | public EditorMenuCommandBinder Visible(Func predicate)
60 | {
61 | this.Entry.IsVisiblePredicate = predicate;
62 | return this;
63 | }
64 |
65 |
66 | ///
67 | /// Sets whether the command entry is enabled.
68 | ///
69 | ///
70 | /// A disabled command is typically presented "greyed out" such that it
71 | /// cannot be actuated.
72 | ///
73 | /// Value indicating whether the command is enabled.
74 | ///
75 | /// Fluid style API to further define the new command entry.
76 | ///
77 | public EditorMenuCommandBinder Enabled(bool isEnabled)
78 | {
79 | return this.Enabled(isEnabled
80 | ? EditorMenuInternalUtility.AlwaysTruePredicate
81 | : EditorMenuInternalUtility.AlwaysFalsePredicate
82 | );
83 | }
84 |
85 | ///
86 | /// Sets the predicate that is used to determine whether the
87 | /// command entry is enabled.
88 | ///
89 | ///
90 | /// A disabled command is typically presented "greyed out" such that it
91 | /// cannot be actuated.
92 | ///
93 | /// Predicate that returns a value of true for an
94 | /// enabled command or a value of false to "grey it out".
95 | ///
96 | /// Fluid style API to further define the new command entry.
97 | ///
98 | public EditorMenuCommandBinder Enabled(Func predicate)
99 | {
100 | this.Entry.IsEnabledPredicate = predicate;
101 | return this;
102 | }
103 |
104 |
105 | ///
106 | /// Sets whether the command entry is checked (ticked /
107 | /// selected / active / on).
108 | ///
109 | ///
110 | /// A check mark is typically presented alongside command entries that have
111 | /// been checked.
112 | ///
113 | /// Value indicating whether the command is checked.
114 | ///
115 | /// Fluid style API to further define the new command entry.
116 | ///
117 | public EditorMenuCommandBinder Checked(bool isChecked)
118 | {
119 | return this.Checked(isChecked
120 | ? EditorMenuInternalUtility.AlwaysTruePredicate
121 | : EditorMenuInternalUtility.AlwaysFalsePredicate
122 | );
123 | }
124 |
125 | ///
126 | /// Sets the predicate that is used to determine whether the
127 | /// command entry is checked.
128 | ///
129 | ///
130 | /// A check mark is typically presented alongside command entries that have
131 | /// been checked.
132 | ///
133 | /// Predicate that returns a value of true for a
134 | /// checked command or a value of false for a regular non-checked command.
135 | ///
136 | /// Fluid style API to further define the new command entry.
137 | ///
138 | public EditorMenuCommandBinder Checked(Func predicate)
139 | {
140 | this.Entry.IsCheckedPredicate = predicate;
141 | return this;
142 | }
143 |
144 |
145 | ///
146 | /// Adds an arbitary parameter to the that can
147 | /// assist implementations by providing them
148 | /// with additional per-entry information.
149 | ///
150 | /// Custom parameter.
151 | ///
152 | /// Fluid style API to further define the new command entry.
153 | ///
154 | ///
155 | /// If is null.
156 | ///
157 | public EditorMenuCommandBinder Parameter(IEditorMenuEntryParameter parameter)
158 | {
159 | ExceptionUtility.CheckArgumentNotNull(parameter, "parameter");
160 |
161 | this.Entry.Parameters.Add(parameter);
162 | return this;
163 | }
164 |
165 |
166 | ///
167 | /// Adds an action to the command entry.
168 | ///
169 | ///
170 | /// Specifying a value of null or simply omitting to specify an
171 | /// action will simply result in the command being
172 | /// disabled ("greyed out").
173 | ///
174 | /// The action to have the command invoke.
175 | ///
176 | /// Fluid style API to further define the new command entry.
177 | ///
178 | ///
179 | /// If is null.
180 | ///
181 | public EditorMenuCommandBinder Action(Action action)
182 | {
183 | ExceptionUtility.CheckArgumentNotNull(action, "action");
184 |
185 | this.Entry.Action += action;
186 | return this;
187 | }
188 |
189 | ///
190 | /// Adds a parameterized action to the command entry.
191 | ///
192 | ///
193 | /// Specifying a value of null or simply omitting to specify an
194 | /// action will simply result in the command being
195 | /// disabled ("greyed out").
196 | ///
197 | /// Type of command parameter.
198 | /// The action to have the command invoke.
199 | /// Parameter for command.
200 | ///
201 | /// Fluid style API to further define the new command entry.
202 | ///
203 | ///
204 | /// If is null.
205 | ///
206 | public EditorMenuCommandBinder Action(Action action, TParam param)
207 | {
208 | ExceptionUtility.CheckArgumentNotNull(action, "action");
209 |
210 | this.Entry.Action += () => action(param);
211 | return this;
212 | }
213 | }
214 | }
215 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuCommandBinder.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5f3fe14dcb073464c87353184ec95379
3 | timeCreated: 1499131236
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuCommandEntry.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Rotorz Limited. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root.
3 |
4 | using System;
5 |
6 | namespace Rotorz.Games.UnityEditorExtensions
7 | {
8 | ///
9 | /// An entry that describes a command.
10 | ///
11 | public class EditorMenuCommandEntry : EditorMenuEntry
12 | {
13 | ///
14 | /// Initializes a new instance of the class.
15 | ///
16 | /// Full path of the command including its path, its label
17 | /// and any shortcut keys.
18 | ///
19 | /// If is null.
20 | ///
21 | ///
22 | /// If is an invalid full command path.
23 | ///
24 | public EditorMenuCommandEntry(string fullPath)
25 | {
26 | ExceptionUtility.CheckExpectedStringArgument(fullPath, "fullPath");
27 | EditorMenuInternalUtility.CheckPathArgument(fullPath, "fullPath");
28 |
29 | int labelStartIndex = fullPath.LastIndexOf('/') + 1;
30 |
31 | this.Label = fullPath.Substring(labelStartIndex);
32 | this.Path = fullPath.Substring(0, labelStartIndex);
33 | this.FullPath = fullPath;
34 |
35 | this.IsEnabledPredicate = EditorMenuInternalUtility.AlwaysTruePredicate;
36 | this.IsCheckedPredicate = EditorMenuInternalUtility.AlwaysFalsePredicate;
37 | }
38 |
39 |
40 | ///
41 | /// Gets the label of the command entry; for instance, "Create Preset...".
42 | ///
43 | public string Label { get; protected set; }
44 |
45 | ///
46 | /// Gets the full path of the command entry; for instance, "Presets/Create Preset...".
47 | ///
48 | public string FullPath { get; protected set; }
49 |
50 |
51 | ///
52 | /// Gets or sets the predicate that is used to determine whether the command entry
53 | /// is enabled or disabled.
54 | ///
55 | public Func IsEnabledPredicate { get; set; }
56 |
57 | ///
58 | /// Gets or sets the predicate that is used to determine whether the command entry
59 | /// is checked or unchecked.
60 | ///
61 | public Func IsCheckedPredicate { get; set; }
62 |
63 |
64 | ///
65 | /// Gets or sets the predicate that is invoked when the command is actuated.
66 | ///
67 | public Action Action { get; set; }
68 |
69 |
70 | ///
71 | /// Evaluates whether or not the command is enabled.
72 | ///
73 | ///
74 | /// In addition to using the provided this
75 | /// method can also incorporate other factors such as being
76 | /// set to a value of null.
77 | ///
78 | ///
79 | /// A value of true if the command is enabled; otherwise, a value of false.
80 | ///
81 | public virtual bool EvaluateIsEnabled()
82 | {
83 | if (this.Action == null) {
84 | return false;
85 | }
86 |
87 | var d = this.IsEnabledPredicate;
88 | return d != null && d.Invoke() == true;
89 | }
90 |
91 | ///
92 | /// Evaluates whether or not the command is checked (ticked / selected / on).
93 | ///
94 | ///
95 | /// In addition to user the provided this
96 | /// method can also incorporate other factors.
97 | ///
98 | ///
99 | /// A value of true if the command is checkedl otherwise, a value of false.
100 | ///
101 | public virtual bool EvaluateIsChecked()
102 | {
103 | var d = this.IsCheckedPredicate;
104 | return d != null && d.Invoke() == true;
105 | }
106 |
107 |
108 | ///
109 | /// Verifies that can be invoked by throwing an exception if
110 | /// there is a problem.
111 | ///
112 | protected virtual void CheckCanInvokeAction()
113 | {
114 | if (!this.EvaluateIsVisible()) {
115 | throw new InvalidOperationException("Cannot invoke command because not visible.");
116 | }
117 | if (!this.EvaluateIsEnabled()) {
118 | throw new InvalidOperationException("Cannot invoke command because not enabled.");
119 | }
120 | }
121 |
122 | ///
123 | /// Invokes the command action.
124 | ///
125 | ///
126 | /// If the command cannot be invoked; for instance, if the command is not visible
127 | /// or is disabled.
128 | ///
129 | public virtual void InvokeAction()
130 | {
131 | this.CheckCanInvokeAction();
132 |
133 | var d = this.Action;
134 | if (d != null) {
135 | d.Invoke();
136 | }
137 | }
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuCommandEntry.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 781127b20ac35e8409fc3e35f3253346
3 | timeCreated: 1499131236
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuEntry.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Rotorz Limited. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 |
7 | namespace Rotorz.Games.UnityEditorExtensions
8 | {
9 | ///
10 | /// Base class for a custom type of entry.
11 | ///
12 | public abstract class EditorMenuEntry : IEditorMenuEntry
13 | {
14 | private List parameters = null;
15 |
16 |
17 | ///
18 | /// Initializes a new instance of the class.
19 | ///
20 | public EditorMenuEntry()
21 | {
22 | this.Path = "";
23 |
24 | this.IsVisiblePredicate = EditorMenuInternalUtility.AlwaysTruePredicate;
25 | }
26 |
27 |
28 | ///
29 | public string Path { get; protected set; }
30 |
31 |
32 | ///
33 | public Func IsVisiblePredicate { get; set; }
34 |
35 |
36 | ///
37 | public ICollection Parameters {
38 | get {
39 | if (this.parameters == null) {
40 | this.parameters = new List();
41 | }
42 | return this.parameters;
43 | }
44 | }
45 |
46 | ///
47 | public bool HasParameters {
48 | get { return this.parameters != null && this.parameters.Count > 0; }
49 | }
50 |
51 |
52 | ///
53 | public virtual bool EvaluateIsVisible()
54 | {
55 | var d = this.IsVisiblePredicate;
56 | if (d == null) {
57 | return false;
58 | }
59 |
60 | return d.Invoke() == true;
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuEntry.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9d9cf34319d65eb49a5b9685e8ee73db
3 | timeCreated: 1499149384
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuInternalUtility.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Rotorz Limited. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root.
3 |
4 | using System;
5 |
6 | namespace Rotorz.Games.UnityEditorExtensions
7 | {
8 | ///
9 | internal static class EditorMenuInternalUtility
10 | {
11 | public static readonly Func AlwaysTruePredicate = () => true;
12 | public static readonly Func AlwaysFalsePredicate = () => false;
13 |
14 |
15 | public static void CheckPathArgument(string path, string argumentName)
16 | {
17 | if (path.StartsWith("/")) {
18 | throw new ArgumentException("Invalid menu path.", argumentName);
19 | }
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuInternalUtility.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 56c51ceae99ce1d4d918fc89578284b4
3 | timeCreated: 1499176698
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuPresenterUtility.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Rotorz Limited. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root.
3 |
4 | using System;
5 |
6 | namespace Rotorz.Games.UnityEditorExtensions
7 | {
8 | ///
9 | /// Utility functions to help with usage.
10 | ///
11 | public static class EditorMenuPresenterUtility
12 | {
13 | ///
14 | /// Gets a default instance.
15 | ///
16 | ///
17 | /// Unless the end-user project has a settings file that overrides the
18 | /// default implementation; this will simply
19 | /// return an instance.
20 | ///
21 | ///
22 | /// A instance.
23 | ///
24 | ///
25 | public static IEditorMenuPresenter GetDefaultPresenterInstance()
26 | {
27 | return (IEditorMenuPresenter)Activator.CreateInstance(EditorMenuSettings.Instance.DefaultPresenterType);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuPresenterUtility.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1abfe1c95f41a0741886f5a4754dfc4c
3 | timeCreated: 1499137498
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuPresenter_GenericMenu.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Rotorz Limited. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root.
3 |
4 | using System.Collections.Generic;
5 | using UnityEditor;
6 | using UnityEngine;
7 |
8 | namespace Rotorz.Games.UnityEditorExtensions
9 | {
10 | ///
11 | /// An that presents an
12 | /// using the Unity API.
13 | ///
14 | ///
15 | /// This is the default implementation of
16 | /// that is used unless an alternative implementation is supplied when constructing
17 | /// an or the project-wide setting
18 | /// is set by the end-user.
19 | /// With this implementation adjacent separators are reduced into a single
20 | /// separator since it looks kinda goofy otherwise.
21 | ///
22 | public class EditorMenuPresenter_GenericMenu : IEditorMenuPresenter
23 | {
24 | private const string UNKNOWN_ENTRY_TYPE_LABEL = "«Unknown Entry Type»";
25 |
26 |
27 | ///
28 | public void ShowAsContext(EditorMenu menu)
29 | {
30 | var genericMenu = this.BuildMenu(menu);
31 | if (genericMenu.GetItemCount() > 0) {
32 | genericMenu.ShowAsContext();
33 | }
34 | }
35 |
36 | ///
37 | public void ShowAsDropdown(Rect position, EditorMenu menu)
38 | {
39 | var genericMenu = this.BuildMenu(menu);
40 | if (genericMenu.GetItemCount() > 0) {
41 | genericMenu.DropDown(position);
42 | }
43 | }
44 |
45 |
46 | ///
47 | /// Builds and returns a for the given .
48 | ///
49 | /// Input menu data structure.
50 | ///
51 | /// A new instance.
52 | ///
53 | public virtual GenericMenu BuildMenu(EditorMenu menu)
54 | {
55 | var genericMenu = new GenericMenu();
56 | var populatedPaths = new HashSet();
57 |
58 | int entryIndex = -1;
59 | foreach (var entry in menu.Entries) {
60 | ++entryIndex;
61 |
62 | if (entry.EvaluateIsVisible() == false) {
63 | continue;
64 | }
65 |
66 | var separatorEntry = entry as EditorMenuSeparatorEntry;
67 | if (separatorEntry != null) {
68 | bool isFirstAtPath = !populatedPaths.Contains(entry.Path);
69 | if (this.CanAddSeparatorEntryToMenu(menu, entryIndex, entry.Path, isFirstAtPath)) {
70 | this.AddSeparatorEntryToMenu(genericMenu, separatorEntry);
71 | }
72 | continue;
73 | }
74 |
75 | populatedPaths.Add(entry.Path);
76 |
77 | this.AddEntryToMenu(genericMenu, entry);
78 | }
79 |
80 | return genericMenu;
81 | }
82 |
83 | ///
84 | /// Adds an entry to the .
85 | ///
86 | /// Output menu.
87 | /// Menu entry.
88 | protected virtual void AddEntryToMenu(GenericMenu genericMenu, IEditorMenuEntry entry)
89 | {
90 | var commandEntry = entry as EditorMenuCommandEntry;
91 | if (commandEntry != null) {
92 | this.AddCommandEntryToMenu(genericMenu, commandEntry);
93 | return;
94 | }
95 |
96 | this.AddUnknownEntryToMenu(genericMenu, entry);
97 | }
98 |
99 |
100 | ///
101 | /// Adds a command entry to the .
102 | ///
103 | ///
104 | /// Can be overriden to provide special
105 | /// implementations:
106 | ///
119 | ///
120 | /// Input menu data structure.
121 | /// Menu entry that is currently being added.
122 | protected virtual void AddCommandEntryToMenu(GenericMenu genericMenu, EditorMenuCommandEntry entry)
123 | {
124 | var content = new GUIContent(entry.FullPath);
125 | if (entry.EvaluateIsEnabled()) {
126 | genericMenu.AddItem(content, entry.EvaluateIsChecked(), () => entry.InvokeAction());
127 | }
128 | else {
129 | genericMenu.AddDisabledItem(content);
130 | }
131 | }
132 |
133 |
134 | ///
135 | /// Finds the next visible menu entry at the given path.
136 | ///
137 | /// Input menu data structure.
138 | /// Path of the entry.
139 | /// Zero-based index of the starting entry (excluded).
140 | ///
141 | /// The next visible instance when found;
142 | /// otherwise, a value of null.
143 | ///
144 | protected static IEditorMenuEntry FindNextVisibleMenuEntryAtPath(EditorMenu menu, string path, int fromEntryIndex)
145 | {
146 | for (int entryIndex = fromEntryIndex + 1; entryIndex < menu.Entries.Count; ++entryIndex) {
147 | var entry = menu.Entries[entryIndex];
148 | if (entry.Path == path && entry.EvaluateIsVisible()) {
149 | return entry;
150 | }
151 | }
152 | return null;
153 | }
154 |
155 | ///
156 | /// Determines whether a separator can be added to the .
157 | ///
158 | /// Input menu data structure.
159 | /// Zero-based index of the separator entry.
160 | /// Path of the separator entry.
161 | /// Indicates if the separator would be the first
162 | /// output entry at that path.
163 | ///
164 | /// A value of true if the separator entry can be added to the output
165 | /// ; else, a value of false.
166 | ///
167 | protected virtual bool CanAddSeparatorEntryToMenu(EditorMenu menu, int entryIndex, string path, bool isFirstAtPath)
168 | {
169 | // Don't output separator at the start of a path... it just doesn't look good!
170 | if (isFirstAtPath) {
171 | return false;
172 | }
173 |
174 | var nextEntryAtPath = FindNextVisibleMenuEntryAtPath(menu, path, entryIndex);
175 |
176 | // Don't output separator if no entry follows in same menu path.
177 | if (nextEntryAtPath == null) {
178 | return false;
179 | }
180 | // Don't output separator if next entry is also separator... it doesn't look good!
181 | if (nextEntryAtPath is EditorMenuSeparatorEntry) {
182 | return false;
183 | }
184 |
185 | return true;
186 | }
187 |
188 | ///
189 | /// Adds a separator entry to the .
190 | ///
191 | /// Input menu data structure.
192 | /// Menu entry that is currently being added.
193 | protected virtual void AddSeparatorEntryToMenu(GenericMenu genericMenu, EditorMenuSeparatorEntry entry)
194 | {
195 | genericMenu.AddSeparator(entry.Path);
196 | }
197 |
198 |
199 | ///
200 | /// Adds a placeholder for an unknown type of entry to the .
201 | ///
202 | /// Input menu data structure.
203 | /// Menu entry that is currently being added.
204 | protected virtual void AddUnknownEntryToMenu(GenericMenu genericMenu, IEditorMenuEntry entry)
205 | {
206 | string label = UNKNOWN_ENTRY_TYPE_LABEL;
207 |
208 | if (entry.Path != "") {
209 | label = entry.Path + "/" + label;
210 | }
211 |
212 | genericMenu.AddDisabledItem(new GUIContent(label));
213 | }
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuPresenter_GenericMenu.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7e3d612c2e9f6024ea0de97731c1a387
3 | timeCreated: 1499131236
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuSeparatorBinder.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Rotorz Limited. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root.
3 |
4 | namespace Rotorz.Games.UnityEditorExtensions
5 | {
6 | ///
7 | /// Binds additional information to an separator entry.
8 | ///
9 | public class EditorMenuSeparatorBinder
10 | {
11 | ///
12 | /// Initializes a new instance of the class.
13 | ///
14 | /// The associated separator entry.
15 | ///
16 | /// If is null.
17 | ///
18 | public EditorMenuSeparatorBinder(EditorMenuSeparatorEntry entry)
19 | {
20 | ExceptionUtility.CheckArgumentNotNull(entry, "entry");
21 |
22 | this.Entry = entry;
23 | }
24 |
25 |
26 | ///
27 | /// Gets the associated which can be
28 | /// modified as further information is provided.
29 | ///
30 | protected EditorMenuSeparatorEntry Entry { get; private set; }
31 |
32 |
33 | ///
34 | /// Adds an arbitary parameter to the that can
35 | /// assist implementations by providing them
36 | /// with additional per-entry information.
37 | ///
38 | /// Custom parameter.
39 | ///
40 | /// Fluid style API to further define the new command entry.
41 | ///
42 | ///
43 | /// If is null.
44 | ///
45 | public EditorMenuSeparatorBinder Parameter(IEditorMenuEntryParameter parameter)
46 | {
47 | ExceptionUtility.CheckArgumentNotNull(parameter, "parameter");
48 |
49 | this.Entry.Parameters.Add(parameter);
50 | return this;
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuSeparatorBinder.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e11b305b6663a7440a2f0e6536f2da7f
3 | timeCreated: 1499131236
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuSeparatorEntry.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Rotorz Limited. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root.
3 |
4 | namespace Rotorz.Games.UnityEditorExtensions
5 | {
6 | ///
7 | /// An entry that describes a separator.
8 | ///
9 | public class EditorMenuSeparatorEntry : EditorMenuEntry
10 | {
11 | ///
12 | /// Initializes a new instance of the class.
13 | ///
14 | /// Path of the separator.
15 | ///
16 | /// If is null.
17 | ///
18 | ///
19 | /// If is an invalid full command path.
20 | ///
21 | public EditorMenuSeparatorEntry(string path)
22 | {
23 | ExceptionUtility.CheckArgumentNotNull(path, "path");
24 | EditorMenuInternalUtility.CheckPathArgument(path, "path");
25 |
26 | this.Path = path;
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuSeparatorEntry.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 87d0e047c006d6e47b8f6d610beee6d1
3 | timeCreated: 1499131236
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuSettings.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Rotorz Limited. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root.
3 |
4 | using Rotorz.Games.EditorExtensions;
5 | using System;
6 | using System.IO;
7 | using UnityEngine;
8 |
9 | namespace Rotorz.Games.UnityEditorExtensions
10 | {
11 | ///
12 | /// Project-wide settings for the "@rotorz/unity3d-editor-menu" package.
13 | ///
14 | ///
15 | /// The default implementation type can be
16 | /// overridden by creating a settings file at the path "{Project}/Assets/Plugins/PackageData/@rotorz/unity3d-editor-menu/EditorMenuSettings.json"
17 | /// and then specifying the type as follows:
18 | ///
23 | ///
24 | public sealed class EditorMenuSettings
25 | {
26 | private static EditorMenuSettings s_Instance;
27 |
28 |
29 | ///
30 | /// Gets the instance for the end-user's project.
31 | ///
32 | public static EditorMenuSettings Instance {
33 | get {
34 | if (s_Instance == null) {
35 | s_Instance = LoadSettings();
36 | }
37 | return s_Instance;
38 | }
39 | }
40 |
41 |
42 | private static EditorMenuSettings LoadSettings()
43 | {
44 | EditorMenuSettings settings = new EditorMenuSettings();
45 |
46 | string editorMenuSettingsFilePath = PackageUtility.ResolveDataPathAbsolute("@rotorz/unity3d-editor-menu", null, "EditorMenuSettings.json");
47 | if (File.Exists(editorMenuSettingsFilePath)) {
48 | var jsonRaw = File.ReadAllText(editorMenuSettingsFilePath);
49 | var data = JsonUtility.FromJson(jsonRaw);
50 | settings.FromSerializable(data);
51 | }
52 |
53 | return settings;
54 | }
55 |
56 |
57 | private Type defaultPresenterType;
58 |
59 |
60 | ///
61 | /// Initializes a new instance of the class.
62 | ///
63 | public EditorMenuSettings()
64 | {
65 | this.defaultPresenterType = this.FallbackDefaultPresenterType;
66 | }
67 |
68 |
69 | ///
70 | /// Gets the fallback implementation type.
71 | ///
72 | public Type FallbackDefaultPresenterType {
73 | get { return typeof(EditorMenuPresenter_GenericMenu); }
74 | }
75 |
76 | ///
77 | /// Gets the default implementation type.
78 | ///
79 | public Type DefaultPresenterType {
80 | get { return this.defaultPresenterType; }
81 | private set {
82 | if (value == null) {
83 | throw new ArgumentNullException("value");
84 | }
85 | if (!typeof(IEditorMenuPresenter).IsAssignableFrom(value)) {
86 | throw new ArgumentException("Does not implement 'IEditorMenuPresenter' interface.");
87 | }
88 |
89 | this.defaultPresenterType = value;
90 | }
91 | }
92 |
93 |
94 |
95 | private void FromSerializable(JsonData data)
96 | {
97 | if (!string.IsNullOrEmpty(data.DefaultPresenterTypeName)) {
98 | var type = Type.GetType(data.DefaultPresenterTypeName, throwOnError: false);
99 | if (type != null && typeof(IEditorMenuPresenter).IsAssignableFrom(type)) {
100 | this.defaultPresenterType = type;
101 | return;
102 | }
103 | }
104 |
105 | this.defaultPresenterType = this.FallbackDefaultPresenterType;
106 | }
107 |
108 |
109 |
110 | [Serializable]
111 | private sealed class JsonData
112 | {
113 | public string DefaultPresenterTypeName;
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/assets/Editor/EditorMenuSettings.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0a6075af90352f34c893cc8c92b4ec60
3 | timeCreated: 1499155054
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/assets/Editor/IEditorMenuEntry.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Rotorz Limited. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 |
7 | namespace Rotorz.Games.UnityEditorExtensions
8 | {
9 | ///
10 | /// The interface of an entry.
11 | ///
12 | public interface IEditorMenuEntry
13 | {
14 | ///
15 | /// Gets the path of the menu entry; for instance, the menu item Sub-Menu > Abc
16 | /// would have a path of "Sub-Menu".
17 | ///
18 | string Path { get; }
19 |
20 |
21 | ///
22 | /// Gets or sets a predicate that determines whether the entry is visible.
23 | ///
24 | Func IsVisiblePredicate { get; set; }
25 |
26 |
27 | ///
28 | /// Gets an editable collection of custom parameters that can assist
29 | /// implementations by allowing additional information to plugged into entries.
30 | ///
31 | ///
32 | ICollection Parameters { get; }
33 |
34 | ///
35 | /// Gets a value indicating whether the has any
36 | /// parameters. This property should be tested before accessing .
37 | ///
38 | ///
39 | bool HasParameters { get; }
40 |
41 |
42 | ///
43 | /// Evaluates whether the entry is visible.
44 | ///
45 | ///
46 | /// A value of true if the entry is visible; otherwise, a value of false.
47 | ///
48 | bool EvaluateIsVisible();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/assets/Editor/IEditorMenuEntry.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4013033b12e28914fa3761c8c7481792
3 | timeCreated: 1499131235
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/assets/Editor/IEditorMenuEntryParameter.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Rotorz Limited. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root.
3 |
4 | namespace Rotorz.Games.UnityEditorExtensions
5 | {
6 | ///
7 | /// The interface of a custom parameter.
8 | ///
9 | public interface IEditorMenuEntryParameter
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/assets/Editor/IEditorMenuEntryParameter.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 417ff7d17ca1c5043bf06a817e180b33
3 | timeCreated: 1499189102
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/assets/Editor/IEditorMenuPresenter.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Rotorz Limited. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root.
3 |
4 | using UnityEngine;
5 |
6 | namespace Rotorz.Games.UnityEditorExtensions
7 | {
8 | ///
9 | /// The interface of an object that presents an data
10 | /// structure to the end-user.
11 | ///
12 | ///
13 | ///
14 | public interface IEditorMenuPresenter
15 | {
16 | ///
17 | /// Shows the as a context menu.
18 | ///
19 | /// The editor menu.
20 | void ShowAsContext(EditorMenu menu);
21 |
22 | ///
23 | /// Shows the as a drop-down from a GUI control.
24 | ///
25 | /// Absolute position of GUI drop-down control.
26 | /// The editor menu.
27 | void ShowAsDropdown(Rect position, EditorMenu menu);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/assets/Editor/IEditorMenuPresenter.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ea20543eca4483743be9bd24364ce73f
3 | timeCreated: 1499131236
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/assets/Editor/_assembly.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rotorz.unity3d-editor-menu.editor",
3 | "references": [
4 | "rotorz.dotnet-exception-utils",
5 | "rotorz.unity3d-package-utils.editor"
6 | ],
7 | "optionalUnityReferences": [],
8 | "includePlatforms": [
9 | "Editor"
10 | ],
11 | "excludePlatforms": [],
12 | "allowUnsafeCode": false
13 | }
14 |
--------------------------------------------------------------------------------
/assets/Editor/_assembly.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5734e33e62533fa4cb5557c00cdba331
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) Rotorz Limited. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root.
3 |
4 | throw new Error("This package is not supposed to be used directly.");
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@rotorz/unity3d-editor-menu",
3 | "version": "1.0.2",
4 | "description": "Fluent style API for constructing custom editor menus presented using `GenericMenu` by default although alternative presentation can be configured for project.",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/rotorz/unity3d-editor-menu"
12 | },
13 | "author": "Rotorz Limited",
14 | "license": "MIT",
15 | "keywords": [
16 | "unity3d",
17 | "unity3d-package"
18 | ],
19 | "dependencies": {
20 | "@rotorz/dotnet-exception-utils": "github:rotorz/dotnet-exception-utils#semver:^1.0.3",
21 | "@rotorz/unity3d-package-utils": "github:rotorz/unity3d-package-utils#semver:^1.0.1"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------