why are plugin connected signal not working after saving? - plugins

I've created a plugin and it works fine when I open the project but as soon as I press ctrl + s to save the scene for the first time since opening, the buttons on the plugin (Close_btn in this case) stop working
tool
extends EditorPlugin
var Key_Btn=null;
var UI=load("res://addons/Plugin_Name/UI.tscn").instance();
func show_UI():
get_editor_interface().add_child(UI)
func close_UI():
if(get_editor_interface().has_node(UI.name)):
get_editor_interface().remove_child(UI);
func _enter_tree():
Key_Btn=Button.new();
Key_Btn.text=" Key ";
Key_Btn.flat=true;
add_control_to_container(CONTAINER_CANVAS_EDITOR_MENU,Key_Btn)
Key_Btn.connect("pressed",self,"show_UI")
func _exit_tree():
close_UI();
remove_control_from_container(CONTAINER_CANVAS_EDITOR_MENU,Key_Btn)
This is what the plugin button looks like:
The UI that pops up when you press the button:
How do I solve this?

I tried your code. I did modify the UI as I describe below. However, with your code, at no point the UI or the button to open it stopped working.
This is what I tried (closing and opening the project between tests):
Saving, then opening the UI. Then closing the UI and opening it again.
Opening the UI, then closing it, then saving, then opening it again.
Opening the UI, saving with the UI open, closing it, then opening it again.
I tested on Godot 3.3, 3.4,, 3.4.3 and 3.5 beta 1.
Since you have a Button called Transparent Background. I had it set to Full Rect, and set the alpha of its self_modulate to make it transparent. Consequently it won't let me interact with anything in the editor…
To be able to close the UI, I had to add a script to Control Main that looks like this:
tool
extends Control
func close():
if is_inside_tree():
get_parent().remove_child(self)
Don't forget to make a tool script.
And I connected the press signal from the Transparent Background and Close_btn to the close method I added.
An alternative would have been to emit a signal from the UI and on the EditorPlugin have it connected to close_UI… I didn't do that because I didn't want to change your code. And since it all worked with that code, I can say that issue for you is not that code.
Also be aware that you load an instance the UI scene on the initialization of your EditorPlugin. In consequence…
Some modifications to that scene won't be reflected on the EditorPlugin until you disable and enable it again, or load the project again.
And I say "some modifications", because you will see reflected the modifications to the resources it had when loaded. For example, I can modify the script I attached, or re-import texture, and so on. However, if I replace the resource with a new one, I will see the old resource on the already loaded UI.
With that in mind, I tried modifying the script I attached to introduce an error and saved… And the UI still appears. Except, since the script I attached was not working, I could not close the UI, so I had to close Godot altogether.
In fact, the only way I have been able to make the button stop working after saving was by introducing an error in the EditorPlugin code and saving. I can only assume this is what happened to you.

Related

Errors after deleting an action using Unity's new input system

