Autor Wątek: My own GUI ;P  (Przeczytany 10372 razy)

Offline Kos

  • Użytkownik
    • kos.gd

# Czerwiec 21, 2009, 20:12:59
A tak z ciekawości, to jak się w praktyce rozwiązuje tworzenie bardziej złożonych layoutów przy takim paradygmacie?

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Adam B

  • Użytkownik

# Czerwiec 21, 2009, 21:35:34
Nie czytałem jeszcze o: Immediate Mode GUI, ale moje GUI ma składać się z 3 klas głównych a właściwie z 2 klas bo jedna klasa to będzie abstrakcyjna tylko do dziedziczenia. Wszystko ma się opierać na klasie Window i Button.

poopa

  • Gość
# Czerwiec 21, 2009, 22:11:47
Cytuj
Jezeli nie bedzie nigdy obslugi innego api graficznego to bedzie to tylko kolejna niepotrzebna warstwa abstrakcji.
Są przynajmniej dwa powody, by dodać tą warstwę:
1. Można w niej umieścić rzeczy specyficzne dla danego API (np. w przypadku OpenGL i DirectX zrobić batching prymitywów - bez wplanowanego batchingu nie ma co nawet zaczynać robić GUI).
2. GUI ma być pod OpenGL, więc warto zabezpieczyć się na przyszłość, jak już przyjdzie do przesiadki na Direct3D.
Ad. 1. Majac klase pt. Graphics ktora z zalozenia jest tylko  klasa utility ("uzytecznosc") ktora obudowuje odwolania do ogl-a juz samoistnie stworzylismy "interfejs" do API. Poniewaz miksowanie rendererow jeszcze nikomu na dobre nie wyszlo, obsluge innego API (niz te na ktorym zaczelismy ) mozemy zalatwic poprzez #define-y (w jednym z silnikow na forum, renderery ladnie byly schowane w .dll-ach). Probowalem rzeczonego podejscia IRenderer na sile... okazalo sie to tylko niepotrzebnie napisanym kodem(czyli smietnikiem) i z racji calej serii wyjatkow (ciezko uogolnic interfejs bez wielkich kompromisow) musialem go przepisywac, poprawiac kilkakrotnie. Nie ma po prostu co sie palic do tego... jezeli zrobic to dobrze to jest tam sporo nadprogramowej roboty (np. wypadaloby przetestowac wszystkie dostepne API w danej dziedzinie pod kompatybinosc z naszym interfejsem w calym zakresie).

Ad. 2. "Jak"? Chyba jezeli. I dlaczego przesiadki? Chyba rozbudowy silnika o obsluge d3d.

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Czerwiec 21, 2009, 22:34:00
A tak z ciekawości, to jak się w praktyce rozwiązuje tworzenie bardziej złożonych layoutów przy takim paradygmacie?
Na ile "bardziej"? W moim wykonaniu cały obszar podzielony jest na okna (patrz: Blender), a każde okno ma jakąś funkcję rysującą. Do tego jest sporo funkcji pomocniczych rysujących i zajmujących się obsługą przycisków, editboxów, comboboxów, treeview i podobnych. Z layoutem nie ma problemu, bo najczęściej i tak wykorzystuję property gridy (po lewej tree view, po prawej kontrolki w układzie liniowym). Oczywiście property grid i jego drzewo nigdzie nie jest fizycznie przechowywane (jak to w immediate mode bywa), więc można tam wyświetlić co się żywnie podoba - kwestia napisania prostej funkcji printującej co trzeba. :)

Cytuj
lasa utility ("uzytecznosc")
Nie wiem skąd wytrzasnąłeś takie tłumaczenie słowa utility, ale w tym kontekście ono nijak nie pasuje. "utility" == "przydatne narzędzie/urządzenie"

Cytuj
obsluge innego API (niz te na ktorym zaczelismy ) mozemy zalatwic poprzez #define-y
Z uwagi na różnice między API, jest to taki sobie sposób.

Cytuj
(w jednym z silnikow na forum, renderery ladnie byly schowane w .dll-ach)
Przy okazji ładnie komplikowały prosty program. ;)

