godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
89.87k stars 21.02k forks source link

Add Accessibility for Blind Developers Who Use Screenreaders #14011

Closed ghost closed 4 years ago

ghost commented 6 years ago

Operating system or device, Godot version, GPU Model and driver (if graphics related): Operating System: Arch Linux, might be true for blind users on other operating systems Godot Version: 2.1.4, may apply to all Issue description:

The Godot game editor does not work with the Orca screenreader. I was expecting to at least be able to use Orca's flat review with the editor application, but nothing happened; it is equivellent to turning off the monitor. Steps to reproduce: Install the GNOME desktop environment, along with the Orca screenreader. MATE will also work. With Orca running, open the Godot application. There will be no speech output from Orca. Link to minimal example project:

ndarilek commented 5 years ago

Ignore my first question above. I discovered and added accessible support to TabContainer. I'm now able to find, and select, the Input Map tab. Still a bit confused about whether there's a keyboard-friendly way to right-click nodes in the scene tree, or failing that, how I can trigger that action programatically.

What would be very useful is if I could set up a screenshare call with someone familiar with Godot development to help me through a few initial tasks. Things I'd like to accomplish:

If I could do those things, I think I could make much faster progress. Even unearthing accessibility issues performing any of the above would help me focus my efforts. Right now I'm just shotgunning, trying to find things that aren't accessible and making them work when what I need to do is focus in on my tasks and branch out from there.

Thanks.

malcolmhoward commented 5 years ago

@ndarilek Yep, I would still like to help work this. I will need a week or so to regain my footing with everything related to this issue, and then I'd be happy to jump onto a call. I not an expert at the engine, but I think I have built enough game prototypes to get us started.

ndarilek commented 5 years ago

I sort of figured out how to add scripts. I decided to start building a simple game alongside the accessibility plugin so that collaborators have a larger common frame of reference to discuss accessibility issues. I created a Player Area2D node, and lots of tabbing around revealed the button to add a script, which popped open Gedit and was a very usable experience. Progress!

Asteroids is sort of my goto for learning an engine or framework, so next I thought I'd add a Main scene to encapsulate all the game logic that couldn't fit within a single entity type. I created a scene, set its root node type to Node, and I cannot for the life of me find a button to add a script. I have no idea whether it isn't possible to add a script to this particular scene for some reason, etc.

I instanced a Player as a child of the scene, and I can see the player and its button to clear the script. But I have no idea why I can't add a script to just the Main scene root node.

My work is here for anyone interested in following along. You may also need the TTS plugin though it may work without it too and just print errors whenever attempting to speak something. But either way, removing the accessibility plugin would possibly reveal why my simple node setup isn't letting me attach a script to Main. Could be that I'm not correctly selecting the Main scene in the tree, in which case that's helpful feedback.

Also, is it fair to say that many of these buttons in the editor are in toolbars? I'm trying to come up with an easier means of navigating through all these buttons via the keyboard, because tabbing/shift-tabbing through them all is a bit slow. If many are in toolbars, I may implement tabbing between the toolbars and right/left-arrowing between the toolbar components.

Zireael07 commented 5 years ago

The main node in the tree is no different from the other nodes as far as I can tell, except the fact that it's selected when your new scene tab is first opened upon creation.

ndarilek commented 5 years ago

OK, more progress. I've exposed more properties on Tree to speech. I thought that up/down-arrow were navigating within the tree, but they seem to be selecting items. I think what's happening is that I have multiple scene nodes selected, so the button to add a script doesn't appear. I can sort of get the tree into a state where only one item is selected by expanding/collapsing items, at which point the Add Script button appears for Main.

Can someone please explain the logic for pressing up/down arrows in a tree? I assumed it navigated to a single item and selected whatever was focused, but in something like a tree of scenes that I assume supports multi-select, I'm wondering if it behaves differently? Is there a different keystroke for navigating in a tree and selecting a single item, or is there something to deselect the current item?

Thanks.

ndarilek commented 5 years ago

