Unity UI : How to reenable a dropdown after its panel was deactivated and then reactivated? - unity3d

I am new to Unity, so this is probably a dumb question but here goes:
I have a Unity app; it has several scenes. One of those scenes has a Canvas upon which there are several overlapping Panels. On one of the Panels (PanelA), there is a Dropdown. When the app first runs PanelA is active and on top by default and the dropdown works fine. But after I deactivate PanelA with a C# call to
panelA.SetActive(false);// hides the panel
and then later reactivate it like so:
panelA.SetActive(true); // redisplays the panel
The dropdown no longer displays its list of option when clicked on. The dropdown is still there and still shows its first option "None" and when clicked on the drop-down changes color to indicate that it was touched, but the dropdown does not drop down its list of options.
What am I missing? Why doesn't the dropdown show the list of options?
Thanks
Windows 10 Pro v1709, unity 2017.1.1f1 Personal
My hierarchy is like so, PanelB is the panel that gets set active after PanelA is inactivated:
The script called when the dropdowns option is selected is called like so in Start():
PickDropDown.onValueChanged.AddListener(delegate {
myDropdownValueChangedHandler(PickDropDown);
});
and the called function is:
private void myDropdownValueChangedHandler(Dropdown target) {
Debug.Log("selected: "+target.value);
stage = 0;
currentval = PickDropDown.options [PickDropDown.value].text;
advice.text = "";
title.text = currentval;
if (currentval != NONE) {
advice.text = "You chose to do "+currentval;
nextVal();
}
}
void newVal(){
Debug.Log("newVal " );
PanelA.SetActive (true);
PanelB.SetActive (false);
Debug.Log("options count="+ PickDropDown.options.Count );
}
void nextVal(){
Debug.Log("nextSet " );
PanelB.SetActive (true);
/*** next line shows the answer to my problem - from killer_mech **/
Destroy(PickDropDown.transform.Find("Dropdown List").gameObject);
/***************************************************************/
PanelA.SetActive (false);
}

Yes, this is a bug in unity. I can reproduce this now. This is happening because Unity is creating a game Object called "Dropdown List" inside dropdown which should get destroyed after the closing. But I have noticed a slight delay is happening while destroying(I used editor debug mode for this). When you set the game object active flag as false, it somehow stops the destroy object and results in object Dropdown List staying there so next time when you try to interact with it the object will still present. You will also notice a white box below the Dropdown list after this which indicates the dropdown list still is present.
For the solution what I did was just before I was about to turn my gameobject off I used
Destroy(PickDropDown.transform.Find("Dropdown List").gameObject);
Destroying this object solves the problem. I know this is not a good way to do it, but I checked whether any references to options are destroyed while destroying this which resulted in no error for me. And Dropdown creates new "Dropdown List" gameobject. So it is safe to assume that destroying is OK. Well not sure if any other good solution for this is out there but for now you can use this.
Note: I have tested this bug with Panel, Empty Gameobject as parent and finally with Dropdown
This shows what is happening inside the drop-down. 1) During No popup 2) During Open 3)After setactive off before the child is destroyed.

Related

Unity - How to react to scene picking? How to force select a parent by picking its child in the sceneview

I have the following situation I need an answer to:
I have a parent object with children. These children all have unique meshes. Whenever these children are selected in the SceneView, the parent needs to be selected in stead. The children should never have their inspectors exposed (not even a fraction of a second).
How do I do this?
There are two possible solutions that I have come up with which are not the solution I wish to go for.
First being using [SelectionBase] attribute on the parent object. This work perfectly, but only once. The first time the child is selected, the parent gets selected. However, when I click the child again, it still gets selected.
Second solution was to react on Selecten.onSelectionChanged. This however is too slow. I can set the selection to the parent if a child gets selected, but the child gets exposed for a few frames still.
Is there an instant solution to this which can guarantee me the functionality of SelectionBase, but then every time in stead of only the first time I click it?
Thanks in advance! :)
I have found a way to do exactly what i want. I combine the [SelectionBase] attribute with a piece of code in the editor OnSceneGui.
First add the [SelectionBase] attribute to your class
Second add this code to its editor class
private void OnSceneGUI()
{
HandleUtility.AddDefaultControl(0);
//Get the transform of the component with the selection base attribute
Transform selectionBaseTransform = component.transform;
//Detect mouse events
if (Event.current.type == EventType.MouseDown)
{
//get picked object at mouse position
GameObject pickedObject = HandleUtility.PickGameObject(Event.current.mousePosition, true);
//If selected null or a non child of the component gameobject
if (pickedObject == null || !pickedObject.transform.IsChildOf(selectionBaseTransform))
{
//Set selection to the picked object
Selection.activeObject = pickedObject;
}
}
}
This allows the first pick to select the component. From then on, only when you select non-child objects in the scene, selection will actually change.

