Seite 1 von 1

[Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input Libra

Verfasst: 29.05.2015, 18:11
von Schrompf
Moin,

SNIIS - Simple Non Intrusive Input Library ist eine Library, die alle möglichen Desktop-Eingabegeräte abbilden soll. Da gibt es ja ein paar existierende Libs, aber hier ist der Wettbewerb erstaunlich dünn im Vergleich zu Alles-Rein-Engines. Und da keine Lib alles konnte, was ich für den Splatter-Port brauchte, habe ich mein altes Vorhaben umgesetzt, meinen Code in eine neue Lib umzuformen.

Link: https://github.com/Schrompf/sniis
Lizenz: WTFPL oder vergleichbarer Quatsch

Was kann die Lib:
- Simple: primitive Schnittstelle und einfacher Code, kein Budenzauber mit AbstractFactoryCreatorAdaptorPattern (I'm looking at you, OIS)
- Non-Intrusive: soll *nicht* die Message Pump des jeweiligen OS übernehmen. Braucht demzufolge gelegentlich Infos von draußen
- Input: kann mehrere Mäuse, Tastaturen, Gamepads, Controller, Joysticks.
- Library: öhm... ist halt ne Lib. Ein Rudel C++-Files zum Mitkompilieren, optional (kommt noch) vorkompilierte Lib mit PlainC-Schnittstelle
- außerdem: kann Action Mapping, also abstrakte Eingabekanäle, die sich aus konkreten Bedienelementen der Eingabegeräte speisen
- außerdem: kann Tastenwiederholung
- außerdem: kann teilweise Namen der Bedienelemente ermitteln, für GUIs und HUDs.

Benutzung:
Initial: SNIIS::InputSystem::Initialize( datFenster);
Pro Frame:
SNIIS::gInstance->StartUpdate();
auf Windows: SNIIS::gInstance->HandleWinMessage( datRawInputMsg);
SNIIS::gInstance->EndUpdate();
Ende: SNIIS::InputSystem::Shutdown();

Plain-C-API kommt wie gesagt noch. Das "Von außen Infos reinreichen" wird aber evtl. der Genickbruch der Lib - in C# oder Java kriegt man ja nie Zugriff auf die Systemnachrichten und kann demzufolge RawInput-Nachrichten gar nicht weiterleiten.

Was fehlt noch:
- C-Interface
- evtl. weitere Typen von Eingabeelementen - die USB-HID-Spec enthält da ja noch einen ganzen Straus weitere Sachen, die garantiert auf irgendnem Flight Stick verwendet werden
- Namen aller Bedienelemente ermitteln - aktuell gehen nur Tastatur-Buttons auf Windows und Linux
- irgendwie anders an die Windows Messages rankommen?
- Touch- und Gesten-Unterstützung?

Was kann die Konkurrenz:
- OIS - Object-Oriented Input System - alt, mühsam und umständlich, teilweise intrusive, kann keine Multi-Tastaturen und Multi-Mäuse, kann kein Action Mapping
- ManyMouse - kleines feines Ding, aber halt nur Mäuse, kein Action Mapping
- "Simple cross-platform gamepad library" von TigSource - kleines feines Ding, aber halt nur GamePads/Joysticks/usw., kein Action Mapping

Würde mich freuen, wenn es dem einen oder anderen hilft.

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 29.05.2015, 21:01
von xq
Hey,
klingt schon ziemlich fancy, ich werd es mir hoffentlich die Tage mal angucken, was du da so gebastelt hast. Multi-Input ist halt schon derb geil

Grüße
Felix

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 29.05.2015, 21:07
von Krishty
Schick! Direkt benutzen werde ich die Bibliothek nicht, denn unter Windows habe ich ja bekanntermaßen meine eigenen Wrapper, aber bei der späteren Portierung wird sie mir garantiert behilflich sein :)

Ich finde ja generell, dass viel zu wenig von den Projekten hier öffentlich gemacht wird (woran ich mitschuldig bin), darum ist das sehr willkommen.

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 30.05.2015, 11:03
von Schrompf
Dann veröffentliche doch auch Deinen Kram! :-) Ich bräuchte bei SNIIS wirklich noch hier und da Unterstützung. Ganz zu schweigen von den vielen kleinen faulen Kompromissen, die ich eingegangen bin, um irgendwann fertig zu werden.

Z.B.: ordentliche Namensauflistung bei Windows - Joysticks, Linux - Joysticks, Mac - Alles.
Kraftrückfütterung wäre noch ein langfristiges Ziel.