Lots of good progress yesterday. The property inspector has some collapsable things that have no keyboard focusability or interactivity, but I unearthed those and did some dark magic with simulating mouse clicks, so I can now expand/collapse node properties via the keyboard. Trees are about 80% accessible, though multi-column trees with different controls still pose a challenge.

Speaking of, I'm confused about how the input map editor works. I see a series of actions represented by tree items. The tree has 3 columns: 0 = action, 1 = deadzone. Expanding each action type seems to expose children for device types, and I assume from here I can configure actions, but I'm confused about lots of things:

 * What is the unlabeled third column in this tree?

 * Say I add an action, "speak_coordinates". I get a tree item for the action with no children. How do I add a child for a key mapping? Maybe it has to do with some interaction with this unlabeled third column that I'm not supporting accessibly yet?

 * What is the unlabeled TextureButton on this screen? Clicking it seems to close the settings, but it isn't the labeled "Close" button so maybe it's another action? Save/Undo?

Thanks for any help.

Calinou commented 5 years ago

@ndarilek The third column of the input map editor contains a button to add a new input event to an existing action (next to actions in the tree, it's represented by a "plus" symbol). For existing input events, it contains two buttons, one to edit the input event (the left one, represented by a pen) and one to remove it (the right one, represented by a cross).

The TextureButton that closes the settings is most likely the WindowDialog close icon (represented by a cross), it's implemented here: https://github.com/godotengine/godot/blob/750f8d4926edb14269d9f6a117c5a9fd4765373a/scene/gui/dialogs.cpp#L338-L345

The Project Settings is a modal dialog, hence the use of WindowDialog.

ndarilek commented 5 years ago

Thanks, that's helpful. I'm now exposing button counts in column announcements for Tree and am getting an announcement of the fact that there are buttons.

Thanks for pointing me to where the Close TextureButton is implemented--I'm having a hard time tracking some of these down in the source, and am trying to set meta fields on some of these so my plugin can provide accessible descriptions/labels.

I just added a get_button_tooltip(...) method to TreeItem to expose buttons' tooltips, since buttons in columns are only returned as Texture objects and there's no way to get at the associated tooltip via that. Hopefully that isn't an objectionable merge when I submit a larger PR for this plugin.

Thanks again.

ndarilek commented 5 years ago

I've now implemented a bit of hackery that lets you right-arrow to a column of buttons in a tree, use Home/End to cycle between them, and use Space to activate one. Via this mechanism, I can now activate the dialog to add a key to a created action.

I have a question about how this works, though, complicated by the fact that I can't use the keyboard to explore this dialog. Does it intercept a single set of keypresses, then let me confirm/cancel that? Or does it intercept every key sent to it, and make the last key what is ultimately bound to the action?

I.e. say I add an action, "speak_coordinates", which I want bound to "c". If this dialog appears and I press "c", then attempt to tab to the OK button, does it:

a) bind "c" to the action, ignoring subsequent keypresses?

b) bind "c", then "tab" when I attempt to tab to the OK button?

Thoughts welcome on how to handle this edge case. I may add a meta property to this specific dialog telling the plugin to either only support capturing the first InputEvent or, if that already happens, redirecting focus to the confirmation button after the first event is handled. But I've looked through the code, and am not immediately certain whether A, B, or something entirely different is true.

Thanks.

Calinou commented 5 years ago

@ndarilek When you trigger the button that adds a new input event, it will present a dropdown with four options:

The Key option displays a modal dialog (on top of the existing one) that asks the user to press a key (or a key with modifiers, e.g. Ctrl+K). If the user presses another key before confirming, it will replace the key that was currently defined in the confirmation dialog. This dialog will keep listening for keyboard events until the user confirms by clicking "OK" or cancels by clicking "Cancel" in the dialog. Since this dialog listens for all keys (including "special" keys such as Tab), keyboard navigation isn't possible. This is because the dialog will replace the current choice with Tab. Likewise, the Escape key cannot be used to cancel the dialog. We should aim on improving this dialog's usability :slightly_smiling_face:

In contrast, the other types (Joy Button, Joy Axis and Mouse Button) don't listen for events, they just use dropdown menus in modal dialogs instead.

ndarilek commented 5 years ago

Got it. So I think that, for accessibility purposes, I'll arbitrarily decide that the first key in this dialog "wins" when the plugin is running, so subsequent tab/enter/escape presses do what they're supposed to. I've discovered that redirecting focus to the OK button when in this dialog causes whatever key used to trigger the button not to be saved. I.e. if I use Space to trigger the dialog to appear, then Enter to trigger the OK button, Space is saved as the key, not Enter.

So here's the behavior I'm witnessing now, and I'm wondering if anyone has any thoughts on what to do about it. I trigger the button that opens the dialog on pressing "ui_accept", so Space or Enter by default. When I trigger the dialog, whatever key I use to trigger the dialog to appear is the key set for the command. So as above, if I use Space to trigger ui_accept, and Enter to close the dialog, my command is set to Space. Likewise if I trigger the dialog to appear with Enter and use Space to press the OK button, the command is bound to Enter.

I think what's happening is that my press event sends the signal to click the button, which in turn opens the dialog listening to key events. That dialog then gets the release of the key I just pressed (I.e. Space) and sets it as the command. Wondering if anyone has any thoughts on how to work around this? I tried is_action_released instead of is_action_pressed, my thought being that it would detect the release of the pressed action somehow and trigger on that, but no dice.

Here's my code. Essentially it identifies the selected button to be clicked, then sends the signal. Is there any way I can make the node accept the entire event, including its release? Or is there something else going on here that's causing the event release to reach the dialog and trigger the capture? Suggestions welcome--I'm learning GDScript by jumping in the deep end so don't have a clue:


var button_index

func tree_input(event):
     var item = node.get_selected()
     var column
     if item:
         for i in range(node.columns):
             if item.is_selected(i):
                 column = i
                 break

     # button_index is set to 0 in an item_selected callback based on 
get_button_count(...) != 0

     if item and column and button_index != null:
         if event.is_action_pressed("ui_accept"):
             node.accept_event() # How can I accept the corresponding 
release of the press here so it doesn't leak through?
             return node.emit_signal("button_pressed", item, column, 
button_index + 1)
         var new_button_index = button_index
         if event.is_action_pressed("ui_home"):
             node.accept_event()
             new_button_index += 1
             if new_button_index >= item.get_button_count(column):
                 new_button_index = 0
         elif event.is_action_pressed("ui_end"):
             node.accept_event()
             new_button_index -= 1
             if new_button_index < 0:
                 new_button_index = item.get_button_count(column) - 1
         if new_button_index != button_index:
             button_index = new_button_index
             var tooltip = item.get_button_tooltip(column, button_index)
             var text = ""
             if tooltip:
                 text += tooltip + ": "
             text += "button"
             tts.speak(text, true)
Zireael07 commented 5 years ago

Just thought of something @ndarilek. Apart from the fact that AFAICT there is no way to "right click" from keyboard, some keyboard commands (e.g. Del) depend on what is focused/selected. Does your Godot/screen reader combo tell you that or would we need an annotation (probably in "meta")?

ndarilek commented 5 years ago

If you mean determining which node currently has focus, I track focus_entered and lots of other signals to report changes via speech.

And I'm simulating left mouse-clicks, so I'll probably branch out to right-clicks soon. Though, having found the list of keyboard shortcuts in the editor along with the New Script/Scene buttons, this isn't so immediately critical.

ndarilek commented 5 years ago

Hacky solution found. The only circumstance I've yet found where an AcceptDialog gets focus is this dialog to set keyboard shortcuts. So if that happens, I add a oneshot timer for 5 seconds that autocloses the dialog. In that 5 seconds, you press whatever key combo you want assigned to that action, and the dialog confirms the change automatically.