How to select a treeItem in a treeView, after checking a Condition on that treeItem, in Javafx

I have downloaded familyTree project and it doesn't have the ability to search for an specific family member!
I have added a search button to it, and in the handler method section, I need the code that searches for a member that has the specified socialID , and select it (scroll it to the sight, and make it blue (selected)). But I don't know how to programmatically select a treeItem, and make it visible and selected?
My code:
#FXML
private void btnSearch_click(ActionEvent event){
for(TreeItem<FamilyMember> treeItem:root.getChildren()){
if(treeItem.getValue().getNationality().toString()=="22"){
// treeView.setSelectionModel(item);
treeView.getSelectionModel().select(treeItem);
//it still doesnt select the item with nationality=="22"
break;
}
}
}
You can select the item with
treeView.getSelectionModel().select(item);
and if you still need to scroll (I think selecting it might automatically scroll to it), do
treeView.scrollTo(treeView.getRow(item));
A couple of notes:
I do not understand the for loop. Why are you doing
TreeItem<FamilyMember> item = root.getChildren().get(i);
and why are you creating the index i? What is wrong with the treeItem variable you already defined in the loop syntax? Isn't this necessarily exactly the same thing as item?
You need to read How do I compare strings in Java?

Change dragging state for all markers

I'm using Leaflet.markercluster 1.0.1
I'm trying to add button on my map, so users can enter in 'edit mode'. On click on that button it should toggle dragging state for all markers. I don't really know how to implement that correctly, but I wrote that code
var drag = false;
$('#button').on('click', function () {
drag = !drag;
markers.eachLayer(function (marker) {
marker.options.draggable = drag;
if (marker.dragging) {
drag ? marker.dragging.enable() : marker.dragging.disable();
}
});
});
It works for some time, but then I get Exception on .enable()
Uncaught TypeError: Cannot read property 'classList' of null
Is anyone know any correct way to do that?
Thanks in advance!
It seems that the logic for the forEach method in MarkerClusterGroup iterates through markers not visible on the map after dragging a spiderified marker. Then the logic for enabling dragging fails, as the marker does not have an icon instance, because it has been removed from the map.
I've cleaned up the reproducible example a bit, and left a copy at https://playground-leaflet.rhcloud.com/qate/1/edit?html,output - I strongly suggest that you turn this into a good bug report in the Leaflet.MarkerCluster.
You may also check if each of the markers has a marker._map private property to check if they are on the map, and skip those which are not, but this may lead to other issues down the road.

How to remove/disable On-Keyboard Textbox when Using UIInput NGUI?

I am using NGUI's UIInput class to accept text input from user. when i start typing in text box in mobile devices. a key board appears and it has an another textbox within it self, with "OK"/"Done" button (Like a keyboard accessory view, if we're talking about iPhone).
Can i disable that text box appearing within keyboard ? Or its not even possible and i am shooting just blanks ?
From what i could gather by search for a while is, the appearance of keyboard is handled buy Unity's "TouchScreenKeyboard" class. but according to Unity Scripting reference there is nothing which could hide the textfield inside the keyboard.
Unity Scripting reference: TouchInputKeyboard
PS:- I should still be able to put input in textbox by directly typing into them, i just want an extra textbox within the key board to be removed.
TO be more clear i have attached images explaining this
This is the screen.
When i start typing in one of the textbox. a keyboard appears like the following.
as you can see the text box just above the keyboard is not the original one.
Did you try checking "Hide Input Check box" in Inspector view of that UIInput Textbox ?
private void OnGUI()
{
TouchScreenKeyboard.hideInput=true;
}
I don't know why it is, but I have had this problem as well and the "hide input" checkbox for some reason doesn't seem to do really anything other then change the keyboard text box from one line to multi line.
I did a little bit of digging and came across a quick lead that will enable that hide input check box.
This fix is Update() in UIInput.cs around 650
else if (inputType == InputType.Password)
{
TouchScreenKeyboard.hideInput = true;
kt = TouchScreenKeyboardType.Default;
val = mValue;
mSelectionStart = mSelectionEnd;
}
else
{
if(hideInput)
{
TouchScreenKeyboard.hideInput = true;
}
else
{
TouchScreenKeyboard.hideInput = false;
}
kt = (TouchScreenKeyboardType)((int)keyboardType);
val = mValue;
mSelectionStart = mSelectionEnd;
}
I added a check in the else statement