Nuja, mir erfüllt sie aktuell alle Bedürfnisse; und sie ist so schon ein rundes Ding mit Funktionalität auf Höhe von OIS plus die Erweiterungen, die Tilman/Sternmull früher dafür geschrieben hat. Ich bin also zufrieden. Ich werde jetzt mal einen Feldzug durch die Foren und Sozialplattformen antreten, um das Ding etwas bekannter zu machen. Gibt ja eh nicht mehr viele Leute, die tatsächlich noch eigenen Code schreiben.

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 30.05.2015, 12:44
von Spiele Programmierer
Sieht wirklich gut aus.
Ich habe bisher immer die Input Funktionen von GLFW genutzt.
Joystick und co. habe ich bisher nicht gebraucht. Sollte ich das oder Input ohne GLFW mal brauchen, könnte die Lib eine echte Option sein!

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 30.05.2015, 16:05
von Jonathan
Ja, sieht sehr nützlich aus, danke schonmal. Werd ich mir garantiert angucken, wenn ich wieder in dem Bereich arbeite.

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 30.05.2015, 16:21
von Schrompf
Randinfo: ich habe die Lib in GLFW reingepatcht. Gab keine Konflikte, hatte ich mir irgendwie stressiger vorgestellt.

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 30.05.2015, 16:32
von Krishty
Schrompf hat geschrieben:Dann veröffentliche doch auch Deinen Kram! :-) Ich bräuchte bei SNIIS wirklich noch hier und da Unterstützung. Ganz zu schweigen von den vielen kleinen faulen Kompromissen, die ich eingegangen bin, um irgendwann fertig zu werden.

Z.B.: ordentliche Namensauflistung bei Windows - Joysticks, Linux - Joysticks, Mac - Alles.
Mein Dauerprojekt an sich geht wegen Copyright-Verletzungen nicht, aber der Input-Kram ist ja schon zu großen Teilen öffentlich. Die Namensauflistung solltest du hiermit hinkriegen: http://zfx.info/viewtopic.php?f=11&t=2977#p39216 (GetRawInputDeviceInfoW() – CreateFile() – HidD_GetManufacturerString() – HidD_GetProductString()). Aber sei vorsichtig – einige billigst-Geräte (die virtuelle Tastatur meiner Freundin) geben da Müll zurück. Falls es, wie hier um die Namen der Knöpfe ging: Das ist das Registry-Gefrickel in meinem Artikel. Ist aber für die meisten Joystick-Treiber nicht gesetzt und man müsste einfacher auch über DirectInput drankommen.
Schrompf hat geschrieben:Kraftrückfütterung wäre noch ein langfristiges Ziel.
Bei mir auch. Sei froh, dass du DirectInput benutzt. Nach der Woche, die ich mit RawInput dran verschwendet habe, sieht es so aus, als dass ich dafür rohe Pakete an den Treiber schicken muss. *Aufschieb*

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 01.06.2015, 14:43
von Jonathan
Schrompf hat geschrieben:Randinfo: ich habe die Lib in GLFW reingepatcht. Gab keine Konflikte, hatte ich mir irgendwie stressiger vorgestellt.
Im Sinne von? Strebst du an, die Eingabefunktionalität von GLFW komplett durch deine zu ersetzen und es als offiziellen Teil des Projektes einzureichen? D.h. in nem halben Jahr oder so müsste ich mir nur die neuste GLFW Version runterladen und hätte dann automatisch ein relativ mächtiges Eingabeverwaltungsframework?

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 01.06.2015, 15:00
von Schrompf
Nein, bisher ist das nur privat. Wie gesagt: ich *musste* meine eigene Inputlib ausrollen, weil nichts Existierendes all meine Ansprüche erfüllt hat. Bei GLFW hat mir das Action Mapping gefehlt, der XInput-Support auf Windows, allgemein die Unterstützung mehr als einer Maus oder Tastatur, und die Namensermittlung der Bedienelemente.

Ich habe meine Lib dann in GLFW neben dem existierenden (aber von mir unbenutzten) Code integriert und musste dazu in jeder der drei OS-Implementationen jeweils ein paar Zeilen einfügen. Ich hatte halt nur erwartet, dass die Nachrichtenverarbeitung von GLFW mir irgendwo dazwischenfunkt... eine kritische Systemnachricht irgendwo wegfängt oder so. Hat es aber nicht. Hm.

Ich hatte auch überlegt, ihnen SNIIS als Komplettersatz ihrer Inputlib anzubieten, aber ich glaube, das würden sie ablehnen, weil sie dann ein bisschen was von ihrer Maus-Zentrier- und Fokus-Logik umschreiben müssten. Aber ich glaube, ich stehe hier mir gerade mal wieder selber im Weg. Wie Väterchen immer sagte: lehne nicht gleich selber alles ab, überlasse das Ablehnen den Anderen.

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 02.06.2015, 14:39
von Schrompf
Hat jemand eine Idee, wie ich in meiner Update-Funktion RawInput-Nachrichten bekommen könnte, ohne dass ich die Nachrichtenschleife des Programms übernehme? Also wirklich nur die RawInput-Nachrichten, ohne in ner BusyLoop mit dem Hauptprogramm zu konkurrieren, Nachrichten zu verlieren oder dem Hauptprogramm welche wegzunehmen?

