Menus in Unity3D, using UnityScript and subclasses - menu

I am trying to set up a generic class that deals with menus within Unity3D.
The following code I intend to attach to an empty game object
import System.Collections.Generic;
#pragma strict
public enum MenuType { loadSceneOnMouseDown, enableGameObject, changeValue };
public class MenuClass extends System.Object
{
public var menuObject : GameObject;
public var menuType : MenuType;
}
public var menuItems = List.<MenuClass>();
This results in the following within the editor:
I want each menu type to have its own parameter, so in this example I want the "loadSceneOnMouseDown" to have another public variable as a string defining the name of the scene to be loaded, once loadSceneOnMouseDown is selected from the enum. Whereas I want the "enableGameObject" Type to have a gameobject as a public var. However I dont want both to appear in both fields. For example I could make it like this:
public class MenuClass extends System.Object
{
public var menuObject : GameObject;
public var menuType : MenuType;
public var sceneName : String
public var targetObject : GameObject
}
But that would make it come under each element of the list. I considered doing a further subclass to resolve this, but then with the line "public var menuItems = List.();" that wouldnt work. (or would it? :D)
Apologies if I have been unclear, trying my best here but Im finding it difficult. Theres probably a very simple solution, or im going about thins entirely the wrong way. Any help with this problem would be very much appreciated!
Thanks!

Unity's serialization doesn't really support polymorphism. A list of type MenuClass can technically contain subclassed objects at runtime, but as far as serializing the list Unity is going to assume they are all objects of the base type.
It's a bit inconvenient, sometimes.
There are a few popular workarounds:
Leave all of the possible fields serialized MenuClass, then write a custom inspector which exposes only the relevant fields while you're working. In simple cases like yours, this is often the quickest solution.
Serialize some basic data fields, then use that data to reconstruct your more elaborate objects at runtime. For example, Unity can't serialize a Dictionary, but it can serialize two lists which you stitch back together. Handy, still simple, has some limits.
Build in some custom serialization library, and go nuts with it. Popular choices include JsonFx, MiniJson, Protobufs, and C#'s built-in XML serialization. Lots of work, but very powerful.
Like I said, in your case I'd recommend starting with the custom inspector, if you think that'll cover your needs.
Aside from code that's in most common tutorials, you could switch based on that control value, then call functions like EditorGUILayout.FloatField(), EditorGUILayout.ObjectField() and their cousins to get data.
Custom editor scripting is often overlooked, but it's one of the most powerful features available to Unity developers.

Related

Is there a way to prevent creation of a data class item in C# WindowsForms UserControl

If I create a UserControl, to create and edit an instance of a data class e.g. Person in C# WindowsForms (call it PersonControl), the framework automatically adds an instance of Person in PersonControl.Designer with some default values for the properties and fills the item controls with those values. This behavior has a number of side effects which I would like to avoid.
Question: is there a defined way to prevent creation of a data class instance in UserControl.Designer?
I think you missing the DesignerSerializationVisibility attribute. If you have a custom control every public property that you add will automatically be serialized. You can use this attribute to disable the serialization for a property. I also recommend to add the Browsable attribute which will hide the property from the designer. If you want more control over serialization, like you want to serialize only when another property is set to true you can create a special named method which will then called by the designer Defining Default Values with the ShouldSerialize and Reset Methods. There was a MSDN Magazine where a lots of winform learning resource was relased there are some gems about winform internal working. If you interested in you can quickly look trhrough it. My favorite is. Create And Host Custom Designers With The .NET Framework 2.0
Sorry but i didn't mention another attribute DefaultValue You can use the attribute the following way.
public partial class PersonEditControl : UserControl
{
[DefaultValue(null)] // This attribute tells the designer if the property value matches what we specified in the attribute(null) it should not store the property value.
public PersonData? Person { get; set; }
public PersonEditControl()
{
InitializeComponent();
}
}

How to avoid constructor to be call twice when a page is define twice in a page

