-
Notifications
You must be signed in to change notification settings - Fork 20
Editor GUI Fixes #15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Editor GUI Fixes #15
Conversation
Before changing a variable would not be detected and so not saved/serialized in some cases.
This would not work with the `upm-support` branch mcpiroman#14 as the attributes are not searched for in the attribute that these scripts are in by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: The attributes [NativeDllLoadedTrigger] etc are not searched for in the source code of this tool itself
Yeah, I just search for them in the same assemblies as for native function declarations. I guess I should just search every assembly and maybe exclude standard unity ones for perf, because searching in every assembly doesn't sound the quickest thing.
The scene is automatically set as dirty when the gui target is
Admittedly this should have been in mcpiroman#12. However, here are the fixes anyways. GUI buttons to un/load show in edit mode if enableInEditMode is true. Disabling and re-enabling the DllManipulatorScript works now.
Previously triggers would not be cleared properly and so be duplicated. (Static variables seem to persist between entering/exiting playmode)
Allow custom triggers to be executed on the main thread in a queue. We need this internally to repaint the editor GUI as it uses the Unity API.
@@ -46,7 +46,7 @@ private void OnEnable() | |||
{ | |||
if (EditorApplication.isPlaying) | |||
Destroy(gameObject); | |||
else | |||
else if(_singletonInstance != this) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Allows the user to properly toggle enabled in edit mode.
Ready for review @mcpiroman. You will probably want to review 39c4fce separately. (side note: #14 should already be compatible with these changes) |
Initialize() is not always called so we should not always reset.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry this took me this long to have a look at this.
I'm somewhat scared about that option cloning, comparing (mainly bout forgetting to update that), but (partly because I'm not quite in the problem it tries to solve), I don't see a better way.
scripts/Attributes.cs
Outdated
/// <summary> | ||
/// Should the method always be executed on the main thread, to allow use of the Unity API. | ||
/// Note: this means the method is not immediately executed but put in a queue. | ||
/// For consistent behaviour, the method is put in the queue even if it is triggered from the main thread. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just about the line 39 - I don't think this behavior is really beneficial, I imagine usually one would want main thread events to stay in order. And as of consistency, dispatching frameworks which I recall tend to invoke calls from target ("main") thread right away. For events though, while it doesn't prevent dead-locks as much as with direct calls, I think this also makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I've changed it. I wasn't quite sure either which is why I left it commented out:
https://github.com/rogerbarton/UnityNativeTool/blob/a0dc185babf73065dad5935be87e2de2f8d5811a/scripts/DllManipulator.cs#L547-L548
scripts/DllManipulator.cs
Outdated
|
||
// Execute now or queue to the main thread | ||
if (useMainThreadQueue /*&& Thread.CurrentThread.ManagedThreadId != _unityMainThreadId*/) | ||
_mainThreadTriggerQueue.Enqueue(new Tuple<MethodInfo, object[]>(methodInfo, args)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of using tuple to wrap arguments, it could be simpler to just store an Action
created with lambda, like so:
_mainThreadTriggerQueue.Enqueue(() => methodInfo.Invoke(null, args));
(You could also make e.g. Action<int>
to provide an argument at call side, JIC you didn't know).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes makes sense
scripts/DllManipulator.cs
Outdated
} | ||
else | ||
{ | ||
Debug.LogError($"Trigger method must either take no parameters or one parameter of type {nameof(NativeDll)}. Violation on method {method.Name} in {method.DeclaringType.FullName}"); | ||
Debug.LogError($"Trigger method must either take no parameters or one parameter of type {nameof(NativeDll)} or two of type {nameof(NativeDll)} and int. Violation on method {method.Name} in {method.DeclaringType.FullName}"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or two of type {nameof(NativeDll)} and int
at first reading this sounded like two NativeDll parameters and one int parameter, don't know if that's just me though.
Also why do you assume the main thread id information would be useful? And when it turns out to be, it should be documented somehow (or I just missed that, in which case I'm sorry)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've changed it to be clearer and given examples of the possible functions in the TriggerAttribute
doc.
The mainThreadId
can be used to tell if we are on the main thread and are allowed to call unity functions. I guess this is partially obsolete now that we have the MainThreadTriggerQueue
.
scripts/DllManipulator.cs
Outdated
/// Executes queued methods. | ||
/// Should be called from the main thread in Update. | ||
/// </summary> | ||
public static void InvokeMainThreadQueue() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't wanna be fussy, but I'd move the dispatcher stuff to DllManipulatorScript
, as it is closer to Unity, whilst this is intended to do 'the stuff', if you will.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume you only mean to move this function, not the queue itself
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean the queue itself. I don't quite imagine how would you move just this method, so that might be interesting too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean the queue itself. I don't quite imagine how you would move just the method, so I don't disagree with that now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By making the queue public (its static already)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, but no, I see this whole in the Script as it is the interface with Unity.
@@ -57,6 +57,10 @@ private void OnEnable() | |||
|
|||
if(EditorApplication.isPlaying || Options.enableInEditMode) | |||
Initialize(); | |||
|
|||
if(!EditorApplication.isPlaying && Options.enableInEditMode) | |||
EditorApplication.update += Update; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doens't just having [ExecuteInEditMode]
make the Update
be invoke in editor? Or do I misunderstand sth.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For ExecuteInEditMode
"Update is only called when something in the Scene changed" - Docs. So we need to manually add this to cover all cases.
[NativeDllAfterUnloadTrigger(UseMainThreadQueue = true)] | ||
public static void RepaintAll() | ||
{ | ||
RepaintAllEditors.Invoke(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's usually safer to handle null case with events (which can be done simply by putting ? before the dot). In this case you initialize the event, however I'm not sure if adding and removing an listener doesn't reset it back to null. Either or, it's better to be safe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed however as the event is initialized with the default delegate it will never be null. https://stackoverflow.com/q/170907/9295437
Ill add it anyways...
Also RegisterTriggerMethod receives attribute instead of bool, Fix naming in DllManipulatorOptions
Regarding cloning the Options, its just that we need a separate copy for detecting changes. This copy is never changed directly only update when changes are made. Its pretty safe in my opinion. I've actually found this quite a good solution. |
I'm fine with that, thanks! |
Note: The attributes
[NativeDllLoadedTrigger]
etc are not searched for in the source code of this tool itself. So by creating an.asmdef
in #14 these attributes may not work, do you maybe know of an easy fix for this @mcpiroman?.