Cytuj
Probowalem rzeczonego podejscia IRenderer na sile... okazalo sie to tylko niepotrzebnie napisanym kodem(czyli smietnikiem) i z racji calej serii wyjatkow (ciezko uogolnic interfejs bez wielkich kompromisow) musialem go przepisywac, poprawiac kilkakrotnie.
Jakiego typu wyjątków? Do GUI wystarczy zestaw podstawowych operacji, a do tego nie potrzeba wielkiej filozofii. Przykładowo API do rysowania grafiki 2D w Allegro, GDI, .NET, czy Javie są na tyle podobne, że gdyby nie różnice wspieranych języków, nie było by większych problemów z ich uogólnieniem. W przypadku API akcelerowanych sprzętowo jest może delikatnie inna filozofia, ale nie jest to też większy problem - w moim przypadku po prostu dodałem wymaganie, że cała grafika i fonty są zawczasu spakowane w jeden atlas tekstur i tyle wystarczyło, żeby całkowicie odciąć się od API pod spodem. :)

Cytuj
(np. wypadaloby przetestowac wszystkie dostepne API w danej dziedzinie pod kompatybinosc z naszym interfejsem w calym zakresie)
Jak wyżej. Piszesz własne API, więc robisz takie funkcje, jakie są Ci potrzebne - narysuj linię w danym kolorze, obrazek i tym podobne. Wrapper pod spodem już dba o szczegóły, jak to najlepiej połączyć z danym API. Przykładowo w przypadku mojego 2D wrappera na D3D wrapper sam już pakuje wszystko w jedną indeksowaną tablicę wierzchołków, zmienia linie na quady oteksturowane jednym pikselem (żeby można było dokładnie wszystko wrzucić do jednej listy) i rysuje dopiero wtedy, gdy trzeba, albo nazbiera mu się wystarczająco geometrii (np. 1000 quadów). Sama aplikacja nie ma żadnej świadomości, że tam dzieje się coś takiego. :)

Cytuj
Ad. 2. "Jak"? Chyba jezeli. I dlaczego przesiadki? Chyba rozbudowy silnika o obsluge d3d.
OpenGL i D3D są na tyle podobne, że bez większych problemów można napisać wspólny interface 2D - jedyną różnica jest to, że w przypadku D3D trzeba przesunąć całą grafikę o 0.5 piksela.

Co do przesiadki, wiem jak to jest, bo sam zaczynałem od OpenGL i dość długo w nim siedziałem. Stadia są następujące:
- Zagorzały zwolennik OpenGL.
- "A dlaczego by nie zajrzeć w końcu co tak naprawdę jest w tym drugim API?"
- Nauka drugiego API (bo zawsze lepiej umieć dwa niż jedno).
- Pisanie w D3D dla zabawy.
- Chęć napisania przenośnego silnika (OpenGL/Direct3D).
- Chęć napisania przenośnego silnika (Direct3D/OpenGL).
- Rodzące się pytanie, po co zajmować się OpenGL.
- Pisanie wyłącznie w Direct3D.

Osobiście myślę, że czeka to każdego (nie dotyczy użytkowników Linuksa), chyba że ktoś jest ignorantem i woli OpenGL od Direct3D (pomimo że nie ma pojęcia jak się w Direct3D pisze), albo z jakiegoś powodu przy OpenGL zwyczajnie się upiera. :)

Offline Dab

  • Redaktor
    • blog

# Czerwiec 21, 2009, 22:58:20
Proponuję przerzucić się z tym mimo wszystko do wątku "OpenGL vs DirectX". :)
Ja nie czuje się ignorantem (przynajmniej jeżeli chodzi o OGL), a GL 3.1 robi duży krok naprzód (poza tym że nie jest jeszcze w praktyce nigdzie zaimplementowane i prawdopodobnie cała reszta świata poza NVidią będzie miała problemy z kompatybilnością). Anyway, czuje się szczęśliwy, ponieważ mam dostęp chociażby do GS nie wymagając wciąż niezbyt popularnej Visty.

Offline Avaj

  • Użytkownik

# Czerwiec 21, 2009, 22:59:01
Cytuj
Ad. 2. "Jak"? Chyba jezeli. I dlaczego przesiadki? Chyba rozbudowy silnika o obsluge d3d.
OpenGL i D3D są na tyle podobne, że bez większych problemów można napisać wspólny interface 2D - jedyną różnica jest to, że w przypadku D3D trzeba przesunąć całą grafikę o 0.5 piksela.

