Nested Variables in Unity Inspector - unity3d

I was wondering if anyone knew how to make nested variables inside the unity inspector with a script, kind of like this:

Doing so does require knowledge of UnityEditor and not only (as you say ... nested variables) can give you many other control options in the inspector. To do this, I created a sample code called MenuManager. As you can see this code:
public class MenuManager : MonoBehaviour
{
public bool variable1;
public float nestedVariable;
//...
}
Unity itself does not provide any attributes such as [Range] or [Header] for such a request, and to do this you need to define a CustomEditor for the class but Before to do that, you need to create a folder similar to the photo with name of Editor and put it in the Assets folder. Then create another script with name of MenuEditor (for example here ..) and put it in a Editor folder.
Now open the MenuEditor code. Inherit it from the Editor class. Editor class is base class for editing inspector and more. It will give you many override methods with access to the features inside the unity editor. and make sure it has two Attributes Custom Editor as well as CanEditMultipleObjects.
[CustomEditor(typeof(MenuManager))]
[CanEditMultipleObjects]
public class MenuEditor : Editor
{
//..
}
This code gives you access to the MenuManager script. According to the following code, I coded a Nested variable to the first one.
[CustomEditor(typeof(MenuManager))]
[CanEditMultipleObjects]
public class MenuEditor : Editor
{
public override void OnInspectorGUI()
{
var myMenu = target as MenuManager; // target is script reference that we want to manipulate it
myMenu.variable1 = EditorGUILayout.Toggle("Variable 1", myMenu.variable1); // show first variable on inspector
GUI.enabled = myMenu.variable1; // access to second variable depend of first
myMenu.nestedVariable =EditorGUILayout.Toggle("Nested Variable", myMenu.nestedVariable);
GUI.enabled = true;
}
}
After finishing the work, you can access the nested variable only by setting first one to true.
Remember after doing this you can access many other features just inside MenuEditor class but if you find this difficult, I suggest you use Odin Inspecter. I hope you have reached your answer. comment under answer if you need more information.

Related

In Unity, how to delete a component via script when deleting another component via the editor?

Context : I'm editing a prefab, I have two components on it, both are custom scripts.
When editing a prefab, I want to remove the component Container Sync at the same time that I remove the component Container Descriptor in the editor by right clicking it and clicking on Remove Component. See the picture below.
In ContainerDescriptor, I have a reference towards the ContainerSync script.
public class ContainerDescriptor : MonoBehaviour
{
public ContainerSync containerSync;
}
I tried to use the method OnDestroy() of the ContainerDescriptor script, but it's not called when removing ContainerDescriptor that way.
On this thread there is a solution at least for if you remove that component via the context menu like you do.
Using [ExecuteAlways] the event message calls that usually are only called in PlayMode do also get called in Edit and in Prefab mode!
You can do something like e.g.
[ExecuteAlways]
public class ContainerDescriptor : MonoBehaviour
{
public ContainerSync containerSync;
#if UNITY_EDITOR
private void OnDestroy ()
{
if(containerSync)
{
if(Application.isPlaying)
Destroy(containerSync);
else
DestroyImmediate (containerSync);
}
}
#endif
}
Note though that specifically for prefabs this might still fail since afaik neither Destroy nor DestroyImmediate can be used inside of prefabs (see here)

Proper way to do dialogs using Prism and UWP