Das wär nämlich der finale Ritterschlag, mit dem ich die Lib dann auch in C# oder Java anbieten könnte oder als Plugin in den Unity Asset Store setzen könnte.

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 11.06.2015, 18:45
von Schrompf
It's mating ridiculous, but it works!

In der dürftigen RawInput-Doku gibt es auch einen Verweis auf GetRawInputBuffer(), was die Buffered-Version ist, die ohne Zuarbeiten von der Message Loop auskommt. Diese Funktion ist der kritische Teil, weswegen ich nun meine Input-Lib nicht mehr in UpdateVorMessageLoop(), HierNimmDieseRawInputNachricht() und UpdateNachMessageLoop unterteilen muss. Ab jetzt reicht ein einzelnes Update(). Und diese Änderung sollte es jetzt auch ermöglichen, die Lib auch von C#, Java aus benutzen zu können oder sie als Plugin in den Unity Asset Store zu stellen.

Der Trick: GetRawInputBuffer() ist auf 64bit-Windows verbuggt! Die RawInput-Nachrichten stecken in sowas:

Code: Alles auswählen

struct RAWINPUT {
  struct Header header;
  union Data data;
};
Und auf 64bit-Windowsen ist data um 8 Byte verschoben. Das Problem ist Microsoft seit mindestens 2011 bekannt, aber die einzige Reaktion war, es als Note in die Doku mit aufzunehmen. Also hab ich mittels GetProcAddress() und IsWow64Process() ermittelt, ob ich das Buggy-Offset einberechnen muss, und dann in diesem Fall eine kleine fiese Zeigerbastelei ausgeführt, womit ich jetzt final korrekte RawInput-Daten gelesen bekomme.

Was für ein wirrer Mist. Aber ich freu mich, dass ich es rausgekriegt habe.

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 11.06.2015, 19:02
von Krishty
Erste Sahne! Wenn es ohne Nachrichtenschleife auskommt, muss ich ebenfalls bald darauf umstellen. Danke!

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 12.06.2015, 07:14
von Matthias Gubisch
Top bei der nächsten bastelei gleich mal ausprobieren :)
Danke schonmal für deine Mühe :)

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 12.06.2015, 13:27
von Schrompf
Zu früh gefreut. RawInput-Nachrichten entstehen anscheinend live jederzeit. Und wenn der Nutzer genau in der Zeit eine Eingabe ändert, wenn das Eingabesystem schon durch ist, aber die Nachrichtenschleife des Hauptprogramms noch nicht, dann geht dieses Eingabeereignis verloren. Was sich z.B. in steckenbleibenden Tasten bemerkbar macht.

Fuckfuckfuck. Irgendwie mit PeekMessage() vorsortieren bringt ja auch nix, dürfte die selbe Wirkung haben. Grmpf. Vielleicht kann ich ja irgendwie die MsgProc des Fensters auf mich umbiegen.

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 12.06.2015, 13:40
von Krishty
Schrompf hat geschrieben:Zu früh gefreut. RawInput-Nachrichten entstehen anscheinend live jederzeit. Und wenn der Nutzer genau in der Zeit eine Eingabe ändert, wenn das Eingabesystem schon durch ist, aber die Nachrichtenschleife des Hauptprogramms noch nicht, dann geht dieses Eingabeereignis verloren. Was sich z.B. in steckenbleibenden Tasten bemerkbar macht.
Verstehe ich nicht – die Nachrichtenschleife ist ja erst „durch“, wenn das Programm beendet. Wie genau ist die Abfolge?
  1. GetRawInputBuffer()
  2. Eingaben verarbeitet
  3. Anwender drückt Taste
  4. ???

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 12.06.2015, 13:56
von Schrompf
Die Reihenfolge ist:
  1. MyUpdate()
  2. .. GetRawInputBuffer()
  3. Beispiel-Anwender drückt Taste
  4. .. ProcessThoseRawInputEvents()
  5. Game's message loop
  6. .. while( PeekMessageW(..., PP_REMOVE) )
  7. .. oder auch irgendwo hier, Beispiel-Anwender drückt Taste, während Loop noch läuft