I am creating a winRt app. In which I am having a Home.xaml page which having a another page called Market.xaml. So for snapped mode the same code is repeated.
Now my itemListView (used for snapped) and itemGridView (for full view) both have this page (Market)
<views:Market x:Name="viewMarket"/>
And the constructor of this page is called twice which I not want.
So do I use some flag kind of thing or some better approach is there.
Thanks
So, let's talk about this:
XAML is basically a varying syntax to C#. So, when XAML references a control like your views:Market with <Views:Market />, you are actually putting in something like new Views.Market() in both places. Basically, invoking the class twice. Should the constructor not fire twice, the time-space continuum would split in half. Dogs and cats living together, the whole 9 yards.
But, more fundamental here, what is the purpose of the constructor in C#, or in a XAML class? Is to do expensive things that you would not want to repeat? No. The reason for this is because the completion of the constructor is necessary before the UI thread is released and allowed to render the control. The resulting effect is a UI hang.
Moreover, the C# constructor is a synchronous method. It cannot properly invoke or hold asynchronous operations. This means long-running or expensive tasks that should be invoked immediately, should not be invoked in the constructor because it would also require them to be synchronous and UI-blocking. It is because of these last two points I suspect your constructor is being misused.
The solution is in the XAML framework. The XAML Page pipeline includes the constructor (since it is a C# class and they all have it) but it also includes a Loaded event. In many cases, the hard work necessary to fill page controls is in the Loaded handler. This allows the page to render properly, then starts the long-running action that will ultimately and asynchronously update control content.
In WinRT, the Page pipeline also includes an OnNavigatedTo() virtual method in the base that you can override to the same effect. In the override you can include the hard work of talking to a service, deserializing from a file, or whatever you need to make your UI work. Both the Loaded event and the override can be asynchronous, and neither prevent rendering by freezing the constructor.
But, there's another thing to consider since we're in C# and that the rather common pattern called singleton that allows for us to reference a type in two different contexts but without creating a brand new class. This is accomplished by making the class constructor private, but exposing a public property usually called Instance that returns a single, shared instances in some static place.
That might solve your problem already. Then again, none of that is probably what you need. Assuming you already know all that, the quick answer is you can't prevent a constructor because a constructor is necessary to create a new instantiation of any class, including a XAML view. Instead, whatever you are trying to prevent being double might need to be a combination of the discussions above. An offloaded method, and a static reference to prevent duplicate efforts.
Something like this:
public class Market : UserControl
{
public Market()
{
Loaded += Market_Loaded;
}
static bool AlreadyLoaded = false;
void Market_Loaded(object sender, RoutedEventArgs e)
{
if (AlreadyLoaded)
return;
AlreadyLoaded = true;
// TODO: your work
}
}
But that might not do it for you because the static variable is scoped too large. Instead, you can control if it does the big operation with a dependency property you add to your control. With a boolean dependency property set to false, the second control knows not to do something. With it set to true, the first knows to go ahead. And, so on. This prevents all future use of the view or user control in your app from thinking it should not run because of the static property in the above solution. Then again, that might be perfect.
Best of luck!

JavaFX access controller's variables from Scene Builder

If I declare something like
#FXML
private final static double PREF_SPACING = 10d;
or
#FXML
private Insets insets = new Insets(10d);
in the controller class,
is there a way to use their values in Scene Builder?
When I want to change the value, I want to change
it only once, in the controller class.
PRELIMINARY ANSWER
I haven't yet tried all of the techniques below, but it seems to be the way you would do it from reading the documentation. If I get some time, I'll try it out later and update this answer with results (or somebody else can do this and post a new answer or edit this one to create a definitive answer). I just wanted to publish something now to point you in what I believe to be the right direction.
If the below is not what you are looking for, add a few more specifics to your questions to fully describe what you want.
Don't using the #FXML annotation here. #FXML is for injecting values from the markup into the controller, not the other way around.
For your first example which is a constant, let's say your controller class is:
class MyControllerType {
public final static double PREF_SPACING = 10d;
}
Then in your fxml, reference the constant:
<?import MyControllerType?>
...
<VBox>
<spacing><MyControllerType fx:constant="PREF_SPACING"/></spacing>
</VBox>
For your second sample which is not a constant or a part of the SceneGraph, you can use an fx:define element to instantiate an instance of the class. Note that you can't directly instantiate an Insets class from FXML as it has no builder class nor zero length constructor. So what you might be able to do is create another placeholder class for the information and instantiate a reference to that in your FXML (or you can create a Builder that FXML can use to instantiate the Insets).
class InsetsHolder {
private Insets insets = new Insets(10d);
public Insets getInsets();
}
<?import InsetsHolder?>
<fx:define>
<InsetsHolder fx:id="i"/>
</fx:define>
<VBox>
<Button text="Click Me!" VBox.margin="$i.insets"/>
</VBox>
SceneBuilder should be able to read fxml files which use the fx:define and fx:constant notation, as well as (possibly) make use of the reference expression $i.insets. SceneBuilder might not have any UI to allow you to edit the values from within the SceneBuilder application, so you will probably need to hand edit the fxml file portions related to the fx:define and fx:constant elements if you wish to make use of these structures.
There is an executable example of using an fx:define element in this mailing list post on designing resolution independent units in FXML.
In general, I think I'd be a bit cautious of maintaining these kind of dependencies between fxml and java code. It may be more prudent to do more of this kind of stuff in plain Java code within the context of the controller initialize method as scottb suggests.
The #FXML annotation enables the JavaFX objects whose names you defined (fx:id) to have their references reflectively injected into nonpublic fields in the controller object as the scene graph is loaded from the fxml markup.
To the best of my knowledge, this is a one way operation. There is no provision for having named static class variables in the controller object injected into the scene graph during loading.
You can accomplish something very similar to what you are requesting by defining the values that you want set as class variables in your controller object's class, and then setting the appropriate object properties programmatically (rather than in markup) in the initialize() method of your controller object.
The initialize() method is called (if it is present) after the loading of the scene graph is complete (so all the GUI objects will have been instantiated) but before control has returned to your application's invoking code.

Loading Data-Backed ComboBox with Simple Types

I have a RPC method that returns a List of Strings. I want to create a ComboBox with a store that will load the values through a RpcProxy, but I can't find an example that doesn't use some sort of ModelData class.
I would prefer not to have to create a simple Bean with only one property (the string) and then have to convert the List one item at a time.
My ideal would be to create something like this:
RpcProxy<List<String>> proxy = new RpcProxy<List<String>>()...
Any suggestions?
Unfortunately, with GXT 2.2.5, you can't get around not using ModelData.
The class definition for ComboBox says it all:
public class ComboBox<D extends ModelData> extends TriggerField<D> implements SelectionProvider<D> {
...
protected ListStore<D> store;
...
So, at this point your biggest concern is keeping your code clean. If you have to make a specialized ModelData derived class, you could subclass ComboBox and keep a nested class definition for your wrapper object.
If you're not tied to using GXT 2.2.5, I would update to GXT 3.0.x and GWT 2.5.0. GXT 3 moved away from using ModelData. Now, everything accepts bean-like objects.

Is is possible to make helpers private in WebMatrix?

I've created my own data grid helper in WebMatrix. The paging and sorting links are helpers too, but I don't really want to expose those helpers publicly to the rest of the app.
For example:
#helper Pager(IEnumerable<dynamic> gridData,
int totalRows, int currentPage, int rowsPerPage)
{
// Helper code is here.
}
Is there any way to make a helper private? Would that be a bad practice, anyway? I know there are private functions, but helpers are handy from a syntactic standpoint.
Using the #helper syntax means that your helper method will automatically get compiled to a public static method. So the answer to your question is no.
One way is to create a library and reference it in your web.config or .cshtml file.
helpers bascially output the html you need/want, essentially htmlhelpers return an html string. You would have to move all your code out into the library and its separate from your main app.

Resources