I'm not sure if I'm thinking about this in the correct way. I have a list of objects, and I would like the user to be able to edit and view the properties of a specified object. My initial thought is great, I'll pop up a dialog that has textboxes and let the user edit to their heart's content until they press either Ok or Cancel.
I'm on UWP, and using Prism for all of my MVVM needs. It's taken me a while, but I understand creating Views and their associated ViewModels, commands, etc. So far, I think I've done a good job keeping the view logic and business logic separated.
I've searched, but haven't found how to show a dialog in a way that follows MVVM principles. The two things that seem to be coming up the most are to use Interaction requests (which don't appear to exist using Prism on UWP), and creating a custom Content Dialog and showing it by calling ShowAsync in a method in the parent view's associated ViewModel (which seems to be counter to MVVM principles).
So, how do I either show a dialog that is defined using XAML and has an associated ViewModel (preferable since it is similar to what I'm familiar with), or another way I can tackle this problem?
Using MVVM the proper place for opening a dialog is in the ViewModel.
Usually I do something like this in your scenario:
Create an interface for showing dialogs:
public interface IWindowService
{
void OpenViewModelInWindow(ViewModelBase vm, string title, bool resizeable = true);
void CloseViewModelInWindow(ViewModelBase vm);
}
Implement this interface in UI layer:
public class WindowService : IWindowService
{
private List<Window> _windows = new List<Window>();
public void OpenViewModelInWindow(ViewModelBase vm, string title, bool resizeable = true)
{
var window = new Window
{
Title = title,
Content = vm,
Owner = Application.Current.MainWindow,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
ShowInTaskbar = false,
SizeToContent = SizeToContent.WidthAndHeight,
ResizeMode = resizeable ? ResizeMode.CanResize : ResizeMode.NoResize
};
_windows.Add(window);
window.ShowDialog();
}
public void CloseViewModelInWindow(ViewModelBase vm)
{
_windows.Single(w => w.Content == vm).Close();
}
}
In your App.xaml you need to define DataTemplates so that when you set the Content property of the window the corresponding View created in the window.
<DataTemplate DataType="{x:Type viewModel:AViewModel}">
<views:AUserControl />
</DataTemplate>
Then you can use the IWindowService from the ViewModel, you should inject it by constructor injection.
This way you are not referencing framework specific classes directly from the ViewModel. ViewModel has a reference only to an IWindowService. This has a benefit also when you want ot write unit test for a viewmodel. You can mock this service so that when the unit test is running it should not open a dialog.

Form inheritance should be abstract

Here my code
GeneralLesson.cs: it's just a .cs file, no .Designer.cs or .resx file
public /*abstract*/ class GeneralLesson : Form
{
public GeneralLesson()
{
this.StartPosition = SS.FrmStartPos;//If I want to change it later, I just change it here and all the children will get the change
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
if (e.CloseReason == CloseReason.WindowsShutDown) return;
SS.LearningDay = 0; //SS is my static class that hold the static variables.
SS.FrmMain.Show();
}
}
SentLesson.cs: This is actually a windows form, with .Designer.cs and .resx file
public partial class _Sent_Lesson : GeneralLesson
{
public _Sent_Lesson()
{
InitializeComponent();
richTextBox1.Text = "under construction";
}
}
So it actually serves my purpose well. my SentLesson window inherits the constructor and OnFormClosing from GeneralLesson. But the problem is I can't design my SentLesson window any more, it shows as the picture below:
Maybe I do it wrong. But I don't want to create GeneralLesson as a Window because I don't design any control on it, I just want to override some function like OnFormClosing or the Constructor. Is there any way I can do this without making GeneralLesson as a Window.
Thanks for reading.
I finally got the solution. Even though the abstract parent form still works logically, but the children form can't be designed any further with Visual Studio designer. So I have to inherit forms the Visual Studio way.
As you can see, Visual Studio provides us Inherited Form to create Children form. So I create GeneralLesson.cs as Windows Form, and SentLesson.cs as Inherited Form. So SentLesson inherits constructor and OnFormClosing from GeneralLesson and the designer of SentLesson no longer shows error.
If you want the Children form can access some controls from the Parent form, say Parent's "Button A". Just set the Parent's "Button A" 's Modifiers in properties window from Private to Protected. Then you can do anything with Button A in the Children form.
Thank for your reading.

How to add documentation to an exposed property?

I'd like to add documentation to my custom Components. This documentation should be visible in the editor.
It seems already available for standard library components :
However, it doesn't work for my code:
using UnityEngine;
using System.Collections;
public class MainPlayer : MonoBehaviour {
// I would like to see this comment in the editor too!
public string myName;
// Use this for initialization
void Start () {
Debug.Log("I am alive and my name is " + myName);
}
// Update is called once per frame
void Update () {
}
}
How can I do that?
All you need to do is decorate the field with Tooltip attribute.
Example:
[Tooltip("These are not droids you are looking for...")]
public string myName;
Also, if I were you, I'd go [Header()] attribute way as it will always show a bolded header above field in Inspector instead of only showing information on hover.
Docs for Header and other attributes:
http://docs.unity3d.com/ScriptReference/HeaderAttribute.html
I'm afraid there is no direct link to the whole section, so you need to navigate in nav on the left to section called Attributes which should be active from start.

Eclipse plugin RCP question

I am creating new Eclipse RCP application. I used "Hello RCP" as template project to create a new project. It works fine. Then I tried adding new menu. I used two extension points "org.eclipse.ui.commands" and "org.eclipse.ui.menu". I created handler class and also defined the menucontribution location uri(). But my menu is not showing up. I strongly suspect my location uri is wrong. But I dont know how to correct it. I have pasted my plugin.xml contents here. Let me know if anyone has a solution. I am following the steps given here http://zenit.senecac.on.ca/wiki/index.php/Add_Menu_to_RCP_Application
You can use ApplicationActionbarAdvisor class to define menus and commands for toolbar as well as menubar.
Firstly you have to declare the commands you want to add in your app like below:
private IWorkbenchAction newAction
Then with the help of ActionFactory class, you have to define the commands in makeActions() method like below:
newAction = ActionFactory.NEW_WIZARD_DROP_DOWN.create(window);
register(newAction);
newAction.setText("New");
Now, after declaration you have to add the commands in menus by using fillMenuBar(IMenuManager menuBar) method :
MenuManager filemenu = new MenuManager("&File", "file");
filemenu.add(newAction);
and if you want to add this command in toolbar, then you have to use following method:
protected void fillCoolBar(ICoolBarManager coolBar) {
IToolBarManager toolbar = new ToolBarManager(coolBar.getStyle());
coolBar.add(toolbar);
toolbar.add(newAction);
Sometimes, you have to use IContributionIem class for declaring commands because all the commands are not in IWorkbenchAction class.
Note: If you are using iContributionItem class then declaration and defination code will be replaced as follws:
IContributionItem show_view;
show_view = ContributionItemFactory.VIEWS_SHORTLIST.create(window);
and rest will be same.