Co do przesiadki, wiem jak to jest, bo sam zaczynałem od OpenGL i dość długo w nim siedziałem. Stadia są następujące:
- Zagorzały zwolennik OpenGL.
- "A dlaczego by nie zajrzeć w końcu co tak naprawdę jest w tym drugim API?"
- Nauka drugiego API (bo zawsze lepiej umieć dwa niż jedno).
- Pisanie w D3D dla zabawy.
- Chęć napisania przenośnego silnika (OpenGL/Direct3D).
- Chęć napisania przenośnego silnika (Direct3D/OpenGL).
- Rodzące się pytanie, po co zajmować się OpenGL.
- Pisanie wyłącznie w Direct3D.

Osobiście myślę, że czeka to każdego (nie dotyczy użytkowników Linuksa), chyba że ktoś jest ignorantem i woli OpenGL od Direct3D (pomimo że nie ma pojęcia jak się w Direct3D pisze), albo z jakiegoś powodu przy OpenGL zwyczajnie się upiera. :)
Kto zasiewa burzę ten zbiera wiatr. U mnie te stadia wyglądają zupeeełnie inaczej :P

Ja z moim GUI nie kombinują tak jak wszyscy tutaj. U mnie GUI jest oddzielone od renderingu, ale rendering jest ustawiony na sztywno na OpenGL. Każdy element interfejsu (przycisk itp.) ma kilka funkcji takich jak onDrag, onClick. W przypadku np. przycisku, onClick jest callbackiem, zaś w przypadku np. scrollbara onClick jest funkcją która obsługuje tylko ten scrollbar i nie jest to wtedy callback. Jak na razie działa dobrze, bez przekombinowania :)

Offline Adam B

  • Użytkownik

# Czerwiec 21, 2009, 23:01:02
Z tym OpenGL i Direc3D to masz racje - sam już od dłuższego czasu myślę o Direct3D poważnie - zacząłem od OpenGL bo każdy z osobna i wszyscy na raz mówili ZACZNIJ OD OPEN GL no więc zacząłem. Z braku czasu nie mogę się uczyć Direct3d.

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Czerwiec 21, 2009, 23:02:34
Cytuj
w przypadku np. scrollbara onClick jest funkcją która obsługuje tylko ten scrollbar i nie jest to wtedy callback.
Tzn. jak działa i kiedy/przez kogo jest wywoływana ta funkcja?

Offline Avaj

  • Użytkownik

# Czerwiec 21, 2009, 23:26:43
Cytuj
w przypadku np. scrollbara onClick jest funkcją która obsługuje tylko ten scrollbar i nie jest to wtedy callback.
Tzn. jak działa i kiedy/przez kogo jest wywoływana ta funkcja?
U mnie robi to klasa o oryginalnej nazwie GUIManager  :P scrollbar ma bounding rectangle, GUIManager sprawdza czy kliknięcie było w tymże prostokącie, jeśli tak, to daje scrollbar->onClick(clickX, clickY) i niech się scrollbar męczy czy kliknięto w strzałkę scrollbara, czy w pasek czy w co.

Pewnie są na to jakieś super mądre metody z przekazywaniem odpowiedzialności i podziałem na różne struktury, ale tym później się będę martwił, a wolę mieć coś co działa niż piękny projekt na papierze :]
« Ostatnia zmiana: Czerwiec 21, 2009, 23:28:43 wysłana przez Java »

Offline Adam B

  • Użytkownik

# Czerwiec 22, 2009, 00:02:29
Dzisiaj dużo zrobiłem bo wybrałem Allegro jako interface graficzny oraz przemyślałem dokładniej to co chce napisać i jak to ma wyglądać!

W załączniku screen - jeszcze nic nie jest funkcjonalne no ale już da się dodawać elementy i je rysować.

od strony kodu wygląda to mniej więcej tak:
AllegroInterface Interface; // Nasz allegrowy interfejs graficzny
...
gui_button * b1 = new gui_button("b1", 10, 10, 100, 50); //stworzenie przycisku
gui_button * b2 = new gui_button("b2", 210, 10, 100, 50);
gui_button * b3 = new gui_button("b3", 410, 10, 100, 50);
gui_window * w1 = new gui_window("OKIENKO PIERWSZE yyy", 100, 100, 300, 300, true); //stworzenie okna
...
Interface.draw(bufor, b1); // rysowanie przycisku
Interface.draw(bufor, b2);
Interface.draw(bufor, b3);
Interface.draw(bufor, w1); // rysowanie okna


