#↕️┃editor-extensions

1 messages · Page 97 of 1

wanton arrow
#

that I can't get objectReferenceValeues if they aren't UnityEngine.Objects

supple willow
#

@gloomy chasm hey u said u could get it through reflection?

#

I'm trying to do the same without using fieldinfo

#

That even possible?

#

I even tried printing all the properties inside the Target object through reflection, but that just printed the properties of the game object it's attached to

#

So we have access to it's game object, but not its own object?! That's ... Seems not practical... Or maybe I'm missing something?

waxen sandal
#

Can you give some more context

supple willow
#

let me just show u the debug , maybe it is in fact its own object

supple willow
waxen sandal
#

The property you get passed is the object

#

If you want an instance and it's a non Unity object then you have to use reflection no other way

supple willow
#

It is reflection , mate. I'm talking specifically about reflection

waxen sandal
#

GetProperties on what?

#

Give some context dude

supple willow
#

yeah I'm tryina open Unity. My PC just shut itself down because of power

#

I dunno why steam opens itself everytime PC is restarted... Even with it's checkbox disabled ( and it's as an administrator )

#

so, this :

var parent = property.objectReferenceValue;
var props = parent.GetType().GetProperties();

prints this :

Boolean useGUILayout : True
Boolean runInEditMode : False
Boolean allowPrefabModeInPlayMode : True
Boolean enabled : True
Boolean isActiveAndEnabled : True
UnityEngine.Transform transform : Main Camera (UnityEngine.Transform)
UnityEngine.GameObject gameObject : Main Camera (UnityEngine.GameObject)
System.String tag : MainCamera
System.String name : Main Camera
UnityEngine.HideFlags hideFlags : None
#

@wanton arrowhey, i remembered what it was i was using ! it's

var target = property.objectReferenceValue as [name of your object];
waxen sandal
#

That doesn't work for non unity objects

wanton arrow
#

yeah...

waxen sandal
#

Anyways, you can use the property.propertyPath field to determine what properties you need to traverse to get to your struct/class

#

Then use reflection to get the value of that field

wanton arrow
#

ah

#

should def just make a helper class

gloomy chasm
wanton arrow
#

I mean helper function

supple willow
gloomy chasm
#

It can get tricky to make sure it supports serializing by reference with the [SerializeReference] attribute.

wanton arrow
#

I mean I can try it but theres no way it works

#

its not like it can magically hold a value that It isn't

waxen sandal
#

Safe casting works, but non unity types are not exposed in objectReferenceValue and thus you'll get null

wanton arrow
supple willow
#

see, considering this class is named Rotatable, i even have access to it's private variables this way

wanton arrow
#

you can't cast an Object to a Non-Object

supple willow
#

but this system.serializable is important

wanton arrow
#

yeah

#

its an Object

#

I know you are trying to help dude but you gotta read

gloomy chasm
#

Normally you would be right though.

supple willow
#

yeah i see the prob...

waxen sandal
#

Also directly accessing fields like that is frowned upon

supple willow
#

@gloomy chasmhey sorry for keep askin , but will this work without probs ?

#

full code. the class is not of type UnityEngine.Object

supple willow
#

then with this, it also now saves the property

#

