Ich lasse mehrere Fenster zeichnen, die ineinander verschachtelt sind. Das Problem ist nun, dass ein Fenster 2, das in Fenster 1 steht, natuerlich nicht ueber den Rand von Fenster 1 hinausragen darf. Dazu wollte ich glScissors verwenden.
Mein Code dazu sieht folgendermaßen aus:
Code:
ifAssigned(ParentObject)then
begin
glEnable(GL_SCISSOR_TEST);
with ParentObject do
begin
glColor3f(1,0,0);
glBegin(GL_LINE_LOOP);
glVertex2f(Left, Top+Height);
glVertex2f(Left, Top);
glVertex2f(Left+Width, Top);
glVertex2f(Left+Width, Top+Height);
glEnd();
glScissor(Left, Top+Height, Width, Height);
end;
end;
Ich habe zwei Bilder, das erste zeigt, wie die Fenster ohne glScissors aussehen.
Das zweite zeigt, was bei glScissors passiert.
Wie man sieht, wird das Fenster 3 komplett weggeschnitten, habt ihr vielleicht ne Idee?
ist das 3. fenster kind des 2. fensters? dann ist der scissor nur auf das 2. fenster bezogen, missachtet aber, daß bereits das fenster 2 ne kind ist - du musst deinen scissor so bauen, daß er sich am ende rekursiv verhält und nicht immer nur die stufe oben drüber mit einbezieht, sondern alle darüber.
Ich hatte es so schonmal aber funktionieren tut es trotz allem nicht.
Code:
procedure TSE_GUI_Window_Custom.Draw;
var i:Integer;
begin
inherited;
ifAssigned(ParentObject)then
begin
if fText ='Window2'then
begin
glEnable(GL_SCISSOR_TEST);
with ParentObject do
begin
glColor3f(1,0,0);
glBegin(GL_LINE_LOOP);
glVertex2f(Left, Top+Height);
glVertex2f(Left, Top);
glVertex2f(Left+Width, Top);
glVertex2f(Left+Width, Top+Height);
glEnd();
glScissor(Left, Top+Height, Width, Height);
end;end;
end;
//Window Zeichnen
// Hier werden alle Kinder gezeichnet
for i :=0to fItems.Count-1do
(fItems.Objects[i]as TSE_GUI_Custom).Draw;
glDisable(GL_BLEND);
ifAssigned(ParentObject)then
glDisable(GL_SCISSOR_TEST);
end;
Problem ist, dass sich keinerlei aenderung zeigt.
Weiteres kuriosum: Beschränke ich die Beschneidung auf das Aeusserste Fenster (also das, das kein Parent hat) funktioniert es, allerdings wird dann innerhalb nicht abgeschnitten.
Bild dazu:
Habe hier nochmal ne Demo, wo Drag&Drop der Fenster funktioniert. Was da beim Ziehen passiert, versteh ich ueberhauptnicht...
http://shaddow89.sh.funpic.de/Desktop.rar
Tja nun habe ich noch einiges an meinem Programm umgestellt und bin bei Rekursionen gelandet.
Leider kann man ja immer nur eine Scissorbox initialisieren, sonst wäre mein Problem sehr viel einfacher zu beheben. Nun stehe ich aber vor dem folgenden:
Ich habe 3 Fenster:
Fenster1
Fenster2
Fenster3
Fenster3 ist Child von Fenster2
Fenster2 ist Child von Fenster1
Nun will ich im Fenster3 eine Scissorbox so setzen, dass das Fenster3 an den Grenzen von Fenster2 UND Fenster1 abgeschnitten wird. Logische Folge: Rekursion.
Ich gehe also immer weiter nach oben im Rekursionsbaum und vergleiche dann die einzelnen Werte der Fenster. Die Box die ich brauche, ist letztlich die kleinste, da sie sowohl von Fenster1 als auch Fenster2 beschnitten wird.
Das heisst effektiv:
Ich brauche den größsten Left und Topwert der Windows
und ich brauche den kleinsten Width und Heightwert der Windows
Die entstehende Box ist genau die, die durch beide Windows begrenzt wird
function TSE_GUI_Custom.GetInnerRect(InnerRect: TSE_Rect): TSE_Rect;
begin//ueberdenken
ifAssigned(ParentObject)then
Result := ParentObject.GetInnerRect(InnerRect)
else
begin
if fLeft + GlobalCoords[0] > InnerRect.Leftthen InnerRect.Left:= fLeft + GlobalCoords[0];
if fTop + GlobalCoords[1] > InnerRect.Topthen InnerRect.Top:= fTop + GlobalCoords[1];
if fWidth < InnerRect.Widththen InnerRect.Width:= fWidth;
if fHeight < InnerRect.Heightthen InnerRect.Height:= fHeight;
Result := InnerRect;
end;
end;
Die erste funktion erstellt nur die Variable. TSE_Rect ist ein Record aus Left, Top, Width und Height.
Diese Variable wird an die Rekusive Funktion GetInnerRect uebergeben. Da drin sollen nun die Werte verglichen. Alle Werte sind relativ zum uebergeordneten Objet, das heisst, Left und Top sind immer relative Werte. Width udn Height sind es ja sowieso da sie von Left und Top abhaengen. Da die resultierende Box aber nach globalen Koordinaten bestimmt werden muss, wird GlobalCoords addiert. Das sind jeweils die errechneten Globalen Koordinaten des Fensters.
Leider funktioniert das nicht, die Scissorbox wird immer irgendwo in der Weltgeschichte initialisiert...
(Die methoden sind überladen
gglMin gibt den kleineren der beiden übergebenen Werte zurück.)
Um die Scissor-Box zu erhalten, muss das untere Aufgerufen werden, also ohne Parameter. Dies ruft dann rekursiv die funktion mit Parameter des Eltern-Elementes auf. Das funktioniert soweit eigentlich ganz gut.
FClientMargins sind Ränder, die ein Offset bilden, sodass die Controls nicht immer direkt am Elternelementrand hängen, kannst du aber natürlich auch weglassen.
Dann habe ich noch folgende Funktion um das Y-Koordinaten-Problem zu lösen:
Code:
function ConvertGuiRectToOpenGLRect(ARect: TguiRect; ScreenHeight:Integer): TguiRect;
Damit wird der Y-Wert umgewandelt, sodass das Scissoring auch so funktioniert, allerdings braucht man dazu die höhe des Viewports (oder der Zeichenfläche?).
Du darfst die Sourcecodes ohne weiteres kopieren, wäre aber über eine nennung in den Credits (am besten mit Link) dankbar
Gruß Lord Horazont
//Edit: Ach ja, bitte verlink die Bilder das nächste mal, vielleicht auch mit Thumbnail. Das Seitwärtsscrollen um dann einen Beitrag zu lesen nervt ein wenig.
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Mh naja ich muss nich scrollen ^^ deswegen isses mir vllt nicht aufgefallen
Also ich habe vorhin schonmal etwas weitergebastelt und im Grunde geht es jetzt. ich haette natuerlich nicht 'im Grunde' geschrieben, wenn jetzt nicht das Aber kaeme
if fWidth < InnerRect.Widththen InnerRect.Width:= fWidth;
if fHeight < InnerRect.Heightthen InnerRect.Height:= fHeight;
Result := InnerRect;
end
else
begin
InnerRect.Left:= fLeft;
InnerRect.Top:= fTop;
InnerRect.Width:= fWidth;
InnerRect.Height:= fHeight;
Result := InnerRect;
end;
end;
Wenn cih nun im Fenster1 SetScissors aufrufe, wird alles wunderbar abgeschnitten.
Allerdings wird Fenster3 nur an den Raendern von Fenster1 und nicht von Fenster2 abgeschnitten.
Wenn ich jetzt aber (Achtung: Kuriosum) die Scissors nur um Fenster2 aktiviere, wird Fenster3 an den Raendern von Fenster2 wunderbar abgeschnitten (aber logischerweise wieder nichtmehr an den Raendern von Fenster1).
Im Grunde muesste aber Fenster3 an Fenster1 und Fenster2 abgeschnitten werden, zumal der Schnitt an Fenster2 ja durch den Test geht. Wenn ich Fenster1 zeichne, nutzt er eine Scissorbox in der Größe des gesamten SDLFensters, da Fenster1 ja das oberste Parentelement ist und daher keine Begrenzungen hat, ausser das SDLFenster selber.
Wenn Fenster1 fertig gezeichnet ist, dann geht er zu Fenster2 und nutzt die dort errechnete Scissorbox, und die ist jetzt mit den Größen von Fenster1 gefuellt. Bis dahin klappt die Rechnung. Ist Fenster2 fertig, gehts noch ein childelement tiefer zu fenster3 und nun muesste an den Grenzen von Fenster1 und Fenster2 abgeschnitten werden, aber nun wird nur an Fenster1 abgeschnitten...
Wenn ich mir deinen Code ansehe, ist es ja im Grunde beinahe das Gleiche. Nur meins geht halt nicht richtig ^^
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Ja, beinahe und ich glaube da haperts.
So wie ich das sehe, hast du ja ein problem mit höhe und breite. Das Problem hatte ich auch am Anfang und es lag an der Zeile mit gglMin. Du machst das nicht genauso wie ich. Versuch doch mal, meinen Code auf deine Klassenstruktur anzupassen.
Wenn es dann klappt, kann ich dir auch erklären weshalb, aber im Moment sitze ich an einem fremden Rechner, daher habe ich nicht so viel Zeit.
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Also ich hab mal n bissel was durchgetestet und offenbar liegt es nicht an diesem Vergleich.
Mein Vorgehen ist ja beim Zeichnen wie folgt:
Die Scissorbox von Window1 wird gesetzt
Dann wird WIndow1 gezeichnet
Dann wird geht er in alle Childobjekte
Die Scissorbox von Window2 wird gesetzt
Dann wird Window2 gezeichnet
Und ich verstehe nicht, warum du da hinten noch etwas subtrahierst. Zumal das bei mir eh nicht geht, weil dann Width und Height bei mir negative Werte annehmen.
Wenn meine Box bei 200,200 erzeugt wird und 50 breit und 50 hoch ist, dann würde nach deiner Rechnung die neue Breite und Hoehe bei -150 liegen. Versteh ich nicht
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Du musst aber eines Bedenken:
Die Left und Top-Koordinaten sind wegen der Rekursion und der Befehlsreihenfolge noch die des Child-Fensters. Daher kann das stimmen, weil so verhindert wird, dass dieses über den Rand zeichnet.
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Ich musste zwar auch erstmal in meine alten Unterlagen schauen (ist schon etwas länger her, dass ich den Algo geschrieben habe) aber jetzt kann ich es dir anhand der beigefügen Grafik zeigen.
//Edit: Das gleiche Gilt für die Breite, aber natürlich alles auf der Y-Achse
Gruß Lord Horazont
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Mitglieder in diesem Forum: 0 Mitglieder 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.