Unity Custom Inspector on Custom Window

I have a custom window that show a list of objects. Each of this objects has a custom inspector editor.
Is possible to show custom inspector inside the custom window?
You can't force Unity3D to draw your custom inspector somewhere else than inspector window.
Btw you can manually instatiate an Editor using Editor.CreateEditor method.
Since you are displaying a custom inspector, than it should be possible to instantiate it manually from inside Window.OnGUI method, and use the public OnInspectorGUI method of the editor to draw the editor inside your window.
For example, if you have attached a script called CustomScript to a GameObject and have a related Editor called CustomScriptEditor, supposing you have selected the GameObject from the hierarchy, this code visualize the custom inspector inside an EditorWindow:
using UnityEditor;
using UnityEngine;
public class TestWindow : EditorWindow
{
[MenuItem ("Window/Editor Window Test")]
static void Init ()
{
// Get existing open window or if none, make a new one:
TestWindow window = (TestWindow)EditorWindow.GetWindow (typeof (TestWindow));
}
void OnGUI () {
GameObject sel = Selection.activeGameObject;
CustomScript targetComp = sel.GetComponent<CustomScript>();
if (targetComp != null)
{
var editor = Editor.CreateEditor(targetComp);
editor.OnInspectorGUI();
}
}
}
As of right now, this question is a top google result for queries such as "Unity inspector inside editor window" so I'm making a necropost to share some very important information I learned through hours of frustration:
I'm building an Editor tool which makes use of custom inspectors inside of an EditorWindow, and I used the exact same method as Heisenbug. Occasionally while working on the tool my console would be bombarded with hundreds of mysterious null reference exceptions. Restarting Unity would make them go away but they would inevitably return. I was finally able to trace the problem to "Editor.CreateEditor", here is the lesson I learned the hard way:
You need to manually destroy any inspectors created from Editor.CreateEditor!
Normally Unity will instantiate an inspector when the relevant object is selected, and automatically destroy that instance as soon as the object is deselected/deleted/etc. But an inspector created via Editor.CreateEditor will never be destroyed and will linger somewhere in memory long after the object it was inspecting has been destroyed.
You can prove this by adding the following code to your custom inspector:
void OnEnable()
{
Debug.Log("on enable " + this.GetInstanceID());
}
void OnDisable()
{
Debug.Log("on disable " + this.GetInstanceID());
}
Using the inspector normally, you will always see these messages in pairs as instances of the inspector get created and then destroyed. But try instantiating a few inspectors from your EditorWindow class and you will only see the "on enable" messages.
I learned that Unity calls OnEnable() whenever scripts are recompiled. Try it and you'll see your console fill up with "on enable" messages from all the inspector instances that were never cleaned up. These instances will linger long after the objects they were inspecting have been destroyed, and any initialization code in OnEnable() will break spectacularly throwing an avalanche of mysterious exceptions.
My solution looks something like this (this code would go in your EditorWindow class):
Editor embeddedInspector;
...
// a helper method that destroys the current inspector instance before creating a new one
// use this in place of "Editor.CreateEditor"
void RecycleInspector(Object target)
{
if (embeddedInspector != null) DestroyImmediate(embeddedInspector);
embeddedInspector = Editor.CreateEditor(target);
}
...
// clean up the inspector instance when the EditorWindow itself is destroyed
void OnDisable()
{
if (embeddedInspector != null) DestroyImmediate(embeddedInspector);
}