Kod był troszkę na szybko pisany w założeniu chce aby każdy przycisk był powiązany z jakimś oknem, a rysowanie odbywało się przy pomocy jednej funkcji dla maksymalnego uprostrzenia (system podkreśla mi to słowo:P).

Ma to wyglądać mniej więcej tak:

AllegroInterface Interface;
...
gui_button * b1 = new gui_button("b1", 10, 10, 100, 50);
gui_button * b2 = new gui_button("b2", 210, 10, 100, 50);
gui_button * b3 = new gui_button("b3", 410, 10, 100, 50);
gui_window * w1 = new gui_window("OKIENKO", 410, 10, 100, 50, 1);

gui_window panel = new gui_window("panel", 0, 0, WIDTH, HEIGHT, 0);
panel->addItem(b1);
panel->addItem(b2);
panel->addItem(b3);
panel->addItem(w1);
w1->addItem(inny_przycisk); //xDDD
....
Interface.draw(bufor); // rysuje wszystko co zapiera się w panelu

Więc okno będzie to podstawa - każde okno będzie zawierało listę elementów jaki się a nim znajdują.
Jeżeli kursor myszki będzie na oknie to będą sprawdzane wszystkie elementy tego okna (nie wiem w ogole czy jest sens wprowadzać tu taką lub bardziej zaawansowaną optymalizację skoro w oknie może znajdować się z 200-300 Itemów maksymalnie... jakaś 1 milisekunda dla procesora).
Rozwijane Menu itp planuję zorganizować jako okno z butonami.

Więc to tyle teraz idę oglądnąć kilka odcinków DragonBalla xD :)
Pozdrawiam

poopa

  • Gość
# Czerwiec 22, 2009, 00:37:21
Co do przesiadki, wiem jak to jest, bo sam zaczynałem od OpenGL i dość długo w nim siedziałem. Stadia są następujące:
- Zagorzały zwolennik OpenGL.
- "A dlaczego by nie zajrzeć w końcu co tak naprawdę jest w tym drugim API?"
- Nauka drugiego API (bo zawsze lepiej umieć dwa niż jedno).
- Pisanie w D3D dla zabawy.
- Chęć napisania przenośnego silnika (OpenGL/Direct3D).
- Chęć napisania przenośnego silnika (Direct3D/OpenGL).
- Rodzące się pytanie, po co zajmować się OpenGL.
- Pisanie wyłącznie w Direct3D.

Osobiście myślę, że czeka to każdego (nie dotyczy użytkowników Linuksa), chyba że ktoś jest ignorantem i woli OpenGL od Direct3D (pomimo że nie ma pojęcia jak się w Direct3D pisze), albo z jakiegoś powodu przy OpenGL zwyczajnie się upiera. :)
Ha... masz mnie za ignoranta.  ;)

U mnie bylo dokladnie na odwrot... podmien D3D na OGL i na odwrot OGL na D3D.
« Ostatnia zmiana: Czerwiec 22, 2009, 00:41:18 wysłana przez poopa »

Offline Adam B

  • Użytkownik

# Czerwiec 22, 2009, 01:10:50
Faktem jest że trzeba/dobrze jest znać i jedno i drugie!

Offline Avaj

  • Użytkownik

# Czerwiec 22, 2009, 10:47:04
Faktem jest że trzeba/dobrze jest znać i jedno i drugie!
Jak się zna jedno to zna się i drugie. Przecież to to samo tylko nazwy zmienione :P

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Czerwiec 22, 2009, 11:30:48
Jak się zna jedno to zna się i drugie. Przecież to to samo tylko nazwy zmienione :P
Właśnie udowodniłeś, że któregoś nie znasz. ;) Różnice miejscami są dość znaczne, pomijając fakt, że porównanie DX10 i OpenGL (w dowolnej wersji) zupełnie mija już się z celem, bo DX10 ma całkowicie inną filozofię (obiekty stanów, model zasób-widok i tym podobne). :)

Offline Avaj

  • Użytkownik

# Czerwiec 22, 2009, 12:15:17
Jak się zna jedno to zna się i drugie. Przecież to to samo tylko nazwy zmienione :P
Właśnie udowodniłeś, że któregoś nie znasz. ;) Różnice miejscami są dość znaczne, pomijając fakt, że porównanie DX10 i OpenGL (w dowolnej wersji) zupełnie mija już się z celem, bo DX10 ma całkowicie inną filozofię (obiekty stanów, model zasób-widok i tym podobne). :)
A kto mówił o DX10 =)