Hi,
ich bin jetzt bei meinem Projekt an einem Punkt angekommen, an dem ich mich um das Interface kümmern muss. Könnte mir jemand sagen, wie man am besten Dinge wie Popup Menü, Label, Checkboxen, (Buttons), Scrollbalken, Progressbars mit OGL realisiert. Hab da schon ein bisschen rumprobiert, aber nicht wirklich was zustande bekommen.
Gruß T3rm1
Registriert: Fr Mai 14, 2004 18:56 Beiträge: 804 Wohnort: GER/OBB/TÖL-WOR/Greiling
du kannst das im Orthomodus machen, und einfach nach dem 3d-rendern die GUI komplett drüber rendern. ich bin da auch gerade am rumprobieren.
am besten baust du dir eigene kleine klassen, die sich z.b. mit einer im Create erzeugten Displaylist rendern lassen. und natürlich texturen.
am schönsten sieht das ganze aus, wenn du mit blending noch transparenz reinmachst. ist auch genial einfach umzusetzen, wenn du tga's, glBitMap und das Phobs Tut ( http://www.delphigl.com/script/do_show.php?name=lesson7&action=2 ) dein eigen nennen kannst.
events musst du dann wohl global abfangen und weiterleiten, z.b. durch entscheidungen anhand der dimensionen der quads.
(vielleicht ist es sogar möglich, dafür wndprocs zu registrieren... ich weiss es aber nicht.)
Registriert: Sa Mai 04, 2002 19:48 Beiträge: 3830 Wohnort: Tespe (nahe Hamburg)
Nun der Hinweis von Luke ist schon der wohl beste Weg. Via Ortho einfach eine GUI zeichnen. Damit sind dann auch gleich die Positionen bekannt, die dann bei den entsprechenden Tasteneingaben oder Maussteuerung verarbeitet werden können. Ein schönes "Praxis-Beispiel" dafür hat Jan Horn einst geschrieben: http://www.sulaco.co.za/opengl2.htm#windows
_________________ "Light travels faster than sound. This is why some people appear bright, before you can hear them speak..."
OK, das mein ich nicht Mich interessiert eher der Teil der Klasses. Wovon soll ich sie ableiten? Was muss da alles rein. Wie kann ich zum Beispiel beim Edit Feld etwas eingeben, makieren und löschen.
Registriert: Sa Mai 04, 2002 19:48 Beiträge: 3830 Wohnort: Tespe (nahe Hamburg)
Nun der Hinweis von Luke ist schon der wohl beste Weg. Via Ortho einfach eine GUI zeichnen. Damit sind dann auch gleich die Positionen bekannt, die dann bei den entsprechenden Tasteneingaben oder Maussteuerung verarbeitet werden können. Ein schönes "Praxis-Beispiel" dafür hat Jan Horn einst geschrieben: http://www.sulaco.co.za/opengl2.htm#windows
_________________ "Light travels faster than sound. This is why some people appear bright, before you can hear them speak..."
Registriert: Do Sep 25, 2003 15:56 Beiträge: 7810 Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Auf alle Fälle ist hier zu sagen, dass an dieser Stelle du über Leben und sterben deines Codes entscheidest.
In meinem Aktuellen Projekt, welches kurz vor der Veröffentlichung steht, hatte ich auch das Problem. Ich hab alles von TObject abgeleitet und viel zu Viel Publick gehalten, also die OOP Kapselung nicht wirklich durchgezogen. Folge: Dirty Programming schlimmster Sorte. Den Code kann ich nach Ende des Projekts nur wegschließen und nie wieder angucken.
Ne Idee der Herangehensweise wäre:
Dein Programm ist die Vater/Mutterklasse und enthält eine Eigenschaft "SubMenüs" (TList). In dieser Liste stehen alle Submenüs, nach sichtbarkeit sortiert drinnen. DU musst dann immer die Liste durchlaufen und die einzelnen Menüs nacheinander Zeichnen. Jedes Menü selbst kann wieder Submenüs enthalten. Außerdem besitzen deine Menüs noch eine Liste. Diese enthält alle Steuerelemente wie Editboxen und Button.
Wenn der Nutzer Klickt, schnappst du dir die Koordinaten und sucht in der Liste nach dem Menü was an der Stelle sichtbar ist, und dann nach dem Steuerelement, was an der Stelle aktiv ist. Das ist das Geklickte Element.
Außerdem sollten deine Menüs noch eine Eigenschaft "Fokus" haben. Damit kannst du Tastatur eingaben einem Steuerelement zuordnen.
So das wäre mein grober anstatz. Aber eine Warnung sein Ausgesprochen:
Konzipiere die GUI mit Hirn. Denk lieber zwei Tage darüber nach und mach ne Menge Skizzen und Diagramme. Wenn du anfängst die GUI zu benutzen um Daten zwischenzuspeichern (Spieldaten) dann läuft was falsch. Die GUI sollte nur zur ausgabe dienen und dein Programm sollte rein Inhaltlich auch ohne die GUI laufen. Wenn das nicht der Fall ist, dann ist das Konzept FALSCH. (Genau das ist bei mir der Fall.... )
_________________ Blog: kevin-fleischer.de und fbaingermany.com
Registriert: So Sep 26, 2004 05:57 Beiträge: 190 Wohnort: Linz
Also zum Design kann ich dir mal sagen wie ich das bei mir gemacht hab.
Alle UI-Elemente sind abgeleitet von einer Frame-Klasse welche die Grundlegenden Informationen besitzt die du für jedes Fenster brauchen kannst. Diese da wären (je nach bedarf):
- Eindeutige ID
- Position / Größe
- Sichtbar / Unsichtbar
- Modal / Nicht Modal
- Besitzt Focus oder nicht (wird von einem Manager gesetzt)
- Ist dieses Fenster ein Popup oder nicht (um es verschwinden zu lassen wenn die Maus das Fenster verlässt)
- Ein Pointer / Referenz auf das Popup Fenster welches bei Rechtsklick oder dergleichen erstellt werden soll (oder auch gar keines)
- Fenstertitel also das WndText der WinAPI, is für viele Sachen brauchbar
- Fensterdaten die vom Benutzer gesetzt werden können (also einfach ein int) entspricht dem WndData
- Bild bzw. Textur + Texturcoordinaten
- Verschiebbar oder nicht
Ein paar dieser Daten könntest du eventuell noch Auslagern in einen Manager (zB den Focus), aber du solltest auf alle Fälle eine Methode beim Frame haben im Sinne von HasFocus().
Zusätzlich besitzt dieses Frame noch virtuelle (wie hieß denn das in Delphi noch mal?) Methoden für alle allgemeinen Events, also OnCreate, OnKeyPressed, OnMove, ... die ergeben sich dann eh automatisch :-). Ein abgeleitetes Steuerelement überschreibt jetzt diese OnXY - Methoden, hat eventuell weitere Bilder (zB Button gedrückt, losgelassen und evntl. Rollover Effekt). Komplexe Steuerelemente bestehen aus mehreren einfacheren, wo du dir dann aussuchen kannst ob du diese einfacheren Steuerelemente manuell übergeben willst, oder ob zB eine Listbox von selber weiß wie breit die Scrollleiste sein soll und wie sie ausschauen soll.
Das Frame ist nun abgeleitet von einer EventSource - Klasse die primär die Funktionen hat:
- RegisterReceiver( EventID, BaseObjekt *Klasse, Callback *Methode )
- PostMessage( EventID, Daten für Callback zb: LParam, WParam )
Von aussem machst du jetzt beispielsweise ein:
MyButton.RegisterReceiver( ON_BUTTON_PRESSED, this also mich selbst halt, Pointer auf Methode die darauf reagieren soll )
Das Button-Steuerelement (von Frame abgeleitet) überschreibt jetzt die On_linke_Maustaste_in_mir_gedrückt/losgelassen() so, dass die OnButtonPressed-Methode aufgerufen wird. Die OnButtonPressed-Methode löst nun wiederum ein PostMessage( ON_BUTTON_PRESSED, ... ) aus.
Idealer Weise hast du deine Callback-Funktionalität so weit gekapselt, dass du später beispielsweise auch über eine Konsole oder die Tastatur ein Event wie "Button XY gedrückt" schicken kannst.
Das ganze hat nun zur Folge das du das verhalten von Steuerelementen auf 2 Arten recht einfach festlegen kannst:
1. Durch ableiten (von zB Button) wodurch du volle Kontrolle darüber erhältst (wenn du möchtest) wie der Button gezeichnet wird, wann welches Event ausgelöst wird, ...
2. Durch das registrieren von Callback-Funktionen die dann nur auf Events reagieren und halt eher beschränkten Zugriff auf die jeweilige Klasse besitzen (Zeichenfunktion kann zB nicht so ohne weiteres überschrieben werden).
Weiter gehts mit der Ableitung noch mit einem BaseObjekt das mir Runtime Type Information (RTTI) liefert, also im Sinne von: Erstelle Klasse mit dem Namen: "ListBox", oder auch: von welchem Typ ist Klasse xy?
Die größte Entscheidung die du noch treffen musst ist die, ob du die Frames in einem Manager verwaltest, also so das dieser Manager eine Baumstruktur mit Pointer auf Frames besitzt, oder ob du jedem Frame die Kinder gibst.
Wenn du es als Baumstruktur in einer Manager-Klasse verwaltest dann hast du den Vorteil, dass der Code zum Verwalten der Fenster sehr gut vom Code der das Verhalten der Fenster definiert getrennt ist. Dafür hast du bei den einzelnen Fenstern nicht mehr ganz so viele Möglichkeiten, ich hab diese Möglichkeiten jedoch noch nie wirklich vermisst.
Wenn du jedes Frame seine Child-Fenster selbst verwalten lässt, dann bläht sich halt die Frame Klasse noch ein bisserl auf und ein unerfahrener Benutzer (der kein Hintergrundwissen zu deinem GUI-System besitzt) könnte auch Funktionen überschreiben, die die gesamte Funktionalität etwas negativ beeinflussen.
Die größte Herausforderung bei mir war dabei (bzw. ist immer noch ... noch ned ganz fertig damit) das ganze ordentlich editierbar zu machen, und zwar für einen Grafiker. Wenn du dein GUI im Quellcode erstellen willst, im Sinne von: Button hier, Edit-Feld dort, Scrollbar da, dann stellen sich diese Probleme weniger. Wenn du allerdings in einem Editor einen großteil deines GUI erstellen möchtest, dann solltest du dir vorher ordentlich Gedanken darüber machen wie du:
- einzelne GUI-Elemente identifizierst (Name, ID, ...)
- auf Events dieser GUI-Elemente reagierst
- komplexere GUI-Elemente die aus mehreren einfachen Elementen bestehen realisierst (eine Listbox mit Scrollbar die du im Editor einfügst muss irgendwo / irgendwie auf die Scroll-Events reagieren).
Und das mit möglichst wenig Code (umsonnst soll der Editor ja auch nicht sein :-) ).
Generell lässt sich noch sagen, dass es für GUI-Systeme extrem viele brauchbare Design Patterns gibt, also spontan fällt mir da mal Dekorator, Kompositum, Observer und Zuständigkeitskette ein gibt aber sicher noch ein paar andere. Und wie meine Vorgänger schon erwähnt haben: abschauen Hilft in diesem Fall sehr viel.
Ach ja und wenn du zuerst auf dem Holzweg bist ... so ein GUI-System lässt sich recht einfach ändern. Der Haupt-Bestandteil sind die Frame und die Manager-Klasse. Der Rest ist zwar auch etwas mehr Schreibaufwand aber dennoch in 30 Min / Klasse erledigt. Das aufwändigste Steuerelement was ich zur Zeit habe ist ein mehrzeiliges Eingabefeld wo du mit der Maus markieren, ausschneiden, löschen, ... kannst und auch der Aufwand dafür hält sich in Grenzen, is halt eine Frage des Perfektionisum :-). Also wenn du dich entschließt das Ganze etwas anders aufzuziehen, dann isses üblicherweise ein Aufwand von ein paar Stunden, es sei denn dein voriges System war komplett anders, was ich bei GUI-Systemen allerdings kaum glauben kann, da alle gewisse Ähnlichkeiten besitzen.
Hoffe ich konnte ein bisschen helfen. Wenn du noch konkretere Fragen zu einem der Teile (Callbacks, RTTI, ...) hast kann ich auch gern mit etwas Code behilflich sein, jedoch nur mit C++ :-).
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2623 Wohnort: Berlin
Programmiersprache: Go, C/C++
Ich denke wie Lyr es gemacht hat ist der beste weg, meine GUI Unit ist basiert auf ähnlichem Prinzip und hat sich in Sachen flexibilität und einfachheit bisher mehr als ausreichend erwiesen. Meine GUI ist unter http://x-dream.sourceforge.net unter cvs zu finden. Ich hab eine GL_Object Objekt angelegt und diesem alle nötigen grundlagen wie zeichnen, event und andere nötige dinge eingebaut. Dann werden alle GUI Elemente davon abgeleitet und erweitert oder überschrieben. Ein GUI_Manager sorgt für das korrekte rendern,eventhandling und erzeugen. Der vorteil liegt darin das man so in wenigen sekunden von SDL Events, wie ich sie verwende, auf Windows oder Linux Events umstellen kann oder wen es gefällt auch Glut events nutzen kann. Wie in Delphi gewohnt kann man für jedes Element Events wie OnDraw,OnMousemove,OnMouseclick,OnMousedown und so weiter nutzen. Wenn diesen was anderes als nil zugewiesen ist wird die Orginalfunktion des Elements nicht verwendet sondern das selbst zugewiesene Element. So kann man leicht das aussehen eines Elementes verändern ohne das es sich auf die anderen auswirkt.
MfG TAK2k4
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.