this would show how it can also use private properties ( i mean c# properties with set/get )

#

(though it wont work on arrays)

visual stag
#

Why not use SerializedProperty? You're just making things complicated for no apparent reason

supple willow
visual stag
#

If you're making a property drawer for something that has some property logic in it why not just copy that logic to the drawer if you need it

supple willow
visual stag
#

Sure, you can have the code in both

supple willow
#

imagine you needed to change it and u already copied it to 9 different places

visual stag
#

To me messing about making some over complicated property drawer that bypasses editor functionality and isn't guaranteed to dirty things that the property could touch is bad practice

supple willow
visual stag
#

You do you then

supple willow
#

what do u mean :?

visual stag
#

I'm not here to argue, if you wanna do it this way go ahead 👍

supple willow
#

whatever...

supple willow
#

@visual stag as for the complexity u mentioned, it'd be wise to turn the nasty part into some method :) now it's as clean as an Editor's OnInspectorGUI() ... even less code than that ;)

#

yeah making things simple to use is a major factor

visual stag
#

Though, it doesn't support undo

supple willow
waxen sandal
#

Everything is possible with a bit of tweaking

#

Doesn't mean it's a good idea

visual stag
#

Sure, none of that's the issue I have with it really.

supple willow
#

im not gonna argue with u about choosing the easier (lazier ? ) way to achieve less functionalities while two more new lines would open up a whole new potentials !

supple willow
#

even gives this blue effect

visual stag
#

You're setting the property via a property field, that does it

supple willow
#

yes

visual stag
#

And seeing as it's a property drawer it added the blue to the declared area

#

The change check is irrelevant to that functionality

#

Begin-end property handles the blue actually, but not sure if it's required in a property drawer

#

Could be wrong though

waxen sandal
#

Not required but heavily recommended

#

IIRC it does a bunch of magic things

supple willow
supple willow
#

this is the properties i tested with

waxen sandal
#

So much redundant work for little to no gain

supple willow
supple willow
# waxen sandal So much redundant work for little to no gain

i dont know, sometimes this little C# properties save lots of hours of time. for me personally I always find myself using them over GetValue/SetValue , which is a c++/java thing to do , but properties are C#-ish and i personally use them everywhere

#

definately depends on usecase though

waxen sandal
#

You're setting the backing value to the value that sin returns, which then executes sin again on it when you use it again

supple willow
real meadow
#

I'm at a bit of loss as to why this is so slow. I right-click to make a node. I left-click on the node, but notice how long it takes for the UI to go from painting a Label to instead painting a textbox. That's in real-time.

waxen sandal
#

Guessing you need to call repaint

real meadow
#

Huh, yeah. That did seem to do it.

#

Thanks @waxen sandal

real meadow
#

I want to make a field in my custom editor that lets you pick an image from the assets in your folder, like the native Image picker.

#

But I cannot figure out which Editor class has the functionality to make such a picker.

waxen sandal
#

Which picker speicfically?

real meadow
#

So if you wanna work with UI Images in Unity, you have a picker for that specific thing. You click it and it opens up your asset folder so you can look for the image you want to insert.

#

How would I achieve that for a custom editor?

visual stag
#

It's just an object field

waxen sandal
#

^

real meadow
#

When I tried to use an ObjectField the IDE said it was obsolete.

waxen sandal
#

Differnet overload

visual stag
#

Use the overload that isn't

real meadow
#

In EditorGUILayout?

#

I think that's the one that gives the objectfield

visual stag
#

Yes, look at the docs

real meadow
#

ok

#

Can I somehow give the ObjectField a Rect so I can control better where I want it to be on the screen?

#

Or is that in the GUILayout options somehow?

visual stag
#

EditorGUI

real meadow
#

Thank you

#

It was pretty hard to search for this stuff because I didn't really know what to search

visual stag
#

Though, as I often say if anyone's making a node tool in Unity these days if it is at all complicated it's best to use GraphView, which is Unity's built in library for node editors (there is a tutorial pinned to this channel)
It has a learning curve as it uses UI Elements, but so does IMGUI, and it doesn't have scaling for free

real meadow
#

I wanted to avoid UI Elements because it's a dependency that not that many people seem to have jumped on yet

waxen sandal
#

It's there in every version since 2018

real meadow
#

I've tried to install it before in different versions and I had several issues with errors even when I didn't use it. I generally stayed away from it after that until someone would be like "Yeah it's good now."

visual stag
#

There is no need to install anything

#

Editor has had it built in and functional for many versions now

#

UIBuilder and runtime UI are a different story

real meadow
#

Hm

#

Okay

#

So far I'm doing okay with IMGUI. I think after I get to a point where I might be okay with this version, I'll try UIElements

real meadow
#

So I'm having some issues using OpenGL to draw a line. As you can see in the gif, the line is always offset quite a lot. If I move the node around the lines origin and end point will also change relative to the nodes location..

#
private void DrawLine()
{
    if (_isConnecting == true)
    {
        Event current = Event.current;
        if (current.keyCode == KeyCode.Escape)
        {
            _isConnecting = false;
        }
        else
        {
            GUILayout.BeginHorizontal();
            Vector2 nodePos = _nodes[_mousedNode].CanvasRect.position;
            Vector2 mousePos = current.mousePosition;

            if (current.type == EventType.Repaint)
            {
                GUI.BeginClip(_gridRect);
                GL.PushMatrix();

                GL.Begin(GL.LINES);
                GL.Color(Color.cyan);
                GL.Vertex3(nodePos.x, nodePos.y, 0);
                GL.Vertex3(mousePos.x, mousePos.y, 0);
                GL.End();

                GL.PopMatrix();
                GUI.EndClip();
            }
            GUILayout.EndHorizontal();
        }
    }
}
#

One thing is the origin point maybe not being correct, but even the mouse position is not correct either so what am I missing about the GL.LINES

gloomy chasm
real meadow
#

Hm, I tried to subtract the Left panel from my X value but that didn't adjust the value as expected

#

This is practically perfectly on the mouse. But I don't get why 1.6f is the difference.

GL.Vertex3(nodePos.x - (node.CanvasRect.width + _gridPadding), nodePos.y + node.CanvasRect.height * 0.5f, 0);
GL.Vertex3(mousePos.x - (node.CanvasRect.width * 1.6f), mousePos.y, 0);
gloomy chasm
#

Does moving the editor window change where the lines are drawn? (I can't remember of GL works per window or on screen)
Again, this is all taken care of with GraphView, I really do recommend using it instead.

real meadow
#

I'm kind of committed now so I wanna see if I can get it to the end

#

😛

gloomy chasm
real meadow
#

Oh it's just a free tool I'm releasing on my open repo

#

after that I can look at a GraphView version

tough stream
#

Hi! I've drawn a reorderable list and wanted to customize the add/remove callbacks, but i'm faced with a problem: how can i indicate the actual selected element properly?
My callback for now:

private void OnRemoveCallback(ReorderableList list)
    {
        //indexToDelete = list.focusedElement;
        ActionSO toDelete = (ActionSO)leafActionsSp.GetArrayElementAtIndex(indexToDelete).objectReferenceValue;
        DestroyImmediate(toDelete, true);
        if (leafActionsSp.arraySize != 1)
        {
            leafActionsSp.MoveArrayElement(indexToDelete, leafActionsSp.arraySize - 1);
        }
        leafActionsSp.arraySize--;
    }```
And of course, list.focusedElement is a pure product of my mind and does not exist. Any tips?
gloomy chasm
# real meadow Oh it's just a free tool I'm releasing on my open repo

No, the sunk cost fallacy is when you have put so much in to something already(whether that is time, or money, or something else) you feel like you would lose all that if you stopped to do something 'cheeper'. When in actuality you spend even more on the thing then if you had just switched to the other thing.

real meadow
#

I know exactly what Sunk Cost Fallacy is

#

This is not that, because I'm not keeping from switching due to a lot of time used here that I don't wanna feel like is wasted. I wanna finish this so I can make a Graph View version after this.

gloomy chasm
real meadow
#

It's nice learning

gloomy chasm
tough stream
#

no fkin way

#

thanks lmaoo

#

you mean this?

gloomy chasm
tough stream
#

well, one way to find out lmao

gloomy chasm
#

Yup. And you can always see what comes up when you type select

#

If you are using VS, you can click on the ReorderableList class and hit F12 and it will show you all of the methods and properties of it.

tough stream
gloomy chasm
#

Does index work?

tough stream
#

this index variable works though! hehe

gloomy chasm
#

Good.

tough stream
#

thanks a bunch!

sage sedge
tough stream
#

yooooo no way

#

my spanish teacher named me this way 5 years ago

#

since then, i was reborned

wanton arrow
#

is there an easy way to get this to just draw with the GameEvent propertyDrawer?? I want to be able to make tons of these and just change the default message

#

its [System.Serializable]

#

sorry I found it its setting the second param (useForChildren) in the [CustomPropertyDrawer] to true oop

opaque zenith
#

I know this is old, and forgot who asked, but, as i keep learning, I came across this (Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed") that can be used in undoing

tender rain
#

Does anyone know how to use serializedObject.ApplyModifiedProperties to save properties on a scriptable object?

gloomy chasm
gloomy chasm
tender rain
#

I've got a scriptable object that's not saving a list when i play the game, I'm thinking it's something that can be fixed with serialize object

supple willow
tender rain
#

Oh, I'll try that

slim zinc
sage sedge
#

When i exit playmode, i get spammed in the console, Relating to if((Selection.Contain))

How can i solve this?

vernal belfry
#

Does anybody know which element do i need to modify in order to overwrite the row and column labels?

#

i mean the 0,1,2,3.....

#

i cant find how to modify that

opaque zenith
# vernal belfry

first, value == null will never happen when checked this way as a bool returns false or true. You either need to make bool a nullable type or change the logic. Other than that, the code for those labels isn't present in the code you showed, so, I'm assuming you have a loop somewhere that is using Drawer and is using some kind of field to display which index number that is.

vernal belfry
#

the field that displays the index is probably being drawn automatically by Odin

#

but I was expecting to be able to overwrite it from inside the drawer

opaque zenith
vernal belfry
#

just... which is the correct property i have to modify?

#

i mean..

#

LabelField creates a label inside

opaque zenith
vernal belfry
#

i mean the labels in the sides... the 0,1,2 are those for unity the same as the ones with 'myLavel' text?

#

what i want to change is the 0,1,2.... and i was wondering if thats another type of control or.....

#

the labels inn the sides and the top i mean

opaque zenith
vernal belfry
#

it might be inside Odin libraries then

#

thanks eliseus

opaque zenith
vernal belfry
#

ye0

#

yep

#

ill try

#

👍

opaque zenith
# vernal belfry 👍

sorry again, I haven't used Odin so can't really help directly with that. I like to try and make all my own things haha

vernal belfry
#

yeah sure, no prob, probably i should try to create the matrix by myself

#

unless the odin guys help me with this

dusk socket
#

How can do in visual studio after I right a dot(.) it give me options on what to write?

gloomy chasm
analog valley
#

Hello guys, any ideas on how could I stack 100 prefabs, one on top of another exactly, a distance of approx 4 units? It's to make multiple floors in a building

sage sedge
#

since i dont know how gameObject can ever be null

gloomy chasm
sage sedge
#

@gloomy chasm Its an asset used for painting grass, sometimes when i leave playmode, it'll spam the console with errors indefinatly untill i close unity and reopen it

sage sedge
#

if (gameObject != null &&(Selection.Contains(gameObject))) i will try it

gloomy chasm
sage sedge
#

that part of code is inside GrassPainter

gloomy chasm
#

Just read the console error, it should be clear how to fix it and if not just copy paste in to google and someone will have already asked what the error means and how to fix it.

sage sedge
#

got it, thank you 🙂

#

i didnt got it, i googled some forums, and it says its todo with a bad unity version? I'd understand if i was instantiating things in OnDestroy but im not

#

if (gameObject.GetComponent<GrassPainter>() != null && (Selection.Contains(gameObject)))

opaque zenith
#

sorry guys, I know these are noob questions, but, I'm trying to take advantage of propertydrawers more. I don't quite understand the difference between public override VisualElement CreatePropertyGUI(SerializedProperty property)
and doing

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        // Using BeginProperty / EndProperty on the parent property means that
        // prefab override logic works on the entire property.
        EditorGUI.BeginProperty(position, label, property);

I read If the PropertyDrawer is used inside a UIElements-based inspector or EditorWindow, the UIElements implementation will be used if PropertyDrawer.CreatePropertyGUI is overwritten with a fallback on any IMGUI implementation. If the PropertyDrawer is used inside an IMGUI-based inspector or EditorWindow, only the IMGUI implementation will display. You cannot have UIElements running inside IMGUI

So, does that mean one is used in editorwindows, while one would be used for inspectors, but, isn't the inspector an editor window? Why ever use one over the other instead of one that can be used in both?

gloomy chasm
#

EditorGUI.PropertyField(..) is IMGUI and will use OnGUI(..) (This is how the inspector works by default), where new UnityEditor.UIElements.PropertyField(..) is UITK and will use CreatePropertyGUI if it is implemented, otherwise it will use OnGUI.

opaque zenith
#

is there a benefit to using UIElements over IMGUI? I see that the fallback exists for IMGUI, but, you an IMGUI inspector takes priority. Should I try to make everything in IMGUI? I know we talked about the UITK before and part of why this is coming up is trying to delve more into these things it made me wonder if I should waste my time with it?

gloomy chasm
visual stag
#

I find it's harder to style UITK to "look like" another control, which I find myself doing in IMGUI a ton, but I'm in mostly the same position

gloomy chasm
visual stag
#

I pass different EditorStyles to controls all the time, ones that don't match the type of the control. Making toggles look like buttons is a main one

gloomy chasm
#

Ah yeah, yeah.

visual stag
#

To get any of that done in UITK I have to do a lot of experimentation, exploration of their codebase, mess around with making my own classes, it's really time consuming

gloomy chasm
#

Oh really?

visual stag
#

When they get back to making editor stuff UITK (once they're settled with their runtime stuff) I'll be happy 😄

gloomy chasm
#

They are so inconsistent with their use of UITK in the editor xD

#

But I too will be happy when more of the editor is UITK. They finally made ListView be able to fully mimic the ReorderableList.

visual stag
#

At least you can easily use IMGUI in UITK, that means you can always make the base of something UITK and then give up

visual stag
#

that was one of the main reasons to not use it

gloomy chasm
#

They also made it so the items can have variable height now.

visual stag
#

Oooh that's gonna be a bit of a game changer

gloomy chasm
#

They must of done massive refactors of the ListView like 4 times now...

#

It has changed so much.

visual stag
#

We're likely going to finally get a UITK channel btw. I think we must just be finalising something

gloomy chasm
#

Which is rather annoying since I have used it used it in 'advanced' ways and had to re-implement stuff my self like reordering in 2020.3.

gloomy chasm
visual stag
#

I have only made a few basic things that didn't exist in the past, HelpBox is one that comes to mind. Everything else I've run into has just been a "fuck this" moment

gloomy chasm
#

How much do you want to bet that they never actualy rename the namespace from UIElements to UIToolkit?

visual stag
gloomy chasm
steep talon
#

Anyone aware if this UV mess of the LineRenderer corners is fixable in some way? Or should I consider using a 3rd party asset or code my own renderer instead? 😅

waxen sandal
#

Wrong channel, wouldn't expect it to be easily fixable though

sage sedge
#

I'm still getting this spammed to in the console after playmode, I've tried to check if the component is null or not but it just wont stop

#

Relating to line 109

median shadow
#

Had a similar issue. Fixed by nullchecking this, then this.gameobject

waxen sandal
#

You're probably not unsubscribing from an event

sage sedge
sage sedge
waxen sandal
#

As in from the assetstore?

#

If so leave a bad review

#

Especially if you paid for it

sage sedge
#

i dont know if you know about them

waxen sandal
#

Ah, bad luck then

median shadow
#

ha! im using the same asset.

#

fun thing about the way they set that up is the grass length is tied to uvs, so you can update the height at runtime 🙂

sage sedge
median shadow
#

Sure

tough cairn
#

is there a way to draw Handles.PositionHandle with only the X & the Y axis ?

#

the available arrow handle is lacking return values so i can't use it to move stuff

waxen sandal
#

Think you'd have to look at how it's implemented internally and copy it

visual stag
#

ArrowHandleCap is a Cap function

#

you provide it to other functions

#

in this case, Slider I think

supple willow
#

working on a custom A* :)

tough cairn
#

is there a way to capture scene save event ?

#

I have cloned a material from sharedMaterial during edit mode ( instead of using renderer.material which will be used in play mode )

#

but when i save the scene the cloned material is invisible

#

the render shows MyMat ( instance ) in the field , and it still exits but it won't render

#

my guess is that the instance variables are reset ... so im looking for a way to listen to Scene Save Event - so i can reapply the material properties

tough cairn
#

ok i solved it , so here is what i did

class MyMono : MonoBehaviour 
{
    public static event System.Action OnSceneSave;
#if UNITY_EDITOR
    class ListenToSceneSaveEvent : UnityEditor.AssetModificationProcessor
    {
        static string[] OnWillSaveAssets(string[] paths)
        {
            var active = SceneManager.GetActiveScene().path;
            foreach ( var path in paths ) 
                if( path == active ) OnSceneSave?.Invoke();
            return paths;
        }
    }
#endif
    void OnEnable() => OnSceneSave += StartDelayedValidate;
    void OnDisable() => OnSceneSave -= StartDelayedValidate;
    void StartDelayedValidate() => StartCoroutine( DelayedValidate() );
    IEnumerator DelayedValidate()
    {
        yield return null;
        OnValidate();
    }
    void OnValidate() { ... } // <- code for material property update  
}
tough cairn
#

on the plus side , don't need the delayed callback anymore

vale bramble
#

Can I turn off objects in a certain layer in the scene editor?

#

I mean hide not turn off

gloomy chasm
vale bramble
#

Tyvm!

keen pumice
#

[debug logs show that everytime I call PopupWindow.Show my popup content class shows BOTH a onOpen and onClose get called.]

opaque zenith
# keen pumice I have a CustomPropertyDrawer that I want to, in some cases, show a popup editor...

PopupWindowContent.OnClose is called when the popupwindow is closed, so, if you have a debug inOnOpen and OnClose of course it should show a debug for those. You haven't provided any code, so, I can't really say for sure, but, somewhere you are opening and closing it, which, I would assume is in your propertydrawer based on the question. Make sure you aren't creating a new PopupWindow every time.

#

specifically, this example is important to reference

    void OnGUI()
    {
        {
            GUILayout.Label("Editor window with Popup example", EditorStyles.boldLabel);
            if (GUILayout.Button("Popup Options", GUILayout.Width(200)))
            {
                PopupWindow.Show(buttonRect, new PopupExample());
            }
            if (Event.current.type == EventType.Repaint) buttonRect = GUILayoutUtility.GetLastRect();
        }
    }

if you haven't done something like this. You have 2 events that are important in GUI, 1 is Repaint, the other is Layout

keen pumice
opaque zenith
keen pumice
#

(I want it to display when my property drawer is in a particular state, rather than when the user presses a button.) Think I missed your point about the events.....

keen pumice
#

(when display state is true)

#

sounds like I may need to change it to.. when the display state GOES true

gloomy chasm
keen pumice
gloomy chasm
keen pumice
#

yes

gloomy chasm
#

That is the problem

#

Only one popup can be open at once and you are opening a new one each time you call Show()

keen pumice
#
    bool isOpen = false;// in class
//in function
       if (!isOpen)
        {
            PopupWindow.Show(pos, filteredListContent);
            isOpen = true;
        }```  did as a test- no more blinking- but also dont see it...
opaque zenith
# keen pumice (I want it to display when my property drawer is in a particular state, rather t...

check out https://docs.unity3d.com/ScriptReference/EventType.Repaint.html and https://docs.unity3d.com/ScriptReference/EventType.Layout.html
I mentioned them from the example in PopupWindow because of things like GUILayoutUtility.GetLastRect only work in the repaint event, which, can not only be used (not the only way mind you, just trying to help diagnose the problem with little info provided) to give the window the proper rect, but, to help maintain the window opened, if it was the last rect

gloomy chasm
#

Can you please put the full code in to a hastebin (or whatever one you like) and share it

#

The context around your code and where/when/how it is being called is important.

gloomy chasm
opaque zenith
#

which I know this is a layout thing... I actually thought it was weird to do a an editor window from a propertydrawer to begin with, but, I don't like using propertydrawers much yet hehe

opaque zenith
keen pumice
#

hmm.. is it possible it IS open.. but just hidden "beneath" the editor window or something? gonna try different RECT to test that

gloomy chasm
keen pumice
#

(I mean certainly , this logic is NOT perfect.. but I expected to see the popup with it)

gloomy chasm
#

You know I just remembered that I'm like 98% sure that popups auto-close when they lose focus.

keen pumice
#

I tested by just clicking the control, not typing.. (though I tried typing.. which is how it became clear it had indeed lost focus, as you mentioned)

#

clicing on it yields this in the debug log:

#

trying a button for sanity sae now

#

worked fine with a button for the conditional- AND repeated clicks on the button toggle it on and off!!! so it seems like the second call to Show is turning it OFF! Did I just miss that part of the docs?!

keen pumice
#

ok I got it working, but somthing odd is going on ... this works: isOpen = true; PopupWindow.Show(position, editorWindowContents); but this does not!!! PopupWindow.Show(position, editorWindowContents); isOpen = true;

#

is almost seems like control is not returning... PopupWindow.Show(position, editorWindowContents); Debug.Log("POST show log"); that log is never displayed, even when the popup is opened

#

no exceptions shown in log.. hmm that is VERY odd...

#

well, anyway- got it going now.. thanks for the help @gloomy chasm@opaque zenith

opaque zenith
opaque zenith
#

can you use https://docs.unity3d.com/ScriptReference/Event.Use.html to stop excessive repainting? I know that it says Events of type EventType.Repaint and EventType.Layout should not be used. Attempting to call this method on such events will issue a warning. but, if you set it up to only repaint based off the current event use?

#

sorry, just read about event.use and trying to understand it more I guess

onyx harness
#

You can't prevent an already executing Layout/Repaint Event

#

Try to think early in the process

#

"Who is triggering this repaint?"

opaque zenith
onyx harness
#

wantsMouseMove, RequiresConstantRepaint(), a user interaction, Repaint()

opaque zenith
onyx harness
#

UnityEditor.EditorApplication.Internal_RepaintAllViews triggers a full repaint

opaque zenith
onyx harness
#

Many ways to repaint stuff, low & high levels

opaque zenith
# onyx harness Many ways to repaint stuff, low & high levels

If you don't mind me asking. I can probably just google it, but I enjoy the convo hehe. Is low & high level where lower is more barebones coding, and higher takes the barebones and creates more user friendly of the lower levels? I'm been seeing this used more often in things I'm looking up and just assumed that was what it is

onyx harness
#

Repaint() is high level, the highest

#

Lower is more like through Reflection triggering a repaint from a View

frozen cove
#

Is there a callback or way of identifying when a prefab stage is opened and closed?
For open I have:

private void OnValidate()
{
    if (PrefabStageUtility.GetCurrentPrefabStage() != null) Debug.Log("I'm open");
}```
Which works alright... but how do I identify when it's closed?

(I have prefabs which are loaded in URP and SRP and it would be great to switch the editor into those modes when editing those prefabs)
opaque zenith
#

PrefabUtility.GetPrefabInstanceStatus I think

#

you can also use Selection to determine that also

frozen cove
opaque zenith
frozen cove
#

But selection is just what's selected in Scene or Project

opaque zenith
#

register to Selection.selectionChanged for example

frozen cove
#

Ideally I'm after OnOpenPrefab > Check which render pipeline it is built for > Switch editor to that pipeline

opaque zenith
frozen cove
#

Yes but selecting a prefab in the project isnt the event I'm trying to capture

#

It's opening and closing it

opaque zenith
frozen cove
#

🤔 could you elaborate a little?

frozen cove
#

Oooooh! 😍

#

That looks like what I'm after

wild edge
#

its experimental though... so you know... might break

frozen cove
onyx harness
#

Not anymore

frozen cove
#

Ahh yeah, I'm in the old world for now

wild edge
#

LTS keeps you sane

frozen cove
wild edge
#

from the LTS version you can look into the future and see what will happen... cant do that with bleeding edge 😉 ... i.e. never trust a roadmap

opaque zenith
# frozen cove 🤔 could you elaborate a little?

for example, if you register to the selection change event, in the method your registered with, you can add

if (Selection.gameObjects.Length != 0)
{
  foreach (GameObject go in Selection.gameObjects)
  {
    if (PrefabUtility.GetPrefabObject(go) != null)
    {
      PrefabUtility.GetPrefabInstanceStatus(go);
    }
  }
}
#

obviously add more for your intended purpose of finding the instance status, but, this will work for that

frozen cove
# opaque zenith for example, if you register to the selection change event, in the method your r...

I now have this on a script on the Prefab

private void OnValidate()
{
    if (PrefabStageUtility.GetCurrentPrefabStage() != null)
    {
        switch (renderPipeline)
        {
            case RenderPipeline.StandardRenderPipeline:
                if (GraphicsSettings.renderPipelineAsset != null) GraphicsSettings.renderPipelineAsset = null;
                break;
            case RenderPipeline.UniversalRenderPipeline:
                RenderPipelineAsset RPA = (RenderPipelineAsset)AssetDatabase.LoadAssetAtPath("Assets/Framework/Render Pipeline/UniversalRenderPipelineAsset.asset", typeof(RenderPipelineAsset));
                if (GraphicsSettings.renderPipelineAsset != RPA) GraphicsSettings.renderPipelineAsset = RPA;
                break;
        }
    }

    PrefabStage.prefabStageClosing -= OnClosePrefabEditMode;
    PrefabStage.prefabStageClosing += OnClosePrefabEditMode;
}

private void OnClosePrefabEditMode(PrefabStage obj)
{
    RenderPipelineAsset RPA = (RenderPipelineAsset)AssetDatabase.LoadAssetAtPath("Assets/Framework/Render Pipeline/UniversalRenderPipelineAsset.asset", typeof(RenderPipelineAsset));
    if (GraphicsSettings.renderPipelineAsset != RPA) GraphicsSettings.renderPipelineAsset = RPA;

    PrefabStage.prefabStageClosing -= OnClosePrefabEditMode;
}

Opening and closing the prefab handles the events itself and only calls them once.

opaque zenith
#

so, I setup an editorscript of sorts that is auto added to a scene gameobject when I select it, then removed when I unselect. I feel like I can do something different though without having a constant adding and removing. I haven't messed with Editor.CreateEditor and wondering if that is possible what I should be doing instead?

gloomy chasm
opaque zenith
#

but I was thinking maybe I should just make a class that is registered to events that does this

whole steppe
#

this is probably super simple but does anybody know how to change the orientation of New Shapes in probuilder

#

whenever i create new shapes, they're locked to face a certain direction regardless of where the viewport camera is located

opaque zenith
#

Does anyone know how to get the screen width and height while in editor? I only know how to get the current view width and the default Screen.Width and Screen.Height return my gameview dimensions.

gloomy chasm
opaque zenith
gloomy chasm
#

You can get the size of the main view area 'easy' enough if that will do I guess.

opaque zenith
# gloomy chasm Why do you want it?

I'm creating some editor windows to have popup at certain positions specifically if opened. between currentview and handlesGUI I have been able to do most editor ui things this way, but, now I'm curious about this lol. I don't need it at all, just one of those things I'm determined to figure out now

gloomy chasm
#

I think there is another way, but I don't remember what it is.

opaque zenith
#

I think that is still the gameview, but wondering if that was what you might have been thinking about

gloomy chasm
opaque zenith
gloomy chasm
#

The MainView is the area below the top toolbar and the bottom app status bar.

#

The area where you can dock windows

opaque zenith
gloomy chasm
opaque zenith
gloomy chasm
opaque zenith
opaque zenith
#

okay cool, with this I was able to use the max values to basically get the proper screen width and height

opaque zenith
#

I feel like this is excessive, but, I can't think of a better way? Rect r = new Rect((mainWindowMax.x - mainWindowMin.x - window.position.width) / 2.0f, (mainWindowMax.y - mainWindowMin.y - window.position.height) / 2.0f, window.position.width, window.position.height);

#

for the center

#

for example

#

actually, think I did that wrong. Think I want to add the mins to offset anything the screen would be forcing the min higher than 0 to give the appearance of being centered on the screen, vs this being centered off the main window

opaque zenith
#

okay, realized the min doesnt matter at all for screen, so. ended up with

Rect r = new Rect(mainWindowMax.x / 2.0f - window.position.width / 2.0f, mainWindowMax.y / 2.0f - window.position.height / 2.0f, window.position.width, window.position.height);

is the most accurate to center and can build off that I guess

dapper yacht
#

Hello everyone, is there a way to call FindObjectOfType from an editor script ?

#

it always return null value 😦

tough cairn
#

I cloned a material form a public variable in my script on OnEnable() and settings the Renderer material during edit mode - then destroying and setting it to null on OnDisable() with [ExecuteInEditMode] and its fine - updating the material properties OnValidate()

But when i copy and paste the same game object - changing one value in the script changes the copy material as well.

Which is strange because when i clone the object i give it random name and looking at the inspector's renderer it has two different materials

tough cairn
#
using UnityEngine;

[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
[ExecuteInEditMode]
public class TestScript : MonoBehaviour
{
    public Material original;
    MeshRenderer render;

    [System.NonSerialized] Material mat;

    bool is_ready = false;

    void OnEnable()
    {
        render = GetComponent<MeshRenderer>();
        ApplyMaterial(true);
        is_ready = true;
    }

    void OnDisable()
    {
        DestroyMaterial();
        is_ready = false;
    }

    bool ApplyMaterial(bool forceNew = false)
    {
        if (original == null) return false;
        if (forceNew && mat != null) DestroyMaterial();
        if (forceNew || mat == null)
        {
            mat = new Material(original);
            mat.name += " (preview) " + ( (int) ( Random.value * 9999 ) );
        }

        if( mat != null ) render.material = mat;

        return true;
    }
    void DestroyMaterial()
    {
        if (Application.isPlaying) Destroy(mat);
        else DestroyImmediate(mat);
    }

    private void Update()
    {
        if( ! is_ready || Application.isPlaying ) return;

        ApplyMaterial( false );
        UpdateMaterial();
    }
    private void OnValidate() => UpdateMaterial();

    public Vector3 row0 = new Vector3( 1, 0, 0 );
    public Vector3 row1 = new Vector3( 0, 1, 0 );
    public Vector3 row2 = new Vector3( 0, 0, 1 );
    public Vector2 shift = Vector2.one * 1.5f; 
    public float extend = 0.5f;

    void UpdateMaterial()
    {
        if( mat == null ) return;
        mat.SetVector("ComposeRow0", row0 );
        mat.SetVector("ComposeRow1", row1 );
        mat.SetVector("ComposeRow2", row2 );
        mat.SetVector("ComposeShift", shift );
        mat.SetFloat("ComposeExtend", extend );
    }
}
#

the only explanation i can find that when doing a copy paste to the game object it retains the same reference to the cloned material mat ( but it should be impossible as im destroying it onEnable )

#

which isn't the case as the names are different :

#

...

to simplify : my question is , when writing a material property something like

mat.SetVector("ComposeRow0", row0 );

during edit mode , why does it effect every single cloned instance based on the original and how to avoid it * ?

opaque zenith
opaque zenith
#

treat the material like you would a models prefab

tough cairn
opaque zenith
tough cairn
#

that's what i did

opaque zenith
# tough cairn ^

so, I'm not actually 100% sure on this, but, figured I'd see if you want to try it. in your render.material = new Material(original); try changing the original to be a shader instead of a material. So, something like render.material = new Material(Shader.Find("MyShader"));

tough cairn
#

good idea

opaque zenith
#

just realized you are copying based off a material, I do all my copying based off a shader

tough cairn
gloomy chasm
#

If you want the actual shader graph then you have to use the AssetDatabase.

tough cairn
#

kk

gloomy chasm
#

All it is is a json file with a shader as a subasset.

opaque zenith
#

Also, and this is important depending on what you are doing

#
Note that a shader might be not included into the player build if nothing references it! In that case, Shader.Find will work only in the editor, and will result in pink "missing shader" materials in the player build. Because of that, it is advisable to use shader references instead of finding them by name. To make sure a shader is included into the game build, do either of: 1) reference it from some of the materials used in your Scene, 2) add it under "Always Included Shaders" list in ProjectSettings/Graphics or 3) put shader or something that references it (e.g. a Material) into a "Resources" folder.
#

IDK what a shader graph is, I've only used surface shaders, sorry 😦

gloomy chasm
opaque zenith
gloomy chasm
opaque zenith
#

No offense, but, this isn't an editor extension question, and is quite literally probably the basics of script/class naming convention in Unity. Have you done any tutorials?

burnt locust
#

och sorry

opaque zenith
burnt locust
#

o thx

real meadow
#

So given this code, Unity just tells me that Creating the asset failed at the given location. But it doesn't tell me anything about why it failed. What could be possible causes?

private void SaveAs()
{
    string path = EditorUtility.SaveFilePanel("Save DialogueChain", "", "NewDialogueChain.asset", "DialogueChain");
    if (path.Length != 0)
    {
        DialogueChain chain = CreateInstance<DialogueChain>();
        chain.Nodes = _nodes;
        AssetDatabase.CreateAsset(chain, path);
        _instanceId = AssetDatabase.LoadAssetAtPath<DialogueChain>(path).GetInstanceID();
    }
}
opaque zenith
real meadow
#

I just checked out an example on the Unity API docs

#

I want to give the user of the editor control over where an asset file is saved

#

So I just searched how to call up the save dialogue and went from there

opaque zenith
#

if that is what you want?

#

well, regardless, not relevent to your question, let me look more.

real meadow
#

The flow is pretty straight forward.
Use my custom editor to make a thing that can be stored as an .asset file.
Click the Save Button.
Choose where to save the asset.

opaque zenith
real meadow
#

Hm, let me see.

#

Oh I think I see the issue. It's not that the path is invalid.

#

It's that the resulting file has an invalid name

#

I didn't quite understand how the dialogue work it seems.

#

.../Assets/Data/NewDialogueChain.asset.DialogueChain

#

And now it complains about not using a relative path

#

Aight

#

Well that makes this something I can continue with. Thanks @opaque zenith

opaque zenith
real meadow
#

StreamWriter could be an option yes, though I was thinking that since CreateAsset() exists and it just needs a path, then it would likely be some easy work done for me to just ask Unity to make the asset for me at the specified path

opaque zenith
real meadow
#

But why?

#

I still need to ask where the user wants to save the file so

#

how else would I obtain that path?

opaque zenith
#

and then just a path string with whatever you want in it if you want to use it multiple time, or in this case, something like string path = "assets/Folder/NewDialogueChain.asset"

real meadow
#

But that's a static path

#

the user needs to be able to tell the editor where they want to save the file

#

How would I do that without the savefile dialog?

real meadow
#

They do the same thing?

opaque zenith
#

well, to be more precise how I CURRENTLY have it

#

is I use and object field for default assets

real meadow
#

You are describing a use-case that isn't mine

opaque zenith
#

yeah

real meadow
#

I need to be able to make a lot of these objects as they are used for dialogues. It's a node editor.

#

The OpenFolderPanel and SaveFilePanel appears to largely do the exact same thing

opaque zenith
# real meadow I need to be able to make a lot of these objects as they are used for dialogues....

but basically the way I did it (which is probably easier ways, most my ways are convoluted from lack of experience) but, I have a text field that the user can enter to has a validation check for if a valid path so if the user wants to type in it, but, also an object field where they can select a folder path. I then use AssetDatabase to get the asset path, and in the previous text field have that path displayed

real meadow
#

Why not just give them the native desktop saving dialogue?

#

That seems a lot more intuitive

#

Ease of use

opaque zenith
real meadow
#

Yeah I get that but, now you know better, hopefully

#

😛

opaque zenith
real meadow
#

I mean, no matter which OS you use there will be some type of popup that will be useful. Like a dialogue to let you choose where to save a file.

#

Unless you are using strictly commandline OS'ses but that's kind of pointless to this discussion

opaque zenith
#

EditorUtility.DisplayDialog has DialogOptOutDecisionType but not quite what I was looking for

gloomy chasm
# real meadow The OpenFolderPanel and SaveFilePanel appears to largely do the exact same thing

They are almost the same, the difference is that one you select a folder, and the other you set the name and folder location. Btw you are doing it all correctly using CreateAsset and such. I assume the problem was that it was a none relative path, yes? Did you get it working?
Also btw a 'better' way for checking a string is to use string.IsNullOrEmpty(path) since it handles if the string is null and also imo a bit clearer to read.

gloomy chasm
elfin cypress
#

Hello,

I'm trying to get into Editor Scripting for some tools development.

I came across a video which uses the new UI Toolkit, in the video they use the Unity Royale demo and create a custom "Card Creator" Tool.

I want to take a look at the code under the hood, but the demo does not seem to contain that section at all. Am I missing something?

https://youtu.be/mTjYA3gC1hA?t=321

In this video, we are walking you through the basics of creating Property Drawers and Editor Windows using UI Toolkit.

🌏 Check out our Docs to learn more about UI Toolkit:
https://on.unity.com/3kR2LC6

🌏 Learn more about Editor Scripting using IMGUI here:
https://on.unity.com/3oZ3oMq

🌏 Download Unity Royale here:
https://on.unity.com/3jXV9fX
...

▶ Play video
#
GitHub

This is a sample project to introduce the use of UI Toolkit in Runtime - GitHub - Unity-Technologies/UIToolkitUnityRoyaleRuntimeDemo: This is a sample project to introduce the use of UI Toolkit in ...

GitHub

Public release of the Unity Royale project. All of the assets are redistributable. - GitHub - ciro-unity/UnityRoyale-Public: Public release of the Unity Royale project. All of the assets are redist...

real meadow
#

Suggestions?

private void SaveAs()
{
    string path = EditorUtility.SaveFilePanel("Save DialogueChain", "Assets", "NewDialogueChain", "asset");
    if (path.Length != 0)
    {
        DialogueChain chain = CreateInstance<DialogueChain>();
        chain.Nodes = _nodes;
        chain.name = $"{path.Split('/').Last().Replace(".asset", "")}";
        path = $"{path.Substring(path.IndexOf("Assets"))}";
        AssetDatabase.CreateAsset(chain, path);
        _instanceId = AssetDatabase.LoadAssetAtPath<DialogueChain>(path).GetInstanceID();
    }
}
elfin cypress
gloomy chasm
gloomy chasm
elfin cypress
#

They are explicitly referenced in the video tho, and they exist in there too. Strange.

Anyways, is there any project you would recommend to get started with this kinda thing?

gloomy chasm
real meadow
#

I am never entirely sure with Instance IDs in Unity

#

they seem to change when I don't expect it

#

So thought I'd be on the safe side

#

At least, if the Load does work, then I know for sure that the Save worked?

#

😂

gloomy chasm
elfin cypress
opaque zenith
#

is there an event called resulting from the closing of an editor window after OnDestroy()?

opaque zenith
#

basically, resulting in doing something like

    protected static void ShowWindow()
    {
        window = Instantiate(instance);
        window.Show();
    }

to essentially do what I was looking for

supple willow
#

hey. any idea how to make this OnStart happen after each domain reload ?

supple willow
#

I ended up using [AlwaysExecute] and putting my method inside OnEnable()

gloomy chasm
supple willow
tough cairn
opaque zenith
# supple willow that doesnt work for non-static methods

look into a somewhat singleton pattern if you want to use InitializeOnLoadMethod or just make everything in that script static. ExecuteInEditMode is not only just editor, however, doesn't take prefab mode into account natively. Looks like you found your solution with ExecuteAlways which is great! Just make sure you have checks with Application.IsPlaying to help separate any logic you want different from editor and play mode

tough cairn
opaque zenith
# tough cairn why not make a static event and dispatch it `OnDestroy()` ?

When you close an EditorWindow there is an internal Close() that is called that calls a DestroyImmediate(). It was late when I was looking into this so about to delve back into it, but, that is something I'm looking into, however, I'm trying to figure out how I would approach how to handle the event. The DestroyImmediate() is the last thing to happen, so when OnDestroy() is called, the instances of the window still exists

tough cairn
#

not sure what you need, when you say something like window = Instantiate(instance);window.Show();

#

are you trying to capture after DestroyImmediate ? Why ?

opaque zenith
# tough cairn not sure what you need, when you say something like `window = Instantiate(instan...

I have an editor script that is my global editor manager script, I guess you could call it. I do different things with this manager script. So, when I want to display it as a window, I'm instantiating it to copy instances instead of creating a new one, then window.Show() to show it. I could simply use GetWindow but that doesn't solve my issue of wanting to maintain the reference rather than have it destroyimmediate when closed. Sorry for slow response, my daughter keeps requiring my attention while trying to respond

#

so basically I'm resulting in saving and copying, and wondering if there is a way to just cancel the destroyimmediate from .close. IDK if through something like Event.use or ExitGUI or something

#

like one approach I'm doing is EditorUtility.SetDirty(); in OnDestroy() but I'm not sure if that is the bestroute

opaque zenith
tough cairn
#

also i don't think making a global window manager is the best route for component based architecture - everything should be modular and as self reliant as possible ( at least that is my opinion ) - u could make a scriptable object that lives as an asset in your project and stores the editor window internal states and restores them on demand

tough cairn
opaque zenith
tough cairn
#

( im just guessing at this point )

opaque zenith
# tough cairn because it is already null ?

no, it isn't null till the very end, which is the problem I'm having. The error is because of

            // Guard against multiple call to Close in the same stack
            // (since we call DestroyImmediate at the end of Close()).
            if (!this)
                return;
tough cairn
#

line 312

opaque zenith
#

Maybe what I should be doing is rather than using the default .Show() and GetWindow() I instead should do something like PopupWindow

#

rather, EditorWindow.ShowPopup

tough cairn
#

¯_(ツ)_/¯

opaque zenith
supple willow
opaque zenith
opaque zenith
# tough cairn ¯\_(ツ)_/¯

I solved a lot of my problems just saving the data and just not caring if it persists or not since the first instance will always be off that

real ivy
#

Is there really no way for the default drawer to hide/show parts of struct/class based on condition?

opaque zenith
#

or get the struct, break it up and just doing normal EditorGUI things on the fields you want

real ivy
#

Im using polymorphic list for the different kinds of element type, but its getting kinda a hassle to maintain
Considering going a struct to hold all the possible values and only show based on some bool/enum
Is this worth the simplification?

#

Oh and can struct be a target for CustomEditor?

opaque zenith
#

dealing with .Next and .NextVisible was especially annoying

real ivy
#

Yeah i got it working already too. But now i wanted to add this same structure list to a list of.. basically something that i now want it to be the polymorphic list + a bit extra thing just for this part
And thinking of having to do a whole writing again just for this little "variant" makes me so cbf...

#

CustomInspector can be for non mono too, right?
This way i can make the custom once for this struct and put it in whatever else variant and itll do just that

opaque zenith
opaque zenith
#

so you have to build a custom one

#

and ones like the one I linked still rely on serializedProperty, but, yeah

#

There is other things to like EditorGUI.BeingProperty() you can make a wrapper with and stuff, but, I haven't found a great way I like personally of doing those things yet. ATM, I just just have a serializedProperty extension that spits the property into the type it is then picks it apart to display specific data, but, I haven't done anything for this outside of serializedProperties yet. TBH, I've been messing around in the editor for months and still kinda confused by serializedObject and serializedProperty do hehe.

real ivy
#

Its just data representation of what the editor keeps. Theres no way around not using it
Im building mine with ui toolkit and even with the provided BindProperty and such, i still occassionally look via serializedProperty

real ivy
opaque zenith
#

is there anything wrong with making editor windows with scriptable objects like I use scriptable objects in builds? Never really thought about using polymorphism with them for some reason

slim zinc
#

that's fine. not the usual use case.....but should still very much work

opaque zenith
real ivy
# opaque zenith is there anything wrong with making editor windows with scriptable objects like ...

I dont fully get this one. Like a editor window that displays all the SO, then the window displays the SO accordingly to the type?

My use case is, theres a main SO called ActiveSkill, and the subasset it holds are of various types like the targetting (unit/point/aim/self), the onFinishCast actions (damage/projectile/aoe/etc), each also got formula which has parts that pulls in stats or states of the caster/target

#

Or ur not referring to my case... But i wanna understand what u mean anyways

opaque zenith
real ivy
#

If its polymorphic then each subclass can override their own part, right. I just have a virtual void AppendInspector(VisualElement theContainerPassedByRootOnInspectorGui)
{theContainer.Add(someIntField) etc}

#

I guess this part is not the hassly part in my case..
Wait just woke up i forgot what was a hassle that i wanna change..

opaque zenith
gloomy chasm
#

@real ivy I skimmed the conversation. Maybe a PropertyDrawer is what you are wanting?

real ivy
gloomy chasm
#

By default the editor for components and ScriptableObjects use IMGUI so the UITK override will not work and you will need the IMGUI override.

real ivy
#

Whats the uitk override called?

gloomy chasm
#

It is the one with Create in it's name.

real ivy
#

Alright2 ill get to it when i get out of bed

#

Thanks a lot. Feels a lot more ready to tackle this big sphagetti monster

gloomy chasm
#

Alright, good luck!

real ivy
# opaque zenith yes, but you have the option to call ``base`` to essentially save time basically...

Yep got that. Is this what ure gonna do or already doing?

I guess my editor skill is still very narrow. Like i never knew propertydrawer works with uitk so i didnt bother learning it
The decision to have these sub SO part polymorphic is i think still correct. Its just the displaying them that i did it all in some "property drawer" done in the main SO class for a somewhat specific "location" in the total inspector spot. Something that's "only" for anAbcList on its own

This is why when i wanna have a variant of where this anAbcList to be (now inside struct Xyz), its such a hassle

#

Its so spaghetti that i should stop even trying to describe it. Ill get back after my progress..

opaque zenith
#

in terms of editor windows, it actually could be more work than it's worth depending on how you set up your polymorphism. Sometimes it's just easier to just inherit from editorwindow, do whateve you need, and call it a day

#

I'm trying to setup some things through EditorApplication.Update Selection.selectionChanged and SceneView.duringSceneGui that just will make it easier if I can have a base editorwindow for

#

which I already have through my generic way, but, for some reason I don't like the generic way and moving over, and what I mean is basically my public abstract class SingletonEditorWindow<T> : EditorWindow where T : SingletonEditorWindow <T> and changing it to just something like public abstract class BaseEditorWindow : EditorWindow and using asset menu to create a scriptableobject and put options and things onto that

real ivy
#

And.. propertydrawer can draw when called from inside CustomInspector right? Why do i have the impression that u only do one or the other?

gloomy chasm
#

By default a inspector just calls EditorGUILayout.PropertyField(..) for each SerializedProperty in the component.

real ivy
#

PropertyDrawer can't be for plain c# class?

My case is a nested list
List<NumberFormula>
class NumberFormula {List<MathEntity>}
abstract MathEntity : SO

Currently i'm drawing List<NumberFormula> as a whole with a Foldout CreateDamageFormula(List<NumberFormula>) kinda method that draws the whole thing wrapped in a Foldout, including the buttons to add/remove NumberFormula. And inside each NF, a button to remove MathEntity, or add (with dropdown to select concrete MathEntity type)

And then now i'm making another nested list
List<StatFormula> stats
class StatFormula {someVarA, someVarB, List<NumberFormula>}

PropertyDrawer can help me draw override SO class (altho this one i already did it with AppendVisualElement overrides that's called from CustomInspector)

I guess for this edge case, i just need to make another method that then calls CreateDamageFormula inside it. PropertyDrawer seems not very relevant anymore in my case
I was hoping i can do

pf = new PropertyField();
pf.BindProperty(statsProp)```
And define the custom PropertyDrawer on `StatFormula` and so can define the buttons etc, but StatFormula is plain c#..
visual stag
#

Property fields works on plain classes just fine. In fact... that's one of the main uses cases for it.

#

Your description is very over complicated so I cannot really speak to the problem though

real ivy
#

Ahaha yea. Well somewhere in there i described my plan and that works just fine, so.. solved!

#

Well hold up
I guess my real question is: can PropertyDrawer be used for List<SomeClass>, as a "bundle" ?

waxen sandal
#

You can't make your own property drawer for a list, if that's what you're asking

opaque zenith
# real ivy Well hold up I guess my real question is: can PropertyDrawer be used for List<So...

I'll give you an example from catlikecoding. You make a class that is serialized, it has a field for vector3 and color that are both serialized. In the propertydrawer you say this is how I want that vector3 and color to be displayed if someone uses it Now, whenever anyone uses that class, it will be displayed as such in the inspector. If someone puts that class into a serialized array (array or list) *(there is more to this, but, irrelevant for this) unity will use their default EditorGUILayout.PropertyField to display the array while the elements will be display with the propertydrawer of those elements. This can actually be kinda wonky depending on how you have your propertydrawer setup, but, irrelevant atm so lets just assume the propertydrawer is setup fine.

Anyways, so, what you do here is either create an extension, which referring back to catlikecoding, they actually have a tutorial that shows how to use propertydrawer that goes into a custom list right after, or just do it in the editor script you want, you get the Serialized Property for the array, and break it up, and display/add other GUI features you want into it.

#

For example, based off their extension example, you do EditorList.Show(SerializedProperty) and if it is an array it will use the custom list

real ivy
#

Yeah just read thru the catlike and i'm already doing the same thing (at least until the buttons)
I'm currently building it thru CustomInspector, so it does the job including drawing all the List<NF> as a bundle with buttons etc
PropertyDrawer will make my code cleaner tho, maybe, but i'm skipping it bcoz i'm already drawing them all in CustomInspector (and this main SO will ever be the only place all this matters)

opaque zenith
real ivy
somber zinc
#

I want to get the current folder a scriptable object is in (from that scriptable object) and retrieve a bunch of scriptable objects but am Unsure where to start, can anyone give me a method or something I'd require to do this

#

I've figured out how to get the string asset path, but I am unsure on what to do from there to get assets from that path

somber zinc
#

I've been tryna use LoadAllAssetsAtPath, but it returns nothing despite the path being correct

#
void Autofill()
    {
        string assetPath = UnityEditor.AssetDatabase.GetAssetPath(GetInstanceID());
        
        string[] splitAssetPath = assetPath.Split('/');
        StringBuilder strBuilder = new StringBuilder();
        for (int i = 0; i < splitAssetPath.Length - 1; i++)
        {
            strBuilder.Append(splitAssetPath[i] + "/");
        }

        Debug.Log(strBuilder.ToString());

        Object[] assets = UnityEditor.AssetDatabase.LoadAllAssetsAtPath(strBuilder.ToString());

        List<Wave> waves = new List<Wave>();

        foreach(object obj in assets)
        {
            Debug.Log(obj.GetType().Name);
            if(obj is Wave wave)
            {
                waves.Add(wave);
            }
        }

        Waves = waves;
    }
gloomy chasm
gloomy chasm
somber zinc
#
string[] assetLocations = UnityEditor.AssetDatabase.FindAssets(strBuilder.ToString());
        List<Wave> waves = new List<Wave>();

        foreach(string str in assetLocations)
        {
            waves.Add(UnityEditor.AssetDatabase.LoadAssetAtPath<Wave>(str));
        }
        

tried this but it doesn't work either

#

Did I misunderstand?

#

@gloomy chasm

gloomy chasm
somber zinc
#

How can I use that GUID to get the asset?

gloomy chasm
somber zinc
#

Problem is string[] assetLocations = UnityEditor.AssetDatabase.FindAssets(strBuilder.ToString()); is returning 0

#

items

#

The path is Assets/t/

#

which is current

#

currect*

#

CORRECT*

gloomy chasm
#

Sorry, I guess ya need to give it a second argument.

somber zinc
#

ah, the path is the second one

gloomy chasm
#

I think just using System.IO will be cleaner to read and I think more performant, but maybe not.

somber zinc
#

Perhaps it doesn't want Assets/

#

nope

gloomy chasm
#

Show code pls

somber zinc
#
string assetPath = UnityEditor.AssetDatabase.GetAssetPath(GetInstanceID());
        
        string[] splitAssetPath = assetPath.Split('/');
        StringBuilder strBuilder = new StringBuilder();
        for (int i = 0; i < splitAssetPath.Length - 1; i++)
        {
            strBuilder.Append(splitAssetPath[i] + "/");
        

        string[] assetLocations = UnityEditor.AssetDatabase.FindAssets("", new string[] { strBuilder.ToString() });
        Debug.Log(assetLocations.Length);
        List<Wave> waves = new List<Wave>();

        foreach(string str in assetLocations)
        {
            waves.Add(UnityEditor.AssetDatabase.LoadAssetAtPath<Wave>(UnityEditor.AssetDatabase.GUIDToAssetPath(str)));
            Debug.Log(UnityEditor.AssetDatabase.LoadAssetAtPath<Wave>(UnityEditor.AssetDatabase.GUIDToAssetPath(str)).name);
        }
gloomy chasm
#

Gotta remove the ending /

somber zinc
real ivy
#

There's something i still dont understand about the new UITK
The last thing i did was

FloatField simpleValue = new FloatField("Value");
simpleValue.SetValueWithoutNotify(number.simpleValue);
simpleValue.RegisterValueChangedCallback((f) =>
{
  number.simpleValue = f.newValue;
});```
Number is just a serializable c# class

As shown there, there is no BindProperty, no setting floatValue to serializedProperty, no ApplyModifiedProperties, SetDirty, SaveAssets, Refresh, etc whatsoever
But this... works. Restarted editor, went into play mode n back, the value survives all that

Looking at my past codes and they're all using Bind and ApplyModifiedProperty and whatnot bcoz i guess, either i couldnt make it persist, setting the value on the actual object itself, or i actually didn't think of just trying it out
gloomy chasm
real ivy
#

But if this is just for SO editing static data, it works fine?

gloomy chasm
#

Definitely not my recommended way to do it at all.

real ivy
#

So maybe SetDirty is the only thing i really need here

gloomy chasm
#

No

real ivy
#

Yeah, i'm just surprised it persists

gloomy chasm
#

tbh I am too. Maybe something else is setting it dirty?

#

SetDirty wouldn't fix the saving problem. All that does is tell Unity that any given asset/object needs to be saved. And when Unity quits properly, it auto saves.

real ivy
#

And yea i'm still (pleasantly) surprised. Still checking these 3 things after any close open play whatever and they're still reliably there

gloomy chasm
real ivy
#

Oh right ok

#

Oooh yea i got mixed up for a scene change

real ivy
#

Is it possible to move this toggle to snap to the right?
I tried setting any flex to FlexEnd and it doesn't change anything
The parent VE flex-direction is set to Row. Only if it's set to Column then this toggle snaps to the right, but then it'll be on a new line..

gloomy chasm
#

Worst case ya just add a label.

real ivy
#

Oh, setting the "Stat Number" label to flex-grow 1 actually pushes the toggle all the way to right, so this works

gloomy chasm
#

Oh, well glad you got it working.
(I miss-read what you said anyway)

inland agate
#

where can I find a good visual basic dark theme?

#

I have checked the market place and found one dark pro

#

but I want another one

#

any idea?

gloomy chasm
inland agate
#

I use visual basic for unity

real ivy
#

Hi all

I'm in the process of changing some data structure, and cant seem to properly "port over" existing data to the new structure

So in my SO i used to have say
List<NF> duration
It's already got several NF data and all is good

Then i wanna stop storing it as List and instead in another class:
class Number{public List<NF> formula}
Then i make a new variable instead of replacing the existing duration
public Number durationNew = new Number();

So i did this in OnValidate:
durationNew.formula = duration;
And all is good, the data reference carried over

And then... what?
I got rid of the old duration, then compiled, and durationNew.formula still holds the data. Cool
Then.. i wanna rename durationNew to duration
I did, and compiled, and the data reference are gone

I guess i can use FormerlySerializedAs?
But what if i really wanna rename and not use that attribute?

#

Ah i guess i can trigger the OnValidate 2x. First from old duration to durationNew, then change duration to Number, then do from durationNew to duration

gloomy chasm
real ivy
#

Aah u can do that..
Well i'll remember next time
My way is like 1 step longer..

opaque zenith
#

At least if I understand structs correctly. I don't actually use them a lot since I'm scared of not using them correctly

real ivy
#

Oh yea im using class

#

Struct in editor as data holder, holding reference, remains tho

opaque zenith
#

sorry for dumb question, but, just to make sure I understand correctly (ignoring the order of execution) a static class does NOT need [InitializeOnLoad] and the constructor is automatically called on domain reload, but, methods in it would either need to be called through the constructor or with [InitializeOnLoadMethod]. A non static class with a static constructor needs [InitializeOnLoad] or a static method with [InitializeOnLoadMethod]?

gloomy chasm
#
  1. [InitializeOnLoadMethod] acts the same as [InitializeOnLoad] but class the method it is on instead of the static constructor of a class.
opaque zenith
#

getting more into UITK. This UITK Builder is so fun

#

I'm not sure how to best organize things yet though. I have a StyleSheet and UXML just called Editor and Runtime atm

#

Is there a way to make the canvas size in UITK match the sceneview?

storm trout
#

Guys what would be the best method to run an editor window in the background of my game

#

basically

#

the user opens the window then closes it

#

but i want the winow to be consistently running events if it is open or closed

coral timber
#

Hey guys I've just downloaded unity on a computer in a closed network (no internet access)
And I got this error Failed to find csc.exe in the console
Anyone knows a solution

waxen sandal
#

Your install is corrupt

keen pumice
#

I’m using EdiotrGUI.PropertyField to draw a List in my custom property drawer. Why do I get a different output in my custom drawer than when disable it (remark out [CustomPropertyDrawer] attribute), and just let it use the default property drawer? Am I calling EditorGUI.PropertyField improperly, somehow?

opaque zenith
#

also, CustomPropertyDrawer doesn't, well shouldn't, be using Layout

#

so you have to do things like the indentation yourself

keen pumice
#

🍒 that "children" thing was it! thank you sir!

opaque zenith
keen pumice
#

EditorGUI.PropertyField(position, fieldsAndControlsProperty,true); <- that's all I had to do- always forget about that darn param- thanks again bud

opaque zenith
keen pumice
#

kinda lost me at the last post there.. shouldn't the property drawer of the serializedProperty itself handle the drawing when the serializedProperty.isExpanded?

opaque zenith
vapid prism
#

Hi, In a PropertyDrawer I'm using GUI.skin.label.CalcSize to get the width for some text, however this text gets cut off in the middle, suggesting that the value returned has too small width. I feel like I'm missing something here? I've tried grabbing the label from EditorStyles as well but that is even shorter? rect is the Rect argument in OnGUI.
Here's relevant code & image:

var itemLabelContent = new GUIContent("Item");
var itemLabelSize = GUI.skin.label.CalcSize(itemLabelContent);

var itemLabelRect = new Rect(rect.x, rect.y, itemLabelSize.x, rect.height);
var itemRect = new Rect(rect.x + itemLabelSize.x, rect.y, rect.width * 0.5f - itemLabelSize.x, rect.height);

var itemWidth = itemLabelRect.width + itemRect.width;

EditorGUI.LabelField(itemLabelRect, itemLabelContent);
EditorGUI.PropertyField(itemRect, itemProperty, GUIContent.none);
waxen sandal
#

Why not use the propertyfield with the label param

opaque zenith
vapid prism
opaque zenith
#

what that is doing is cutting off the size you provide for the Item label

#

so if you were to remove the indentlevel, for example, you would see item just fine

vapid prism
#

Actually, outlining my allowed rect seem to indicate that my label starts drawing a bit offset to the right, as if the label is offset x-pixels. I think this is where the issue is but I'm not sure what is causing it
Blue here is my calculated Label's rect

waxen sandal
#

Pretty sure it's indent

vapid prism
#

So yeah it seems to be indentation that's screwing with me

opaque zenith
#

lol

vapid prism
#

I am not

opaque zenith
#

try doing this, hold on

#
// at beginning of property drawer
int oldIndentLevel = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
// at end of property drawer
EditorGUI.indentLevel = oldIndentLevel;
#

you can also do something like this to check

contentPosition = EditorGUI.IndentedRect(position);
#

outside of that, make your field more precise. The width you have for it could be much larger with rect.width * 0.5f - itemLabelSize.x, than you are expecting possibly

waxen sandal
#

IndentedRect will assume that it's drawing in the whole row and subtract the amount it moved it by

#

So you need to change it yourself

vapid prism
opaque zenith
vapid prism
#

Yeah, got it to work as expected now 😃

#

So to summarize if someone else runs in to this problem; my issue was that I was calculating all rects etc with indentation set and also drawing with indentation. So simply resetting indentation before doing the actual drawing fixes the issue. I also fix my provided rect to be indented at the start with rect = EditorGUI.IndentedRect(rect);

lethal sonnet
#

hello everyone, my project keeps crashing with the same error:
Got a SIGSEGV while executing native code.

opaque zenith
#

UITK makes turning fields into serialized properties so much easier

visual stag
#

How so? Maybe I'm confused as to what you mean, but both have PropertyDrawer

opaque zenith
#

well, I have visualElement.Add(new PropertyField(){bindingPath = nameof(selectedObject)}); also

visual stag
#

I don't really see the difficulty in imgui

opaque zenith
visual stag
lethal sonnet
#

@visual stag could you tell me who can help me with the crash unity?

visual stag
#

Nobody can help. This is a community server

#

This channel is for authoring extensions for the editor. You should ask in #💻┃unity-talk if anything

lethal sonnet
#

ok thanks

lethal sonnet
shut zenith
#

Hey everyone. I'm trying to draw a hex grid using handles - it works but it runs very slow. Seconds-per-frame slow. I suspect I might be doing something wrong regarding drawing the handles, or maybe handles are too expensive and not a good way to draw a grid. Here's my code: https://paste.ofcode.org/3bqSNdtSKvWbR75U8GMAxfC

#

Maybe how the HexagonalGrid class is instanced in the EditorWindow?

#

Ok - I just updated the properties in my EditorWindow and it drew the new grid on top of the old grid. So I'm definitely doing something wrong.

#

Nevermind. I restarted Unity and it runs smoothly now - no FPS loss unless I make the gridSize more than 50

#

It seems the grid is sticking around after assembly reloads

visual stag
#

I reported a bug that OnDisable wasn't being called for an Editor not long ago, so I'm not sure if that was a more general problem

shut zenith
#

Ok I got it working. OnDisable is called for the EditorWindow but not for Editor object instances created in the EditorWindow class. In my case the HexMapEditor class's OnDisable was called, but not HexagonalGrid's. I fixed it by calling all of the instanced object's OnDisable code as a public method from within the EditorWindow class.

visual stag
#

Seeing as Editor is a ScriptableObject if you are instancing it you need to Destroy it when you are done

#

But if you're not actually using any features of Editor or ScriptableObject, just make it a normal class and call Enable and Disable methods of your own.

shut zenith
#

I thought of that but then I cant make a SerializedObject out of it

#

And therefore no SerializedProperties either.

visual stag
#

I'm honestly confused why you're doing that, you're not using the editor outside of this window

shut zenith
#

Does that only really help with Undo? If so maybe I can handle the undo cases myself

visual stag
#

Just serialize the values in the EditorWindow imo

#

If you make HexagonalGrid a normal serializable class you can just serialize that into the window

shut zenith
#

I was under the impression that using the Serialized Property fields was considered best practice - it's in much of the example code in the documentation. Honestly though from a code organization perspective it would be nice to not have to manage two versions of every single field. Especially as I continue to add more functionality to my tool

#

I can't remember the reason it was listed as best practice but I'm pretty sure it has something to do with setting the scene dirty and undo

#

But like you said I'd much rather just make the class serializable and the fields I want in that class serializable as well.

real ivy
#

Hi so i have my enum StatType, some are like so:
AtkMelee, AtkMeleePercent
ArmorPhysical, ArmorMagical, etc

I wanna make an enum/popup that takes these enum but inserts a "/" in the PascalCase string, so the popup will categorize them
I guess i have to parse PascalCase then .Replace("/","") myself?

Just asking if there's something similar built in, or know of some gist i can just copaste

#

Ok so i found ObjectNames.NicifyVariableName maybe can start with that

#

Coool. So neat now

lilac python
#

Hi, I recall there is a way to get a persistent identifier for a scene object like a GUID, but can't find it will trying to search for it.

#

What I'm trying to solve is a tool to search through a bunch of scenes and store a way to select them if I open up the scene again.

real ivy
#

Hi i'm trying to make property drawer for a NON UITK custom editor (just for in default inspector)
It seems like it doesnt work?

It seems i have to use OnGUI for custom property drawer in default inspector?

visual stag
#

What do you mean? If it's a non-UITK editor it uses OnInspectorGUI

#

If you're making an IMGUI property drawer it uses PropertyDrawer's OnGUI

real ivy
visual stag
#

Post your code

real ivy
#
    public override VisualElement CreatePropertyGUI(SerializedProperty property)
    {
        // Create property container element.
        var container = new VisualElement();
        
        // assume that property.enumValueIndex is enum's int value. not index of order of the enum indexing
        PopupField<StatType> statPopup = Utils.MakeEnumPopup((StatType)property.enumValueIndex, (t) =>
            {
               //Debug.Log("Selected add: " + t.newValue);
               property.enumValueIndex = (int)t.newValue;
               EditorUtility.SetDirty(property.objectReferenceValue);
            });

        container.Add(statPopup);
        return container;
    }```
#

Utils.MakeEnumPopup is just a method to make the popup. It works in anywhere in my other custom editor UITK

visual stag
#

So you're drawing in an IMGUI editor?

real ivy
#

Yes.. i think? Default inspector for SO without custom editor is... IMGUI right?

visual stag
#

Yes

#

Then you need to use an IMGUI property drawer.

real ivy
#

So default is not UITK?

visual stag
#

UITK cannot be embedded in IMGUI

#

The default is IMGUI

real ivy
#

Omg yea why did i think otherwise..

real ivy
#

Hi all, i'm getting a type is not a enum value
Am i right to be using property.enumValueIndex?


        StatType currentSelected = Utils.statsAll[statProp.enumValueIndex];
        Debug.Log("Cur enum value index: " + statProp.enumValueIndex);

        Func<StatType, string> format = s =>
        {
            var regex = new Regex(Regex.Escape(" "));
            var newStatTypeext = regex.Replace(ObjectNames.NicifyVariableName(s.ToString()), "/", 1);
            return newStatTypeext;
        };

        int result = EditorGUI.Popup(amountRect, "Stat", statProp.enumValueIndex, Utils.statsAll.Select(format).ToArray());
        
        property.enumValueIndex = result;```
#

This line

        Debug.Log(result);
        property.enumValueIndex = result;```
Result is 2, which is totally a valid index in the enum
But it throws that error..
waxen sandal
#

Try int value

real ivy
#

type is not a supported int value
I'm now just doing this property.intValue = 1;// result;

#

So 1 is not supported it seems..

#

Omg wait

#

Sorry, it was a stupid mistake
I should be using "statProp" instead of "property"..

But now the popup is still not drawing

waxen sandal
#

🤦

real ivy
#

Why cant i draw a single damn popup field? This thing is not clickable and i'm not sure what those excess boxes are...

#
        var nameRect = new Rect(position.x, position.y, 40, position.height);
        var statRect = new Rect(position.x + 40, position.y, 40, position.height);
        var valueRect = new Rect(position.x + 100, position.y, 60, position.height);```
Code is really similar from the docs
#

The floatfield is editable tho

visual stag
#

If you're drawing a really thin element with a label it usually comes out wrong

#

you should pass GUIContent.none into the label field if you're drawing something small

#

and manually draw the label with another call if you still want it

real ivy
#

Are they thin tho? 40 width and using position.height
They're displayed with reasonable rect size but positioning wise it's wrong
The "NumNum:0" on the left is... i dont know where that's from actually

Before i started making this drawer, i'm using the "first string of a serialized class is what the default inspector uses to display the entry in a list", and "NumNum: 0" is what the string is
But why is it still being drawn even when nothing in the custom property drawer is drawing it?

visual stag
#

40 width sounds tiny

#

if you're drawing an element with a label the label will crush it to death

real ivy
#

Ooooo like that. The width is already shared with the label

#

Ok yea i got it working, at least the popup is clickable

But the left "NumNum: 0" is still a mystery. How is that "immune" to custom prop drawer?

#

But whatever, my fields are clickable so it's functional now

opaque zenith
visual stag
#

That they made the default (presents first) editor docs all UITK before they even had parity was rather irritating

#

It's still a mess in that regard

opaque zenith
# visual stag It's still a mess in that regard

Is it worth putting in reports of documents that seem like a "mess" when coming across them? I came across some recently that I just put off as probably already known, so didn't waste my time as to not be spam basically

visual stag
#

I have no idea. I only report stuff that's unclear or incorrect. The UITK/IMGUI editor stuff... it's just a lot to explain

opaque zenith
#

Does anyone know how to disable EditorApplication.Beep? I have some movement controls in interactiveGUI that makes it go nuts

#

I'll try using Event.Use I guess

opaque zenith
#

That works fine, but, if someone has an explanation of why, please let me know? All I'm assuming is while I'm using input the beeping is happening from a GUIEvent trying to accept that input for something else and EventType.used is preventing it

gloomy chasm
#

If so then when you use a event you need to Use() the event.

opaque zenith
gloomy chasm
#

Also iirc when you use a mouse down you also need to use the mouse up and vise versa.

opaque zenith
tough cairn
#

did u make it ? my list keeps growing >_<

gloomy chasm
tough cairn
gloomy chasm
tough cairn
#
[NativeHeader("Editor/Src/MenuController.h")]public sealed class Menu
gloomy chasm
#

(Oh yeah I also remember the other reason I hadn't yet, I realized that they completely rewrote the internals of the menu in 2021.2...)

gloomy chasm
tough cairn
#

im on that version

#

did they change it to another class rather then Menu ?

gloomy chasm
#

No, it is just that they completely rewrote how it works internally. The way the function is basically completely different.

tough cairn
#

oh ... i get it now

gloomy chasm
#

So I would need to make two separate systems basically for the same thing. The new system is much better and works properly, the old/current system is rather limited and doesn't always seem to work.

gloomy chasm
tough cairn
#

just do what u need for your needs , if u make it FOSS others will adapt

tough cairn
#

https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/Menu.bindings.cs#L38

#

this is 2019

gloomy chasm
# tough cairn yes.

Ah, yeah. I just use dnSpy now. Github hasn't updated since 2020.1 I think it is.

tough cairn
#

ah i c now , https://github.com/Unity-Technologies/UnityCsReference/blob/2020.2/Editor/Mono/Menu.bindings.cs

#

this is the latest branch

#

but still not 21

gloomy chasm
gloomy chasm
gloomy chasm
tough cairn
gloomy chasm
tough cairn
#

do u know which dll holds the editor classes ?

gloomy chasm
tough cairn
#

ah found it Editor\Data\Managed

tough cairn
#

but rather the window toolbar

tough cairn
gloomy chasm
tough cairn
#

or do i just modify anything under Assets/... and it will auto fetch it into the context

#

i do see the similarity , gonna try that

#

@gloomy chasm im not sure its possible to edit them without losing the Action bind

#

there is the add method

#

but nothing returns the callback for the current path

#

but it might still be possible to just disable alot of clutter i don't use 🤔

gloomy chasm
#

I don't remember now, but there is a way.

tough cairn
#

although MenuUtils has this beefy method

gloomy chasm
gloomy chasm
#

It uses the Menu to add items.

tough cairn
#

but there isn't a straight forward way for getting a command index from path

tough cairn
#

@gloomy chasm well i made this simplified thing that deletes items and it works ok but it loses any changes after assembly reload >_<

#

anyhow if u end up making your thing give me a ping , i'd like to check it out

gloomy chasm
tough cairn
#

want my code from above ?

#

i can drop it into a gist

gloomy chasm
#

Couldn't hurt.

shut zenith
#

I have a general question for everyone - how do you all go about structuring your scripts around an editor window to work with Unity's serialization? Is there a neat and organized way to do it without one giant monolithic editor window class?

gloomy chasm
tough cairn
shut zenith
#

I'm working on a project with one single editor window that has lots of different functionality. I started making individual classes for each function but to get each field from each class into my editorwindow Serialized and displayed properly is proving very difficult

gloomy chasm
tough cairn
#

i mean u can make 20 classes inside a single file 😛

#

not that i would recommend if you like to preserve you sanity that is , but i sometimes don't mind )

gloomy chasm
gloomy chasm
tough cairn
#

whahaha

gloomy chasm
tough cairn
gloomy chasm
tough cairn
#

i mean if the class has multiple fields

#

would it draw them all in a single call ?

#

i.e : my class Klacc()has A, B and C and calling EditorGUILayout.PropertyField( klass ) would draw 3 fields ?

gloomy chasm
#

Of course.

shut zenith
#

So I have a separate class that does the function I need and it does it well. It has five fields, all of which I want to include in my editor window. First I have to instantiate the class, then pull in data from all the fields (which means I have to make them all public). Plus since I'm not using SerializedObjects and SerializedProperties, I have to handle Undo and make things dirty myself. I can make my function class inherit from ScriptableObject and then use SerializedObject on it which works - but now I'm duplicating fields everywhere. It all just feels messy.

tough cairn
#

in a single call ? - if so that's amazing

shut zenith
gloomy chasm
gloomy chasm
shut zenith
#

Yes I've done that with my EditorWindow but it doesn't have the fields I need

#

Unless I'm content with the default foldout menu it creates

gloomy chasm
shut zenith
#

Yes

#

Ideally I'd like them to be in the other class as private fields

#

SerializedFields of course

#

All of this other stuff works but it doesn't feel clean

gloomy chasm
# shut zenith Yes

Then you just do windowSerializedObject.FindProperty("otherClassField").FindReletiveProperty("theFieldYouWant");

shut zenith
#

I just spent an hour digging through documentation and never found Find RelativeProperty

#

I think that's exactly what I need actually. Thank you

gloomy chasm
# shut zenith That sounds good

You can also do windowSerializedObject.FindProperty("otherClassField.theFieldYouWant") (Works with FindReletiveProperty(..) too)

tough cairn
#

👀 didn't know that ^

shut zenith
#

And that even works if the field is a private SerializedField?

gloomy chasm
shut zenith
#

They are

#

That was one of things I didn't want to do lol

#

I think I can also set up events from my EditorWindow for OnEnable and OnDisable too so that I can trigger each class to load and save EditorPrefs

#

Well, I guess I can just use a constructor for the OnEnable part

gloomy chasm
shut zenith
#

They save automatically?

tough cairn
#

save where ?

#

they will survive script recompilation

#

but not project reload

gloomy chasm
#
class MyWindow : EditorWindow
{
  [SerializeField] private int _myfield;
}
#

It saves on editor reload just like ScriptableObject assets do.

shut zenith
#

What about the private fields in my other classes

tough cairn
#

no?

gloomy chasm
#

Well if they are serialized of curse they will.

tough cairn
#

"serialized "

gloomy chasm
#

As long as the fields are serialized, and the class/struct has the Serializable attribute.

shut zenith
#

It wasn't working for me earlier - probably because I create a new instance of the function classes in OnEnable - I'll play around with it

gloomy chasm
shut zenith
#

Basically if I put 5 in the field, closed the EditorWIndow and reponed it, it would be reset to its default value

gloomy chasm
#

Yes

shut zenith
#

Yeah that's what I thought

gloomy chasm
#

Closing the EditorWindow destroys the window ScriptableObject.

tough cairn
#

^

#

he needs EditorPrefs

gloomy chasm
#

If he wants to save data when closing the window. There is also SessionState which lets you save data for just the unity editor session.

#

However if you are doing anything more than extremely simple data I recommend ScriptableSingleton.

shut zenith
#

EditorPrefs works fine I think

#

We're talking about ints and floats here

tough cairn
#

but whatever i did , it never could re-attach to the same cmd process ( after assembly reload )

gloomy chasm
#

Or more accurately are never serialized.

gloomy chasm
tough cairn
#

i think so ( iirc )

gloomy chasm
#

Well it isn't serializable

#

So, it would never survive reload, and never will.

tough cairn
#

oh well , its dead then

gloomy chasm
#

Unless you can find it again.

#

Maybe? Idk I never touched Process or anything like that until just last weekend 😛

tough cairn
#

back then i remember trying a lot of tricks and hacks but nothing seemed to work /

shut zenith
#

FYI I did have to load the property data to editor prefs using a custom event called from the Editor Window class. Apparently you can't use EditorPrefs.GetInt in a constructor.

#

So I just have OnEnable and OnDisable in my regular C# class, both called by events in my EditorWindow's respective methods. Seems to work great.

gloomy chasm
shut zenith
#

Yeah. Ideally if you set a handful of values, close the window and reopen it, those values should be right where you left them

#

Also assembly reloads seem to clear out data as well, EditorPrefs works nicely to preserve that

#

Also I have to subscribe and unsubscribe to SceneView.duringSceneGUI in at least one of my classes, likely more as I continue adding more functions

#

But calling so.FindProperty("classInstance.classField") works great. Thank you for that. That cleans up my code a lot

#

I thought I was going to end up declaring, updating, and applying modified properties to a dozen SerializedObjects. This is much better

gloomy chasm
shut zenith
#

I did consider that. I have it set up with tabs right now, which I quite like. Plus a lot of it needs to be done in sequence. It's an editor I'm setting up for myself to help me with a hextile strategy game I'm working on. This window will let me display a hex-shaped grid, set the size of the map and create it, and eventually place prefab tiles , objects, and units. But, for example, I don't want to be able to place prefabs until I've created the map base first. Some of it will involve terrain generation, placing roads/trees/rivers, etc. It's a big project.

#

But I ran into a problem making the game wherein making a map would take waaaay too long. It's going to be multiple levels/worlds, so I need something to speed up the process and also make it all saveable in the end.

shut zenith
wicked orbit
#

Having a weird issue with ObjectFields inside of an EditorWindow. For some reason, the dialogue to select an asset doesn't work, but dragging and dropping an asset does. Anyone know why this would be?

#

This is my code for this line - should work, right?

ReferencedConversation = EditorGUI.ObjectField( RelativeRect(new Vector2( 0, 30 ), new Vector2( 270, 40 ), padding ), ReferencedConversation, typeof(Conversation), false ) as Conversation;```
#

object type and what I'm trying to write to are both ScriptableObjects if that helps at all

real ivy
#

Can PropertyDrawer be not for a class, but an enum?
So anywhere i have the enum, whether in c# plain class or UE.Object, it'll draw it custom?

visual stag
#

Sure

real ivy
#

Super awesome. Trying it now real quick and mind about to be blown
I thought this is what Attributes are for but this is even better

visual stag
#

Attributes are for when you want to more generally apply a drawer to multiple types

real ivy
#

Awesome all working! And doesnt clash with the UITK part bcoz that's not using custom prop (UITK) anyways

waxen sandal
visual stag
#

Or if you need to pass some parameters per field

pseudo jasper
#

Is there a way to manually set the UUID of an asset in the database? I have a tool which generates assets, but each time I regenerate one it gets assigned a new UUID and so breaks references

#

(in my case, it's modifying animation assets to change the keyframes)

waxen sandal
#

Not really, you can manually edit the meta file but that's a bit tricky as well

#

Something like this

Match guidMatch = Regex.Match(metaText, "guid:.([A-Za-z0-9]{32})");
            if (guidMatch.Success && guidMatch.Groups.Count == 2)
            {
                string guidToAssetPath;
                string newGuid;
                do
                {
                    newGuid = AssetBundleVariantGenerator.RandomGUID(random); 
                    guidToAssetPath = AssetDatabase.GUIDToAssetPath(newGuid);
                } 
                while ( 
                    !guidToAssetPath.Equals(assetPath) &&
                    !string.IsNullOrWhiteSpace(guidToAssetPath) && 
                    !guidToAssetPath.Contains("__DELETED_GUID_Trash") );

                metaText = Regex.Replace(metaText, "guid:.([A-Za-z0-9]{32})", $"guid: {newGuid}");
            }```
pseudo jasper
#

thanks Navi, I worried that might be the only option! it seems prone to errors or breaking changes. Is there a way to reduce the asset to an empty container and then put something else in it?

waxen sandal
#

wdym?

#

You can just put a text field in it and serialize that

pseudo jasper
#

I mean for instance, if the original asset is an AnimationClip, and the updated one is also an AnimationClip - rather than create a new asset through the AssetDatabase, is it possible to do the equivalent of clearing the AnimationClip and then populating it with the new data, so it's still technically the same asset

#

My vague understanding is that some assets can be containers for multiple SOs

waxen sandal
#

I mean you can just modify the AnimationClip you have

pseudo jasper
#

My goal is to have a source asset and a modified version, and when someone clicks 'generate' it recreates the modified one from the source asset (but using the same UUID as any previously generated modified version, so it doesn't eg break references). Ideally I'd copy the source into modified and then run my process over that - it seems the easiest way to prevent any kind of error occuring on subsequent regeneration, because it only depends on the state of the source asset and not of the generated

#

(whereas modifying the generated asset could potentially lead to bugs where it depends on the state of a previously generated asset, e.g. say some field doesn't get reset correctly)

waxen sandal
#

Ah, subassets might be possible but they'll still get a unique id

tough stream
#

Hi! I've got a little conversion problem. I've got an array of Leaves (yeah, again :) ) on an object. On it's Editor script, i get those leaves on a serialized property. here's the script where i fetch the leaves:

ScenarioTree tree = (ScenarioTree)target;
            Leaves.ClearArray();//I clear the array of the sp
            Object[] o = AssetDatabase.LoadAllAssetsAtPath("Assets/Scenarios/" + tree.ScenarioTreeKeyID + "/Leaves/Leaves " + tree.ScenarioTreeKeyID + ".prefab");//I get all the leaves that are on the same object
            int count = 0;
            for (int i = 0; i < o.Length; i++) {
                if (o[i].GetType() == typeof(ScenarioLeaf)) {
                    count++;//I get the future length of the array
                }
            }
            ScenarioLeaf[] pLeaves = new ScenarioLeaf[count];
            for (int i = 0; i < o.Length; i++) {
                if (o[i].GetType() == typeof(ScenarioLeaf)) {
                    pLeaves[i] = (ScenarioLeaf)o[i];//I set the values on the array
                }
            }
            Leaves.objectReferenceValue = pLeaves;//Can't do that, i can't convert ScenarioLeaf[] to an object.

So two problems:

  • Can't i minimise the two foreach in one? I hate lists, i got told using arrays when you can is more efficient, so i tend to use them here too
  • How to set the Leaves SP?
visual stag
#

AssetDatabase.LoadAllAssetsAtPath("...").OfType<ScenarioLeaf>().FirstOrDefault(); is what I'd use

#

@tough stream

tough stream
#

oooh nice! what's first or default?

tough stream
#

effectively! okok
but i need the whole array though:

#
ScenarioTree tree = (ScenarioTree)target;
            Leaves.ClearArray();
            ScenarioLeaf[] pLeaves = AssetDatabase.LoadAllAssetsAtPath("Assets/Scenarios/" + tree.ScenarioTreeKeyID + "/Leaves/Leaves " + tree.ScenarioTreeKeyID + ".prefab").OfType<ScenarioLeaf>().ToArray();
            Leaves.objectReferenceValue = pLeaves;
            soTarget.ApplyModifiedProperties();```
#

cast still isn't possible though

#
if (GUILayout.Button("Fetch Leaves")) {
            ScenarioTree tree = (ScenarioTree)target;
            Leaves.ClearArray();
            ScenarioLeaf[] pLeaves = AssetDatabase.LoadAllAssetsAtPath("Assets/Scenarios/" + tree.ScenarioTreeKeyID + "/Leaves/Leaves " + tree.ScenarioTreeKeyID + ".prefab").OfType<ScenarioLeaf>().ToArray();
            Leaves.arraySize = pLeaves.Length;
            for (int i = 0; i < pLeaves.Length; i++) {
                Leaves.GetArrayElementAtIndex(i).objectReferenceValue = pLeaves[i];
            }
            soTarget.ApplyModifiedProperties();
        }```
i've done this, and it seem to work quite well! Do not hesitate to ping me if you have any workaround, i am hungry for knowledge
visual stag
#

That's what I'd do

#

No need to use ClearArray though if you're setting all the values afterwards though

knotty herald
#

posted in wrong channel originally - moved here.

Hi all, is it possible to make a custom UI inspector for a Scriptable Object or do they need to be a mono? My goal is to be able to define a list of Vector2 points and be able to see the result in the UI Inspector when editing the SO. My goal is to be able to see the objects in the editor. e.g. in my screenshot, we would just see a straight-line.

primal heron
#

@knotty herald I have done this on a SO using imgui by just having a customeditor class for the SO. then the GUI will appear if u inspect the SO asset in the project folder

knotty herald
#

This is all I have so far though; so no real element displaying - so I am definitely using it wrong

[CustomPropertyDrawer(typeof(TetrisShape))]
public class TetrisShapeDrawer: PropertyDrawer {
    public override VisualElement CreatePropertyGUI(SerializedProperty property)
    {
        // Create property container element.
        var container = new VisualElement();
        
        Debug.Log("CreatePropertyGUI called");
        return container;
    }
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
       Debug.Log("OnGUI called");
    }
}
primal heron
#

@knotty herald if it’s simple imgui is easier IMO but hard to do stuff like reorderable lists etc.

knotty herald
#

Ok thank you, I'll have to read up on imgui then

#

Do you know of any good resources out there otherwise I will just try the docs first

primal heron
#

@knotty herald I learned by trial and error but for an asset look at editorguilayout.

waxen sandal
#

You probably want an Editor instead of a property drawer