So, meine GUI nimmt langsam (nebenbei will ja noch ein Chemiestudium bestritten werden ^^) aber sicher Form an. Die Grundklasse, von der ich alle Komponenten ableiten will, die in Interaktion mit dem Benutzer treten steht kurz vor der Fertigstellung - es fehlt nur noch eine Winzigkeit, um die es hier gehen soll.
Also, Erklärung zum Screenshot: Ihr seht da 4 Quadrate, rot, grün, blau und weiß. Die drei farbigen Quadrate sind "eigenständige" (nur dem GUI-Manager untergeordnete) Kontrollelemente. Sie reagieren auch korrekt auf die gängigen Mausereignisse (MouseMove, MouseEnter, MouseLeave, MouseClick, MouseDown, MouseUp). Das weiße Quadrat ist nicht direkt dem GUI-Manager untergeordnet, sondern dem roten Quadrat - hier wird mir von Mausereignissen als Sender dummerweise das rote Quadrat gemeldet...und das ist das Problem, der Sender sollte natürlich das weiße Quadrat sein.
Hier noch ein bisschen Quellcode:
1.: TglGUIManager.FindMouseEvent: Diese Prozedur wird aufgerufen sobald in der Form, auf der sich der Rendercontext befindet ein Mausereignis stattfindet.
Code:
Function TglGUIManager.FindMouseEvent(MouseX:Integer; MouseY:Integer): TglControl;
var
i:Integer;
PixelData:LongInt;
Index:Integer;
glMouseX, glMouseY:Integer;
begin
// 1. Mausposition OpenGL-konform umrechnen
glMouseX := MouseX;
glMouseY := Home.ClientHeight- MouseY;
// 2. Momentan gesetzte OpenGL-Attribute sichern und Buffer leeren
glPushAttrib(GL_ALL_ATTRIB_BITS);
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
// 3. Blending, Alpha und Texturierung deaktivieren, um Selektionsfarben nicht
// zu verfälschen, außerdem Scissor setzen.
glDisable(GL_BLEND);
glDisable(GL_ALPHA);
glDisable(GL_TEXTURE_2D);
glEnable(GL_SCISSOR_TEST);
glScissor(glMouseX, glMouseY,1,1);
// 4. Alle untergeordneten Objekte, die auf Ereignisse reagieren können zeichnen
for i :=0toHigh(Children)do
if Children[i].InheritsFrom(TglControl)then
(Children[i]as TglControl).Render(True);
// 5. Farbinformationen auslesen und in Index umrechnen
// Nur das sich keiner wundert: Ich kann im Editor einstellen, ob ich die
// "Szene" in Selektionsfarben sehen will. Damit ich da nicht nur schwarz sehe
// die Multiplikation mit 150.
i :=(Index +1)*150;
r := iv[0]* fac; g := iv[1]* fac; b := iv[2]* fac;
// 5. Farbe setzen, rendern.
glColor4f(r, g, b,1);
glBegin(GL_QUADS);
glVertex3f(0,0,0);
glVertex3f(Width,0,0);
glVertex3f(Width, Height,0);
glVertex3f(0, Height,0);
glEnd;
glPopMatrix;
end;
end;
3.: TglControl.FindMouseEvent Siehe TglGUIManager.FindMouseEvent: Wird aufgerufen um rauszufinden, ob ein "Kind" des zunächst als getroffen festgestellten Objekt getroffen wurde.
Code:
Function TglControl.FindMouseEvent(glMouseX:Integer; glMouseY:Integer): TglControl;
var
i:Integer;
PixelData:Longword;
Index:Integer;
begin
// 1. Buffer wieder löschen (Tiefenpuffer ist testweise auskommentiert,
// Selektion funktioniert auch mit gelöschtem Tiefenpuffer nicht)
glClear(GL_COLOR_BUFFER_BIT{ or GL_DEPTH_BUFFER_BIT});
// 2. Alle untergeordneten Kontrollelemente in Selektionsfarben zeichnen
for i :=0toHigh(Children)do
if Children[i].InheritsFrom(TglControl)then
(Children[i]as TglControl).Render(True);
// 3. Pixelfarbe an Mausposition auslesen, Index ausrechnen
// 4. Wenn kein Objekt getroffen wurde, wurde das Hauptobjekt getroffen, sonst...
if Index =-1then
Result :=Self
else
Result :=(Children[Index]as TglControl).FindMouseEvent(glMouseX, glMouseY);
end;
Da die Selektion auf "Rootebene", also der Ebene gleich über dem Manager funktioniert, scheint der Fehler irgendwo in 3. zu liegen, aber ich finde ihn einfach nicht...vielleicht (hoffentlich) kann mir hier ja jemand helfen.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Zuletzt geändert von zoiX am Sa Jan 30, 2010 17:41, insgesamt 2-mal geändert.
Peinlich....20 Minuten nach dem ich den Thread erstellt hatte bringt ein Einkauf und das damit verbundene Sinnieren über ein völlig anderes Problem (Was esse ich heute?) die Erleuchtung...
Hatte schlichtweg vergessen, wenn ich die "Kinder" in Selektionsfarben zeichne, vorher den Ursprung auf den Ursprung des übergeordneten Objektes zu setzen.
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2623 Wohnort: Berlin
Programmiersprache: Go, C/C++
Colorpicking ist eine recht langsame variante GUI picks zu machen und meiner meinung nach garnicht notwendig. Die meisten Spiele nutzen entweder 2d Boxed intersection oder 2d/3d vectorbased intersection. Ich kann dir 2D Boxed intersection empfehlen, da es so ziemlich das schnellste ist und für die meisten Projekte völlig ausreichend ist.
Code:
If (Mouse.X>Elmt.Position.X && Mouse.X<Elmt.Position.X+Elmt.Position.Width && Mouse.Y>Elmt.Position.Y && Mouse.Y<Elmt.Position.Y+Elmt.Position.Height)
return true;
else
return false;
Vector intersection wird im Professionellen Bereich oft verwendet.
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Ich hab mir schon fast gedacht das sowas kommt, und mir auch selbst schon Gedanken gemacht, ob ein "geometriebasiertes" Picking für mich nicht besser wäre, aber ich will auch nicht-rechteckige (und nichtmal zwingend viereckige) Kontrollelemente "verbauen", und weiß nicht genau, wie ich Treffer da basierend auf der Geometrie finden soll. Ich bin nicht besonders fit in Geometrie, und die Frage, ob ein Punkt innerhalb eines Dreiecks liegt stellt mich schon vor eine große Hürde, wenn ich sie mittels eines Algorithmus beantworten soll.
Ja....schaut ja denkbar einfach aus o.O Das man auf sowas nicht selber kommt... Hatte gerade eben auch noch gegoogelt und auch ne Methode, die nicht allzu kompliziert klang gefunden, aber die Methode über die Flächen ist einfach großartig. Und auch auf höhere n-Ecke verallgemeinerbar, ohne sie auf Dreiecke zu vereinfachen, wenn ich mich recht entsinne.
Da wird meine Geometrie-Unit heute abend wohl noch ein paar Prozeduren lernen...
Mitglieder in diesem Forum: Google [Bot] und 9 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.