I'm using Unity's new input system. I recently deleted some actions, and now I'm getting the following error whenever I go into Play mode. As stated here, the error doesn't break anything, but it's annoying to always see errors in my console. Is there any way to refresh the input settings so that the actions I deleted are completely removed and this error goes away?
Cannot find action 'Camera/New action1' with ID 'af026e96-883f-4172-ba96-2d8225a11f0f' in
'PlayerInput (UnityEngine.InputSystem.InputActionAsset)
UnityEngine.InputSystem.PlayerInput:OnEnable() (at Library/PackageCache/
com.unity.inputsystem#1.0.0/InputSystem/Plugins/PlayerInput/PlayerInput.cs:1564)
Its just a bug in Unity, if you just go to any game object with player input, change default map to some other value and just change it back to original and save, the error will go away.
If you go to the object in the inspector, re-select it, and then re-save it then the error should stop.

SceneManager LoadScene not working in editor playmode

as the title says I have an issue loading a scene when in playmode in the editor.
The workflow of my game is as follows:
Initializing (works fine)
There is an empty scene that creates some global game objects that will exist during the entire runtime.
MainMenu (works fine)
After the Initializing is done it loads the MainMenu scene. I can interact with the scene and everything is nice.
Connect to game server (works fine)
In the main menu I have an option to connect to a game server (a dedicated server application I created on my own)
Establishing the connection and sending the login works well.
Character selection (not working)
After the login on the server I get the resonse to select a character. (This works as expected.)
Then I'm going to handle this response by opening the character selection scene.
And here I have the issue. In Playmode inside the editor the handler method is executed (verifyed by debug logs) but the scene is not loaded actualy.
When I build the game and run the created .exe and follow the exact same steps the character selection scene is loaded and shown as expected.
I searched the documentation and also the web but did not find any similar issues (maybe I still missed something)
So my question is as follows:
How do I get the scene to also load in the editor playmode? My approach seems not to be totaly wrong as it works after build.
Here is the code snippet that should load the scene:
private void MessageRecived(object sender, GNL.ResponseMessageEventArgs e)
{
GameEventMessage message = this.eventManager.MessageHandler.ParseMessage(e.Message);
Debug.Log($"Recived message with type {message.Type}");
switch (message.Type)
{
case GameEvent.CharacterSelectionRequired:
Debug.Log($"Handle character creation 01");
this.HandleCharacterSelectionRequried(message);
break;
default:
break;
}
}
private void HandleCharacterSelectionRequried(GameEventMessage eventMessage)
{
Debug.Log($"Handle character creation 02");
SceneManager.LoadScene("CharacterCreation");
}
All three Debug.Log statements are executed. Only the LoadScene isn't working in the editor playmode.
IMPORTANT ADDITION
After further testing I have to mention that the network communication is done in a seperate thread. From this thread when a new message arrives an eventHandler is called.
This is where the Method is added to the Event handler:
this.client = new GNL.GameClient(System.Net.IPAddress.Parse(host), port);
this.client.AnnounceRecivedMessage += this.MessageRecived;
this.clientNetwork = new Thread(this.client.Start);
clientNetwork.Start();
And this is the definition of the eventHandler:
public event EventHandler<ResponseMessageEventArgs> AnnounceRecivedMessage;
IMPORTANT ADDITION - Part 2
I just discovered that, it works on a normal build but not when selecting "development build" in the build settings.
This is really annoying as I have to build the game every time I made a change to test it.
I'm thankful for any help and suggestions.
After much more debugging and testing I figured out that this issue indeed is a threading issue.
Deep in the debugger I found the exception I would have expected for a threading issue. So I will have to change my implementation here.
But still there is an inconsistence in how threads are handled in Unity when running the game with debugging tools enabled (playmode in editor and development build) and with them disabled (normal build).
AFAIK, you can't switch between scenes in the editor. Unity Editor only works to edit and play the opened scene.
If you want to test some parts of the workflow, create functions dedicated to the editor (you can use #if UNITY_EDITOR) to test your scenes without the previous character selection.

Issue with setting AutomationElement value

I have an issue with setting value of AutomationElement by using method ValuePattern.SetValue().
Everything works just fine until some dialog appears. When the dialog appears the code execution got stuck. No exception is thrown. After the dialog is confirmed, the code exection continues. Bellow is a sample of the code:
BasePattern basePattern = null;
ValuePattern valuePattern = null;
AutomationElement elementA = Window.GetElement(SearchCriteria.ByText(propertyName));
object patternObjectA = null;
elementA.TryGetCurrentPattern(ValuePattern.Pattern, out patternObjectA);
basePattern = (BasePattern)patternObjectA;
valuePattern = (ValuePattern)patternObjectA;
valuePattern.SetValue(optionToSet);
// Window.GetElement() is a method from TestStack.White framework
// The code execution got stuck on the last line until the dialog is confirmed
Is there any other way to set AutomationElement value?
Is somehow possible to avoid of getting stuck by dialog?
I'll by grateful for any help.
Thanks advance.
It could be that this dialog is not supporting UI Automation correctly or that you simply target the wrong element.
To verify that you may use Inspect.exe from Microsoft or similiar tools.
If it works, check if you really target the correct component with your code again.
If it does not work and:
if you are able to change the application
you can change the so called AutomationPeer of the UI component - here is a link for more infos
Or simply use another UI component that supports UI Automation correctly.
if you are not able to change the application, and also do not need to run in background, parallel, etc.. you might just focus the component (call setFocus() onto the AutomationElement, or expand it (via IsExpandCollapsePatternAvailable or simulated MouseClick onto the components coordinates)) and then use the SendKeys.SendWait("test") method.
EDIT: There is one more thing you should have a look at, and I wonder why I didn't mentioned it in the first place: Register to UI Automation Events
For example you could register a callback for the Structure change event type, and check if the dialog you talk about appeared.
If so --> click the confirmed button of the dialog.
Probably you will have to synchronize your execution, so that every further action in the UI Automation script waits until the registered callback got executed and the confirmed button got clicked.

Addon SDK way to make a dialog

What is the proper way to use the SDK to make a dialog (which is not anchored to the add-on bar, etc. but shows centered on screen)? It doesn't seem like there is any API for this important capability. I do see windows/utils has open but I have two problems with that:
The dialog opening seems to require "chrome" privs to get it to be centered on the screen (and I'd be expectant of add-on reviewers complaining of chrome privs, and even if not, I'd like to try to stick to the SDK way).
While I can get the DOM window reference of the new window/utils' open() dialog, I'm not sure how to attach a content script so I can respond to user interaction in a way that prompts (and can respond to) privileged behavior ala postMessage or port.emit (without again, directly working with chrome privs).
Ok, this answer should have been pretty obvious for anyone with a little experience with the SDK. I realized I can just use a panel. In my defense, the name "panel" is not as clear as "dialog" in conjuring up this idea, and I am so used to using panels with widgets, that it hadn't occurred to me that I could use it independently!
Edit
Unfortunately, as per Bug 595040, these dialogs are not persistent, meaning if the panel loses focus, the "dialog" is gone... So panel looks like it is not a suitable candidate after all... :(
Edit 2
I've since moved on and have gotten things working mostly to my satisfaction with sdk/window/utils and openDialog on whose returned window I add a load listener and then call tabs.activeTab.on('ready', and then set tabs.activeTab.url to my add-on local HTML file so the ready event will get a tab to which I can attach a worker. There is still the problem with chrome privs I suppose, but at least the main communications are using SDK processes.
Update to Edit 2:
Code sample provided by request:
var data = require('sdk/self').data,
tabs = require('sdk/tabs');
var win = require('sdk/window/utils').openDialog({
// No "url" supplied here in this case as we add it below (in order to have a ready listener in place before load which can give us access to the tab worker)
// For more, see https://developer.mozilla.org/en-US/docs/Web/API/window.open#Position_and_size_features
features: Object.keys({
chrome: true, // Needed for centerscreen per docs
centerscreen: true, // Doesn't seem to be working for some reason (even though it does work when calling via XPCOM)
resizable: true,
scrollbars: true
}).join() + ',width=850,height=650',
name: "My window name"
// parent:
// args:
});
win.addEventListener('load', function () {
tabs.activeTab.on('ready', function (tab) {
var worker = tab.attach({
contentScriptFile: ....
// ...
});
// Use worker.port.on, worker.port.emit, etc...
});
tabs.activeTab.url = data.url('myHTMLFile.html');
});
if the panel loses focus, the "dialog" is gone...
It doesn't get destroyed, just hides, right? If so, depending on why it's getting hidden, you can just call show() on it again.
You'd want to make sure it's not being hidden for a good reason before calling show again. If there's a specific situation in which it's losing focus where you don't want it to, create a listener for that situation, then call if (!panel.isShown) panel.show();
For example, if it's losing focus because a user clicks outside the box, then that's probably the expected behaviour and nothing should be done. If it's losing focus when the browser/tab loses focus, just register a tab.on('activate', aboveFunction)
Simply adding ",screenX=0,screenY=0" (or any values, the zeroes seem to be meaningless) to the features screen seems to fix centerscreen.

avoid chrome popup extension to close

Is there a function that allow me to select text when the extension
stays open. Normally when I Use the extension popup and I Click outside the
extension the extension close. Is there a wat to avoid this.
Thank you so much
Unfortunately there is currently no way to keep the popup open once you focus out of it. This is by design.
If you would like to always show something while interacting with the page, perhaps the experimental Info bars or even Desktop Notifications would work?
Hope that helped!
The only way to keep it open is to right click over the extension icon (button) and select "Inspect popup" the extension popup then show up and remain open but of course the debugger window show and this not a fix obviously still it will maybe inspire a hack... if someone is skilled enough and share the solution with all of us.
I encountered the same problem and I've thought of a possible solution (though not tested it):
Use your background.html to store the content of the popup action and upon loading the popup, you fetch the content via the default messaging for chrome extensions.
When doing all kinds of other stuff, like XHR's or something, I think you should do that in background.html too, so the requests won't abort if you close and you can do something with the result. Then when a user re-opens the popup, he'll see the result of his previous action instead of the default screen.
Anyone tried something like did already?
As far as I know you can't persist a pop up menu but my workaround has been using a content script to append a menu on page load. After the menu is appended you can toggle the menu via messaging between the background script and the content script.
If you want to encapsulate the menu from the page it's deployed on you could wrap your menu in an iframe. This could add complexity to your project since you would have to deal with cross origin issues and permissions.
There is an alternative hack for this. You can make use of chrome local storage to store the metadata as needed. Upon restart you can read that metadata and render the desired content. You will also probably clear that metadata after you have completed performing the operations based on that.