This is hacky as fuck, so if someone has a better solution then I'm all ears. :) I may also need to add an obscure meta property to this dialog in the engine so the accessibility plugin knows to special-case it and announce instructions to press a key.

With this in place, I'm able to add actions to my game and respond to them. I now have keys to speak my player's coordinates, heading, etc. as well as to quit the game. Think I'm getting close to being able to develop simple audio games with my accessible interface.

So naturally I have another question. :) Is there a signal that I can hook in my EditorPlugin to detect when the game I'm running exits? When the editor initially launches, I have to set a starting UI focus so that Tab/Shift-Tab can even navigate, otherwise there's no current focus to find a next/previous focus from. But when a launched game exits, focus is unset, and I haven't tracked down a signal to catch to handle that. Presumably something as significant as launching a separate game/scene tree within the editor doesn't just vanish without sending a signal.

Whew, and the road goes ever onward...

Zireael07 commented 5 years ago

I don't think there is something, but you could make use of WM_NOTIFICATION_QUIT in your game script somehow maybe? Send a boolean variable over to the EditorPlugin? (While I have used WM_NOTIFICATION_QUIT to autosave on exit, I haven't used EditorPlugin almost at all)

ndarilek commented 5 years ago

Hmm, what is WM_NOTIFICATION_QUIT?

And what happens visually in the editor window when I run a game? I know the game appears in a separate window, but does anything in the editor change? Wondering if it switches to a different screen or something. I see this in my console:

Running: /home/nolan/src/godot/bin/godot.x11.tools.64 --path /home/nolan/Projects/godot-accessibility --remote-debug 127.0.0.1:6007 --allow_focus_steal_pid 32312 --position 328,225

which suggests to me that maybe the interface itself changes to something that isn't yet accessible, even after the game closes.

Calinou commented 5 years ago