Mit der GetRawInputBuffer()-Methode bekomme ich sicher alle Events, die nach Abschluss der Spiel-Nachrichtenschleife und noch vor meinem GetRawInputBuffer() kommen. Ich verliere aber alle Ereignisse, die nach meinem GetRawInputBuffer() und noch vor Abschluss der Spiel-Nachrichtenschleife kommen.

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 12.06.2015, 14:17
von Krishty
Was machst du mit der Nachricht nach PP_REMOVE? Meine Intuition ist: So lange sie an die DefWindowProc() weitergeleitet wird, müsste sie im nächsten GetRawInputBuffer() auftauchen. ODER GetRawInputBuffer() sammelt nur jene Nachrichten, die in der Nachrichtenschleife NICHT abgeholt werden – dann musst du WM_INPUT in der Schleife lassen bzw. in deiner WndProc() mit return 0; quittieren bevor es DefWindowProc() erreicht.

Genau diese Unsicherheit, wann denn nun gesammelt wird und wann nicht, war der Grund, warum ich es nicht benutzt habe und mich jetzt so freute, dass du es herausgefunden hast :D

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 12.06.2015, 15:03
von Schrompf
Tja, da kann ich Dir ja auch nicht weiterhelfen. Da GLFW, was bei mir aktuell den ganzen Fenster- und Nachrichtenkram liefert, in seiner Message Loop WM_INPUT nicht verarbeitet, geht es dort am Ende in die DefWindowProc() rein. Und die gibt 0 für WM_INPUT zurück, was wohl bedeutet, dass die Nachricht konsumiert wurde. In meinem GetRawInputBuffer() taucht sie aber nicht auf. Dafür klingelt jetzt gelegentlich meine WNDPROC, die ich vor die Spiel-eigene WNDPROC gehängt habe.

Hässlich, aber jetzt funktioniert es verlustfrei. Theoretisch könnte ich jetzt alles mit dem WNDPROC-Hook abbilden, aber damit würden die akkumulierten Signale wie z.B. die Mausbewegung erst im nächsten Frame gemeldet werden. Um die Latenz etwas zu senken, betreibe ich jetzt auf Windows also eine Mischform aus GetRawInputBuffer() und WNDPROC-Hook, um die verlorenen WM_INPUT-Nachrichten einzufangen.

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 12.06.2015, 17:04
von Krishty
Hier wird gesagt, man dürfe WM_INPUT keinesfalls aus der Nachrichtenschleife holen, weil GetRawInputBuffer() nichts anderes macht, als ebendiese nach WM_INPUT abzugrasen. Ach scheiße; dann bleibt es für mich wertlos.

Ganz ab davon: Man sollte vorsichtig sein, wenn man Input-Ereignisse zusammenfasst, und dabei zumindest das Mapping weglassen. Das musste ich auf die harte Tour lernen, weil ich ja lieber zusammenfasse statt alles kreuz und quer zu verarbeiten:
  1. Anwender drückt ESC und LEERTASTE um ins Hauptmenü zu kommen und den ersten Menüpunkt auszuwählen
  2. Input wird gesammelt und übersetzt
  3. Beim Mappen der LEERTASTE befindet sich das Programm noch im In-Game-Modus statt im Menü-Modus und interpretiert die LEERTASTE falsch
  4. Spieler befindet sich nun im Menü, wunder sich warum nichts passiert, und die Spielfigur springt, sobald er fortsetzt
Und man bemerkt diese Fehler erst recht spät, wenn man sich so sehr an die Steuerung gewöhnt hat, dass man schneller wird als die Hauptschleife.

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 02.07.2015, 01:05
von Krishty
Beachtest du in SNIIS WM_SETFOCUS und WM_KILLFOCUS? Habe eben durch den Code geguckt, und nichts entsprechendes gefunden.

Hintergrund: Wenn man bei mir einen Screenshot macht, öffnet sich sofort der Speichern unter...-Dialog. WM_KEYDOWN und Konsorten verstummen dann, aber WM_INPUT kommt weiter an, obwohl alle Eingaben dem Dialog gelten sollten! Wenn ich einen Dateinamen mit Leerzeichen eintippe, springt der Charakter also, sobald der Dialog fertig ist. Selbes passiert, sobald man die Engine in einen Editor mit Controls einbettet usw. Darum unbedingt alles zwischen WM_KILLFOCUS und WM_SETFOCUS ignorieren.

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 02.07.2015, 10:12
von Schrompf
Nein, ich beachte das nicht. Das ist so beabsichtigt, es liegt in der Verantwortung des Nutzers, SNIIS stellt dafür nur SNIIS::InputSystem::SetFocus(bool) zur Verfügung.

Re: [Lib] SNIIS - Gesundheit! - Simple Non Intrusive Input L

Verfasst: 02.07.2015, 20:00
von Krishty
Wunderbar; das tut's natürlich genauso :)