Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Handles.Button to render & work on non-selected objects?

Discussion in 'Scripting' started by NanushTol, Jun 13, 2023.

  1. NanushTol

    NanushTol

    Joined:
    Jan 9, 2018
    Posts:
    121
    How can I have a Handles.Button to work on a non selected object?
    I'm trying to implement something like the selectable labels icon (because the default one creates an error)

    I've tried the [DrawGizmo(GizmoType.InSelectionHierarchy | GizmoType.NotInSelectionHierarchy)]
    but this only work for labels and such but the button functionality doesn't work.

    Also tried using and registering to SceneView.duringSceneGui, by creating an editor from the monobehaviour on start, this worked but it creates multiple editors instances and I cant check if one exists.

    any work around that would work to create a Handles.button ?
     
    Last edited: Jun 13, 2023
  2. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    You need to explain your situation better. I can only half-understand what you're trying and what you've tried. 3rd paragraph is enigma to me. Creating editors on start? I don't even know what that means.

    Also GizmoType is only useful for the DrawGizmo attribute, and that's not directly relevant to your problem. I mean you can use it, but that's more of a choice, not a necessity.
     
    Bunny83 likes this.
  3. NanushTol

    NanushTol

    Joined:
    Jan 9, 2018
    Posts:
    121
    Sorry about the mess :) Its late here and I was out of focus.

    I have this blue dots, like the one with the mount 1 label, these are Handles.Buttons that when press select the object associated.
    I want them to render in the scene view without selecting the object. from the moment the object is created/instantiated.

    right now I'm doing a bit of a hack, by creating the component's custom editor from the component(MonoBehaviour) OnEnable function, in order to initialize the editor when the component is loaded/enabled.
    and then register a function called OnScene to the SceneView.duringSceneGui event, so it continues on rendering even when the script is not selected.


    But this is a kind of a dirty trick I don't like, mixing editor code in MonoBehaviour.
    And also the blue handles disappear after Unity compiles scripts changes.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. #if UNITY_EDITOR
    6. using UnityEditor;
    7. #endif
    8.  
    9. [ExecuteAlways]
    10. [SelectionBase]
    11. public class PathScatterer : MonoBehaviour
    12. {
    13.     public Transform prefab;
    14.     public SmoothedPath path;
    15.     public bool isOpen;
    16.  
    17.     public bool isOnSceneActive { get { return _isOnSceneActive; } set { _isOnSceneActive = value; } }
    18.     private bool _isOnSceneActive;
    19.  
    20.     private void OnEnable()
    21.     {
    22. #if UNITY_EDITOR
    23.         if (!isOnSceneActive)
    24.             Editor.CreateEditor(this);
    25. #endif
    26.     }
    27. }

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEditor;
    4. using UnityEngine;
    5.  
    6. [CustomEditor(typeof(PathScatterer))]
    7.  
    8. public class PathScattererEditor : Editor
    9. {
    10.     private PathScatterer _script;
    11.     private SmoothedPathEditor _pathEditor;
    12.  
    13.     public override void OnInspectorGUI()
    14.     {
    15.         base.OnInspectorGUI();
    16.  
    17.         _script.path.isOpen = _script.isOpen;
    18.     }
    19.  
    20.     private void OnSceneGUI()
    21.     {
    22.         if(_pathEditor == null)
    23.             _pathEditor = CreateEditor(_script.path) as SmoothedPathEditor;
    24.  
    25.         _pathEditor?.OnSceneGUI();
    26.     }
    27.  
    28.     public void OnScene(SceneView sceneView)
    29.     {
    30.         if (target == null)
    31.         {
    32.             SceneView.duringSceneGui -= OnScene;
    33.             return;
    34.         }
    35.  
    36.         Vector3 pos = _script.transform.position;
    37.         float size = HandleUtility.GetHandleSize(pos) * 0.2f;
    38.  
    39.         Handles.color = new Color(0.94f, 0.55f, 0.22f, 1);
    40.         Quaternion rot = Quaternion.LookRotation(sceneView.camera.transform.position - pos);
    41.         if (Handles.Button(pos, rot, size, size, Handles.CylinderHandleCap))
    42.         {
    43.             Selection.activeObject = _script.gameObject;
    44.         }
    45.  
    46.         Handles.Label(pos + Vector3.up * size * 2, _script.gameObject.name);
    47.  
    48.         if (Event.current.type == EventType.MouseMove)
    49.             HandleUtility.Repaint();
    50.     }
    51.  
    52.     private void OnEnable()
    53.     {
    54.         _script = target as PathScatterer;
    55.  
    56.         if (_script != null && !_script.isOnSceneActive)
    57.         {
    58.             SceneView.duringSceneGui += OnScene;
    59.             _script.isOnSceneActive = true;
    60.         }
    61.     }
    62. }
    upload_2023-6-14_0-51-27.png
     
  4. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    Ok, well, hm.. I get what you mean, you want [DrawGizmo(GizmoType.NotSelected)] but this effectively kills the interactivity of your buttons, so you instead force the editor in a "hacky way". Does this introduce new problems? Are you satisfied with the overall behavior of this? In my view it's not hacky if you can't prove that it collides with something or inhibits you in any way. Unity is regularly hacky like this. I'd keep this until someone is able to show a more legit way to achieve this.
     
  5. NanushTol

    NanushTol

    Joined:
    Jan 9, 2018
    Posts:
    121
    Well I guess it will do for now, thank you anyway :)
    Other then the hackyness, the only problem is that it stops working when Unity recompiles scripts, havent understood why yet.
     
  6. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    Honestly I don't normally work with persistent editors like this and I do everything custom, i.e. I don't rely on Handles that much for interaction. Usually I have some contextual switch, either by selection, or via on/off button.

    I've seen a lot of things over the years, but my mind blocks in front of this particular issue. Yet there is nothing abnormal with your use case.

    All I can say is that if you're seeing anything peculiar emerging out of this, then your hunch is good and you're probably forcing it too much. There is probably some well-trodden path but I don't know it / can't find one.

    I personally wouldn't rely on automatics. I would implement an edit lock via inspector (making sure that object can't be deselected until the edit is turned off), kill the default tools, remove all default scene behavior (except mouse navigation), and would create a window for the parameters.
     
  7. NanushTol

    NanushTol

    Joined:
    Jan 9, 2018
    Posts:
    121
    So if I understand correctly you would create some kind of a master editor/toolset window/toolbar, that would handle all objects of certain types and display a cutom made "handle" or interactive element, based on a user prefrence? Instead of having each element/object manage its own existance automatically

    So for example this is a part of a terrain editor, so this editor would have a settings window that activates or deactivates certain handles/abilities etc...
     
  8. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    Well, I'm not sure if I understood that correctly. I would hijack the usual CustomEditor approach, but I would make the edit mode very clearly a different regime to work with. You are either just inspecting the selected object, or you are actively editing it. Only in the edit mode, the handles and corresponding windows would appear, and stay persistently there, until you decide to quit the edit mode. It should also actively prevent you from deselecting the object because that would invalidate the state.

    Once inside this edit mode, you are then free to completely substitute the Unity's reality with your own, and you have a clear line of demarcation, and clear signals when to actually disrupt everything and when to revert everything back.

    But even if you don't do this 'edit mode', you're supposed to have some point of entry into the "magical world" and the trigger is usually the object getting selected.

    The window doesn't have to be an ever-present thing if that's what you meant. It can show up only when it's contextually needed, i.e. you're in edit mode. So it doesn't violate like you said "having each element/object manage its own existance automatically". Each element is its own thing, but that's exactly the point, you shouldn't have to deal with hundreds of objects with their editors active. Editing is something that's pretty much a modal activity. You edit one thing at a time or in the case of editing a family of similar things, there has to be some umbrella somewhere. "Edit this spline", "edit this mesh", "edit this terrain". Not "edit all these disconnected splines all at once". That would be a hell to work with.

    Which is why perhaps the internal logic is leaning so heavily on selected objects and ignores you when you attempt to do otherwise. However, at this point I'm just speculating.

    In any case, you typically surround yourself with ample libraries that take the boilerplate and IMGUI away, so that your actual editor is refined to the point of being actually readable. However some fuzzy areas are unavoidable. Sometimes you have to cross the line and reach for the target object. I can't remember the exact use case, but it was completely justified. Guard that with #if and move along. It still counts as an editor code.

    After a while I've accumulated enough experience and libraries, that this approach has become my go-to way of dealing with the tools. But I'm absolutely positive that there are people who know more about the internals, and they probably have somewhat better ideas on how to leverage the existing logic. I can't even tell! I constantly discover new things I never knew existed.

    Editors in Unity are pretty much black magic, to this day. In my case, this is something I've refined over the years to at least get up to the level of knowing what the hell is going on. And eliminating the weird or unwanted behaviors so that I can concentrate on the actual editor logic. And I did some pretty wild things, like full voxel editor/painter similar to MagicaVoxel, whose data gets compressed on serialization, where you can rotate every individual cube (which makes it drastically more advanced than MagicaVoxel because you can have UV painted models instead of cubes), and even have Minecraft-like tools or MagicaVoxel-like editing in bulk.
     
  9. NanushTol

    NanushTol

    Joined:
    Jan 9, 2018
    Posts:
    121
    I like the approach of the "edit mode", after all I don't edit/make levels every day.
    I've created my fare share of artists editors in my professional life as a technical artist, but usually simple tools that focus on a single object at a time, this time its a full on terrain editor with a graph (that procedurally generate the landscape) + a set off tools,
    The part this post is all about is the tool set, so an "edit mode" fits the bill, I can add the selection display and logic to the tool bar that already exist, and this can handle displaying the selection circles for the toolset objects, probably will add a window with settings using a ScriptableSingelton.

    The voxel tool sound really cool :)

    Thanks for the help and your thoughts on the subject !
     
    orionsyndrome likes this.
  10. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    It is immensely cool. I'm especially proud of that one because it's loaded with great stuff, both algorithmically and on the use front. Perfectly integrated with the regular workflow and sporting a neat custom inspector. If I'm to be honest, this could very well be the best thing I've ever made in under a month, but there is such a long way before I can truly call it finished and make it into an asset or something. I really wish sharing stuff with the world was any easier.

    But no, you either just hand it over via Github -or- you have to produce ludicrous amounts of bling-bling to go full commercial. And you have no guarantees that this kind of time sink would ever pay off. It's a catch-22 situation for me.

    Anyway, originally it was intended as a level editor for a game that is shelved currently. But if anything it gave me some confidence that I have maybe mastered some of the aspects of Unity editor tools.

    NP, holler if you need more help with the edit mode setup.
     
  11. NanushTol

    NanushTol

    Joined:
    Jan 9, 2018
    Posts:
    121
    Would love to see it if you have a link :)
    Totally understand the dilemma regarding sharing it, I'm thinking of sharing this editor too, maybe after the game is released or maybe before IDK.

    BTW the approach with the window + a scriptable singleton as settings works :)

    upload_2023-6-14_21-55-10.png
     
    orionsyndrome likes this.