NOTIFICATION_WM_QUIT_REQUEST is a notification identifier (it's defined in MainLoop).

For instance, you can react to notifications in GDScript by writing a _notification(what) function:

func _notification(what):
    if what == NOTIFICATION_WM_QUIT_REQUEST:
        print("User requested the project to quit")

You can also make Godot not quit automatically when the user clicks the "Close" button or presses Alt+F4. See Handling quit requests in the documentation.

To answer your latest question, the Output panel of the editor will open automatically when you run a game by default. This behavior can be disabled by unchecking Run > Output > Always Open Output On Play in the Editor Settings. It will stay open after you close the game, unless you check Run > Output > Always Close Output On Stop in the Editor Settings.

This panel displays all messages printed by the running game, and is located at the bottom of the editor window. When the project isn't running, it can be expanded or folded manually by clicking on it.

francipvb commented 5 years ago

Hello,

How can I test this under windows?

Thanks,

ndarilek commented 5 years ago

Windows testing is a bit dicy right now. First you need to compile godot-tts, which is Rust-based, and requires setting up Rust's Tolk library and running a screen reader. Tolk-rs' maintainer isn't actively working on the project anymore, but I've offered to take it over and make it a bit easier to work with. I just spend most of my time in Linux, so Windows isn't a priority. You also need my fork of the engine.

So, in short, very rough under Windows right now. Help on that front very much appreciated. It's doable--I just have my hands full.

I'll probably put together a screencast in a week or two showing off what's possible so far and recruiting help. So you'll at least be able to see it in action.

francipvb commented 5 years ago

Thanks,

Ok, native devel is not a strong point in my case...

I will try to build myself.

Anyway I got this when trying to build godot-tts

   Compiling gdnative-sys v0.5.0
error: failed to run custom build command for `gdnative-sys v0.5.0`

Caused by:
  process didn't exit successfully: `C:\Users\Franci\source\repos\godot-tts\target\debug\build\gdnative-sys-01490563416791dd\build-script-build` (exit code: 101)
--- stderr
thread 'main' panicked at 'Unable to find libclang: "couldn\'t find any of [\'clang.dll\', \'libclang.dll\'], set the LIBCLANG_PATH environment variable to a path where one of these files can be found (skipped: [])"', src\libcore\result.rs:999:5

So I'm stuck...

ndarilek commented 5 years ago

Hmm, I have the following in my EditorPlugin:


func _notification(what):
     print("Notified: %s" % what)
     if what == MainLoop.NOTIFICATION_WM_QUIT_REQUEST:
         print("User requested the project to quit")

That does print things, but never "User requested the project to quit", even when I quit the editor itself. Thoughts?

Also, I tried an experiment where I made every node keyboard/mouse-focusable, thinking that should make focus land somewhere from which I could tab. I then started printing on focus_exited, and discovered that focus is removed from where it last lands on game launch. So it isn't, in fact, landing somewhere unfocusable. It's nowhere at all.

For now I have a workaround wherein I set an initial focus on screen change if nothing is focused, so pressing F1-F3 gets things working again. Is it possible for an EditorPlugin to intercept GUI input? I see a `forward_guiinput method (or something similar, docs aren't open now) but it isn't documented. If so, I can capture input and set focus somewhere if focus is unset.

Thanks.

ndarilek commented 5 years ago

I asked this on the forum, but didn't get an answer. This work depends on a GDNative TTS plugin I wrote. Can I make GDNative plugins available for others to use, and if so, how? I don't mean how to cross-compile and set up CI, but rather:

 * Is there a standard way of making an archive of compiled binaries available for other plugins/games to use? Presumably folks aren't expected to build third party GDNative libraries in cases where they're exporting to other platforms. Or are third party pre-built GDNative plugins not a thing?

 * I have const TTS = preload("res://godot-tts/godot_tts.gdns") in my script. This assumes a set location for my plugin library. Likewise, the libraries themselves have res:// paths which assume locations in res://godot-tts/target/debug. I don't want to impose a project layout on anyone, so am wondering if any of these paths can be relative?

Thanks.

Calinou commented 5 years ago
  • Is there a standard way of making an archive of compiled binaries available for other plugins/games to use? Presumably folks aren't expected to build third party GDNative libraries in cases where they're exporting to other platforms. Or are third party pre-built GDNative plugins not a thing?

Unfortunately, there's no standard for that yet, so you will have to compile libraries and make them available using GitHub Releases or similar.

  • I have const TTS = preload("res://godot-tts/godot_tts.gdns") in my script. This assumes a set location for my plugin library. Likewise, the libraries themselves have res:// paths which assume locations in res://godot-tts/target/debug. I don't want to impose a project layout on anyone, so am wondering if any of these paths can be relative?

I don't think you can make the GDNativeLibrary use relative paths (unless you create it at run-time, but that sounds quite involved). Still, add-ons are often located in res://addons, which is the standard location used by editor plugins. Therefore, you could ask users to place everything in res://addons/godot-tts, which should play well with most projects.

ndarilek commented 5 years ago

Ah, OK, so basically build a GitHub release or equivalent containing my pre-built binaries/docs/whatever, and ship everything configured to recommend and use res://addons/godot-tts? Cool, thanks, that's helpful!

ndarilek commented 5 years ago

I think that, once I've added support for setting node properties from the editor, I'll start working on actual audio games to see how far I get.

Unfortunately, I'm struggling with making some of the properties a bit more accessible. Specifically, I've added keyboard support to expand/collapse EditorInspectorSection, at which point I can tab through any contained properties. What I can't do is get labels for some--EditorPropertyVector2, for instance.

I assume there are text labels for these somewhere? They aren't made available as Label instances. Could someone please point me to where these property labels are rendered? I'm scraping the tree trying to find them, but am coming up blank.

Thanks a bunch.

Calinou commented 5 years ago

EditorPropertyVector2 displays two fields (EditorSpinSlider) marked as "x" and "y". These EditorSpinSliders are children of a VBoxContainer by default, or an HBoxContainer if interface/inspector/horizontal_vector2_editing is enabled in the Editor Settings.

The initial rendering is done here: https://github.com/godotengine/godot/blob/24e1039eb6fe32115e8d1a62a84965e9be19a2ed/editor/editor_properties.cpp#L1150-L1181

ndarilek commented 5 years ago

Sorry, I was unclear. Where is the label for this property rendered? Presumably in a Node2D, one of these properties references position. I'm wondering how to find the label text for that property, given that it doesn't appear as a Label anywhere I can find.

Sorry if I'm missing it--I did find the EditorPropertyVector2 implementation a while back, but it only seems to render the UI for setting the property and not its associated label.

Thanks.

Zireael07 commented 5 years ago

The labels (as well as everything that @Calinou mentioned) are rendered in the inspector.

From the top, the inspector's contains the following: Inspector | Node (those are two tabs) [ name of node you're inspecting, e.g. "marker"] a text box for filtering properties [Script Variables header (optional), with an arrow for collapsing] [any exported script variables appear here] [ class of node you're inspecting, e.g. Node2D] [Transform header - with a tiny arrow that lets you collapse the section] Position label - rendered to the left of the two boxes that EditorPropertyVector2 makes Rotation degree - ditto, to the left of a single text input box Scale label - same as position, the two boxes are labeled x,y so same as Position [Z Index header] [ super class of node you're inspecting, e.g. CanvasItem in case of a Node2D] [Visibility header, with an arrow...] [Visible label next to a tick box] [Two color selectors] [Show behind parent label next to a tickbox] [Layer mask - a complex container full of tiny little boxes] [Material header, with an arrow...] [Node label] - it's a super super class every node inherits from, so it's always at the bottom This section always contains two headers, both with arrows for folding: [Pause - a dropdown] [Script - a dropdown which lets you select a script]

For e.g. 3D nodes, the inspector can get very complex - that was just a simple Node2D example I described, I am thinking your best bet is to somehow make a shortcut for quickly accessing the most important things - the Transform section and Pause/Script at the bottom, and you can always easily navigate to exported properties because they're at the top.

P.S. If you select the Node tab at the top, it opens a completely different menu in place of the Inspector.

Zireael07 commented 5 years ago

PPS. If you filter the properties, you only have the labels, e.g. Node2D, and only one header (of the kind that has the arrow for collapsing) which contains the property you want. I just checked and you do can filter for a built-in property such as position, so this might save you a lot of time :)

ndarilek commented 5 years ago

Oh, I figured it out. Forgot that a node's parents aren't necessarily its superclasses. In this case, I had a simple check for node is EditorProperty and spoke its label if one was set. In this case, the LineEdit for the position X/Y components has in its node ancestry tree an EditorPropertyVector2 which, in turn, has the label.

Cool, now we have labels speaking for editor properties in the inspector. Thanks for the layout description as well. That helps. Going to have to think about how to make that more accessible.

Calinou commented 5 years ago

It seems property labels aren't drawn using nodes, but rather using low-level draw_string() calls. (Try searching for draw_string in editor/editor_inspector.cpp.) I'm not sure how these could be made accessible, or if turning them into nodes will be necessary.


For future reference, here's some additional information about EditorInspector/EditorProperty. I wrote this before searching for instances of draw_string(), so what follows may be superfluous.

I haven't played much with the editor inspector code, but from what I understand, editor properties are added to an AddedEditor struct when they're registered: https://github.com/godotengine/godot/blob/24e1039eb6fe32115e8d1a62a84965e9be19a2ed/editor/editor_inspector.cpp#L865-L873

This AddedEditor struct has a label string, which will be passed to instanced EditorProperty nodes: https://github.com/godotengine/godot/blob/24e1039eb6fe32115e8d1a62a84965e9be19a2ed/editor/editor_inspector.cpp#L1320-L1367

Finally, this label string is used to populate the Label node using EditorProperty::set_label_reference, but only if horizontal Vector2 editing is disabled: https://github.com/godotengine/godot/blob/24e1039eb6fe32115e8d1a62a84965e9be19a2ed/editor/editor_properties.cpp#L1178

Otherwise, EditorProperty::set_bottom_editor will be used to place the editor below the label: https://github.com/godotengine/godot/blob/24e1039eb6fe32115e8d1a62a84965e9be19a2ed/editor/editor_properties.cpp#L1158

ndarilek commented 5 years ago

I now have the Menu key triggering right-clicks. This seems to allow programatic interaction with rows in trees.

I also fixed some issues calculating text for PopupMenu items. This has the added benefit that many items I thought were unlabeled actually are.

Now the right-click menu items in trees are accessible, or at least partially. I seem to be experiencing some off-by-one issues that are tricky to diagnose.

Getting there...

ndarilek commented 5 years ago

I promise not to hijack this issue for this purpose, but where's the best place to get help with general questions using the engine?

A few days ago, I discovered that 2-D audio streams seem to presuppose that they're panned/attenuated from screen center, and don't take rotation into account. This isn't what I want from a top-down audio game which will have rotation, possibly off-screen sound sources heard in the distance, etc. The viewport docs seem to indicate that 3-D audio is possible even for 2-D nodes, but I'm not clear if I can just add a 3-D stream player to 2-D nodes and have their positions synced, if I have to sync the X and Z positions manually to the 2-D X/Y and pin the stream's Y to 0, if I have to figure out how to use an ortho camera and render 3-D objects in 2-D, etc.

I asked this and tried posting this on Reddit, but the former has no responses and the latter isn't visible. I don't know if I don't get Reddit, if I need to be approved, etc.

Anyhow, I don't want to turn this issue into a support thread, but I'm using Godot in an unusual way, and it may turn out to be impossible even after doing all this work. I'm prepared for that--I decided to give a month to pushing this forward and seeing how far I get with it--but part of succeeding here involves knowing whether what I want is even achievable even with accessibility. And if I can create an audio game development environment, I'll be putting together materials to show others how to do it, so hopefully my learnings can help others. But I'm having a tough time getting answers to these niche questions, and that seems to be this week's bottleneck.

In other news, I'm also working on automating Windows builds of the TTS plugin, and have put together an accessible starter project making it easy to both demo my work and create in an accessible environment. I'll update when I have binary builds of the TTS plugin available for download.

Thanks.

Calinou commented 5 years ago

Adding a Listener2D node has been requested in https://github.com/godotengine/godot-proposals/issues/49. It would let you configure where the sound is being listened from in a 2D scene, like it can already be done in 3D with the Listener node.

I can confirm the Reddit post appears as removed, I don't know why. I manually approved it, but it probably won't appear in the front page as it was posted yesterday. Try posting it again, it should be fine for now :)

ndarilek commented 5 years ago

Ugh, so frustrating. Just resubmitted the post, viewed in a private tab, shows as removed again.

Thanks for the proposal link.

Sorry to use this issue for support like this.

ndarilek commented 5 years ago

Progress slowed a bit while I tried doing battle with Appveyor to build the TTS plugin under Windows. I've since given up on that hot mess, and will probably provision my own Windows VM sometime soon and set up a GitLab CI runner. If anyone has a spare Windows VM sitting around for that purpose, I'd appreciate it.

Panels are now focusable. This fixes last week's issue where quitting a game in the editor broke keyboard focus.

I also refactored the TTS plugin a bit to route calls through a TTS.gd script. For now this sends all calls to the native Rust library, but future versions might dispatch calls to a Java/Kotlin module on Android, etc.

I'm also doing a bit of work on my first Godot game, a spatial audio version of Asteroids. Last week's Appveyor distraction killed progress in that area, but I'm hoping to get to it more this week. Working on navigation, wrapping, speaking coordinates/heading, etc. I also had to hack around the lack of 2-D spatial audio, which I think I've done but have yet to test.

ndarilek commented 5 years ago

@francipvb Have you tried installing Clang/LLVM? I'm actually hitting this trying to build the latest godot-tts under Windows as well, and discovering I likely need clang installed. The build works under Appveyor, so I suspect they have it installed there and it may be your missing piece.

I may try this later this week, but Godot doesn't run in my Windows VM, so even if that gets it working, I'll be limited in how much Windows testing I can do.

I have an accessible starter that sets up a directory structure into which you can compile godot-tts. Ignore the instructions to fetch the godot-tts build from Appveyor. I can't figure out how to combine Linux and Windows builds into a single zip, so I'm abandoning that in favor of setting up my own GitLab CI runner. But since I can't run Godot under Windows currently, that's getting downgraded in priority for now.

Calinou commented 5 years ago

I may try this later this week, but Godot doesn't run in my Windows VM, so even if that gets it working, I'll be limited in how much Windows testing I can do.

You should be able to install a software OpenGL implementation in the VM: https://github.com/pal1000/mesa-dist-win

Godot will run slowly, but this way, both the GLES3 and GLES2 renderers will work.

francipvb commented 5 years ago

@francipvb Have you tried installing Clang/LLVM? I'm actually hitting this trying to build the latest godot-tts under Windows as well, and discovering I likely need clang installed. The build works under Appveyor, so I suspect they have it installed there and it may be your missing piece.

I may try this later this week, but Godot doesn't run in my Windows VM, so even if that gets it working, I'll be limited in how much Windows testing I can do.

I have an accessible starter that sets up a directory structure into which you can compile godot-tts. Ignore the instructions to fetch the godot-tts build from Appveyor. I can't figure out how to combine Linux and Windows builds into a single zip, so I'm abandoning that in favor of setting up my own GitLab CI runner. But since I can't run Godot under Windows currently, that's getting downgraded in priority for now.

I left this untouched, but I will give a try.

Cheers,

francipvb commented 5 years ago

Hello @ndarilek,

I gave up a try into this. I've installed LLVM toolchain and it worked.

Cheers,

ndarilek commented 5 years ago

Sweet! Do you mean it compiled, or does it actually talk under Windows? I haven't had a chance to try getting software OpenGL working yet.

francipvb commented 5 years ago

I think I have an OpenGL implementation (I have a NVIDIA GPU).

I'm just building your godot branch.

francipvb commented 5 years ago

Hello,

How I connect these two things now?

Thanks,

francipvb commented 5 years ago

Note that I've built the branch from github.

ndarilek commented 5 years ago

I think it's documented well in the README for the starter. Please let me know if you have any questions regarding that.

francipvb commented 5 years ago

Sorry, I am unsure where I have to look, because the godot-tts repository doesn't have a README.

Cheers,

ndarilek commented 5 years ago

Oh, sorry, thought you saw this. Don't follow the godot-tts download instructions since they assumed I could get Appveyor working. And the last bit about losing focus on game quit is no longer true.

Good luck, hope this works under Windows.

ndarilek commented 5 years ago

Having some real struggles with the right-click popup menus I get when clicking on tree nodes in the editor. Here is the code I'm working with. In particular, sometimes get_item_index is returning -1 and I don't know why. That makes it pretty much impossible to get any details on a PopupMenu item, and the methods for doing so seem to expect an idx parameter which I assume is an index.

Looking at the source, it seems -1 means the item isn't found. But I'm passing in the ID as retrieved by id_focused, so I don't know why this signal would hand me an ID that isn't found.

Anyhow, I attempted to just sub in the ID when I get -1, but that's clearly not right, as I often click on one thing and get something entirely different. Help with this very appreciated--I've spent hours on it and don't know whether these particular control instances are buggy or if something else is going on here. Things work in other menus, but not the tree item context menus in the node list. Thanks.

francipvb commented 5 years ago

Oh, sorry, thought you saw this. Don't follow the godot-tts download instructions since they assumed I could get Appveyor working. And the last bit about losing focus on game quit is no longer true. Good luck, hope this works under Windows.

Apparently this link is to a private repo...

Thanks,

ndarilek commented 5 years ago

Doh, fixed, sorry.