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

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Czerwiec 22, 2009, 12:30:55
Cytuj
A kto mówił o DX10 =)
Chodziło mi o to, że różnice między DX9, a OpenGL są znaczne, a między DX10, a OpenGL ogromne. Skoro twierdzisz, że OpenGL i Direct3D 9 to tylko pozmieniane nazwy, to powiedz jak w OpenGL jednocześnie podpiąć ten sam rendertarget do dwóch samplerów (np. jeden sampluje z filtrowaniem typu POINT, a drugi typu LINEAR). ;)

Offline Mr. Spam

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

Offline Avaj

  • Użytkownik

# Czerwiec 22, 2009, 13:57:37
Cytuj
A kto mówił o DX10 =)
Chodziło mi o to, że różnice między DX9, a OpenGL są znaczne, a między DX10, a OpenGL ogromne. Skoro twierdzisz, że OpenGL i Direct3D 9 to tylko pozmieniane nazwy, to powiedz jak w OpenGL jednocześnie podpiąć ten sam rendertarget do dwóch samplerów (np. jeden sampluje z filtrowaniem typu POINT, a drugi typu LINEAR). ;)
zawsze można zrobić FBO blita i wtedy sobie czytać. Można też filtrowanie w shaderze zrobić.

to ty mi powiedz jaki jest odpowiednik PBO w DirectX 9, bo się nie doszukałem!

« Ostatnia zmiana: Czerwiec 22, 2009, 13:59:25 wysłana przez Java »

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Czerwiec 22, 2009, 14:14:53
Cytuj
zawsze można zrobić FBO blita i wtedy sobie czytać.
I przy okazji zużyć pełny ekran fillrate'u i pamięci na pełen ekran tylko po to, żeby obejść ograniczenie API? Dziękuję, postoję. ;)

Cytuj
Można też filtrowanie w shaderze zrobić.
Nieco lepiej, ale wtedy 4x bardziej obciążasz samplery (znowu tylko i wyłacznie z uwagi na niedomagania API OpenGL), co im się samplerom raczej nie spodoba.

Cytuj
to ty mi powiedz jaki jest odpowiednik PBO w DirectX 9, bo się nie doszukałem!
Nie ma jako takiego odpowiednika, bo taki feature był tam "od zawsze". Tekstury/powierzchnie można tworzyć i lockować z odpowiednimi flagami (np. dynamic/discard), a do szybkiego kopiowania między powierzchniami jest StretchRect. :)

Offline Avaj

  • Użytkownik

# Czerwiec 22, 2009, 14:19:29
A wracając do GUI...  8)

Offline Adam B

  • Użytkownik

# Czerwiec 23, 2009, 00:52:05
A no wracając do gui mam pewien problem ;)

Postanowiłem że wszystko co będzie w oknie będzie umieszczane w vector <obj *> content  (obj to klasa po której inne klasy dziedziczą). Mam funkcję addItem(obj *), za pomocą której wiążę obiekt z oknem. Funkcja addItem dodaje do vectora wskaźnik. Teraz za pomocą funkcji (Interfejsu) draw chcę narysować zawartość okna.

Oto kod:


////////GUI
class gui_window : public obj
{
public: // klasa częściowa i uprostrzona dla czytelności
    vector <obj *> content;

    void addItem(obj * o){
      content.push_back(o);
    }
};

//////INTERFEJS ALLEGROWY

class AllegroInterface{
  public:
    void draw(BITMAP * layer, gui_button * g);   
    void draw(BITMAP * layer, gui_window * g);   
};

//////KOD PROGRAMU
//TUTAJ MAM PROBLEM Z UGRYZIENIEM TEGO :/

for (int i =0; i<w1->content.size(); i++){  // w1 to okno, a content to właśnie vector jego zawartości
          Interface.draw(bufor, w1->content[i]); // 1*
        }

1* - content zawiera obj* więc nie zadziała, jak tutaj sensownie wywołać odpowiednią funkcję rysującą (z AllegroInterface)? Potrzebna mi dodatkowa wiedza o typie...

Jakoś nic sensownego nie przychodzi mi do głowy :/

poopa

  • Gość
# Czerwiec 23, 2009, 00:55:14
zastosować delegat czyli wskaźnik do metody. Chyba o to ci chodzi?

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Czerwiec 23, 2009, 00:56:37
Od tego właśnie są w tym przypadku metody wirtualne.

Offline Adam B

  • Użytkownik

# Czerwiec 23, 2009, 01:22:45
Od tego właśnie są w tym przypadku metody wirtualne.

Z mojej wiedzy wynika, że zastosowanie metody wirtualnej by mi pomogło jak by metoda rysująca była wpisana w klasę window jak i w klasę button.

coś w stylu:
#include <cstdlib>
#include <iostream>
#include <string.h>

using namespace std;

class k1{
public:
  virtual void f1(){cout<<"k1 f1:"<<endl;}
          void f2(){cout<<"k1 f2:"<<endl;}
};

class k2: public k1{
public:
  void f1(){cout<<"k2 f1:"<<endl;}
  void f2(){cout<<"k2 f2:"<<endl;}
};

int main(int argc, char *argv[])
{
    k1 *wsk1;
    wsk1 = new k2();
   
    wsk1->f1(); //KLASA DRUGA WUNKCJA PIERWSZA
    wsk1->f2(); //KLASA PIERWSZ FUNKCJA DRUGA
   
    system("PAUSE");
    return EXIT_SUCCESS;
}

Jednak tutaj nie wiem za bardzo jak to podpiąć może to wina już nie najwcześniejszej pory ;)

poopa

  • Gość
# Czerwiec 23, 2009, 01:45:13
KK: Mówienie o całkowicie innej filozofii przy okazji DX10 jest grubo na wyrost.

 A teraz spójrz jak się napociłeś udowadniając wyższość D3D (na dziś) ponad OGL. Stwierdzileś też po drodze, że sam sie zdecydowaleś na całkowite pominięcie, odżegnanie od OGL w przypadku windy. A teraz powiedz, jak to się ma do tych interfejsów na API które warto tworzyć, do Agile Development które od zawsze chwalisz.
 ;)

Ja tu dostrzegam szereg kontrastów.

Co do Utility... wziąlem je w cudzysłów, a także nawias (chyba?). Znam słowo, jego znaczenie i używałem... nigdy nie musiałem tłumaczyć na polski. Z racji braku pewności jak powinno być, napisałem to tak jak napisałem... co by żadnego malkontenta nie urazić. No i proszę - mimo to - znalazł się taki. :)


Co do problemu interfejsu... zamiast metod wirtualnych możesz wykorzystać template-y (co polecam):
Kod: (cpp) [Zaznacz]
struct IDrawable
{
  void IDrawable_Draw();
};
struct DrawableObject : IDrawable
{
  void IDrawable_Draw()
  {
  }
};
struct Panel
{
  template<typename DrawableT>
  void Draw(DrawableT& drawable)
  {
    drawable.IDrawable_Draw();
  }
};

int WINAPI WinMain (HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nCmdShow)
{
  Panel panel;  
  DrawableObject drawableObject;
  panel.Draw<DrawableObject>(drawableObject);
  return 0;
}

Offline Esidar

  • Użytkownik

# Czerwiec 23, 2009, 04:23:52
Co do problemu interfejsu... zamiast metod wirtualnych możesz wykorzystać template-y (co polecam):
Kod: (cpp) [Zaznacz]
 panel.Draw<DrawableObject>(drawableObject);
Template to słaby zamiennik metod wirtualnych. Co jeśli nie znasz typu DrawableObject i masz listę obiektów IDrawable ?

A teraz powiedz, jak to się ma do tych interfejsów na API które warto tworzyć, do Agile Development które od zawsze chwalisz.  ;)
Wystarczy mieć renderer z kilkoma metodami :
* Start2DMode()
* DrawImage( x, y, image )
* DrawLine( x, y, x, y )
* DrawRectangle( x, y, w, h )
* DrawString( text )
* LoadTexture( name )
I to wystarczy. Żadna filozofia. Nie ma najmniejszego znaczenia czy to będzie pod D3D czy OGL bo przerobienie tego to jest 1 godzina, a taki interface jak powyższy "wychodzi" sam z siebie. Przecież głupotą byłoby pisać np. w metodzie GUI_Button::Draw wywołanie bezpośrednio do DrawPrimitive i jakieś bawienie się w ustawianie macierzy, shader'ów, vertex declaration itd. To jest robione po stronie renderera i wybór D3D czy OGL nie wpływa na interface renderera 2D.


Z mojej wiedzy wynika, że zastosowanie metody wirtualnej by mi pomogło jak by metoda rysująca była wpisana w klasę window jak i w klasę button.
Bo tak powinno być. Umieszczanie w "rendererze" różnych metod typu "void draw(BITMAP * layer, wstaw_tutaj_nazwe_klasy_gui * g);" mija się z celem. Powinieneś zrobić metodę draw w obiekcie typu gui_element.

Poza tym nie widzę za bardzo czym się różni gui_button od gui_window.

Immediate Mode GUI jest bardzo wygodne nie tylko ze względu na prostotę ale też dlatego że rozwiązuje powyższe problemy automatycznie. Ostatnio jak piszę edytory w C# to olewam cały ten Framework .NET i wbudowane kontrolki. Mam tylko swoją klasę którą wykorzystuję do wszystkiego (listy, buttony, widoki jakichś rzeczy itd).
Do tego warto mieć odizolowane rysowanie kontrolek od kodu. Zamiast metody "draw" którą trzeba przeciążyć żeby narysować Button, to do kontrolki podaję coś w rodzaju dynamicznego XAML. Wszystko jest rysowane z danych a nie kodem. Np. narysowanie jakiegoś obrazka z czarną obwódką:
// pseudocod
draw_image( {image_name}, {x} + 1, {y} + 1 )
draw_frame( {x}, {y}, {x}+{w}, {y}+{h}, black )
w klamerkach {} są zmienne odczytywane z różnych miejsc: zmienne z globalnej tablicy lub zmienne lokalne w kontrolce.
Dzięki temu mam tylko jedną klasę "UIElement" która służy do wszystkiego; Button, List, TreeView, itd. Gdy potrzebuję wiedzieć kiedy dany przycisk będzie wciśnięty to ustawiam mu nazwę event'a który ma mi przysłać w momencie kliknięcia.


« Ostatnia zmiana: Czerwiec 23, 2009, 04:25:51 wysłana przez Esidar »

Offline Adam B

  • Użytkownik

# Czerwiec 23, 2009, 10:46:21
Esidar mówisz o umieszczeniu funkcji rysującej w gui_button i gui_window. Tylko, że gui ma być zbudowane na zasadzaie: GUI osobno i WIZUALIZACJA GUI tez osobno.

Offline master18

  • Użytkownik

# Czerwiec 23, 2009, 11:37:19
Ja już kilka projektów mam za sobą. Na początku było fajnie bo GUI zawierały około 300, ale po ostatnim gdzie tych kontrolek wyszło ponad 2500 to postanowiłem zrobić GUI ładowane z pliku, tym bardziej że program jest wielojęzyczny polski, angielski, ruski itd.
Nie wiem jak to się ma do wydajności jeśli chodzi o metody opisywane przez was, ale ja postanowiłem zrobić coś podobnego do metody działania kontrolek WinApi. Każdy rodzaj kontrolki przechowuje swoje pozycje i skalę o wartościach od 0.0f do 1.0f razy rozdzielczość ekranu/okna. Potem mam klasę meneger_GUI i ona zarządza przepływem komunikatów (mysz i klawiatura). Rekurencyjnie rozsyłam sobie te komunikaty po kontrolkach i każda kontrolka sama sobie robi z tym co chce np. mouse over, mouseLB down. Potem ta kontrolka wystawia stosowny komunikat do kolejki komunikatów ze swoim nr ID. Do tego jeszcze każda kontrolka ma wskaźnik na swojego rodzica, np okno i wtedy sama pobiera sobie z niego takie parametry jak widzialność, pozycja itp.
GUI działa na DX i muszę przyznać, że wydajność tej metody są zadowalające. Bufor wierzchołków i indeksów blokuję tylko w razie konkretnego zdarzenia.
No ale jeszcze nie zaprojektowałem wszystkich kontrolek, żeby wiedzieć na dokładnie jak to się sprawdzi.

Offline Esidar

  • Użytkownik

# Czerwiec 23, 2009, 11:44:40
Esidar mówisz o umieszczeniu funkcji rysującej w gui_button i gui_window. Tylko, że gui ma być zbudowane na zasadzaie: GUI osobno i WIZUALIZACJA GUI tez osobno.

Zamiast metody "draw" którą trzeba przeciążyć żeby narysować Button, to do kontrolki podaję coś w rodzaju dynamicznego XAML.

Ja nie mam metody draw w kontrolkach. Mam w rendererze "void draw( xaml_data* data);" z danymi pobranymi z kontrolki. To że tobie poradziłem użycie draw w kontrolce to dlatego że z jakiegoś powodu uparłeś się mieć 2 różne klasy gui_button i gui_window i powtórzę, nadal nie widzę między nimi różnicy :)

« Ostatnia zmiana: Czerwiec 23, 2009, 11:54:12 wysłana przez Esidar »

Offline mdn

  • Użytkownik
    • home page

# Czerwiec 23, 2009, 12:41:02
Moim gui, które powoli wychodzi ze stanu projektu, oparte jest na sprite'ach (kontrolka sama pobiera z pliku tekstury odpowiednie fragmenty, które składają sie na jej wygląd, i 'skleja się' do kupy) i sama się wyświetla (wirtualna metoda Draw(); ).
W ten sposób moje gui uzależnione jest od dx9, z drugiej strony wystarczy podmienić jeden plik z teksturą, by uzyskać całkiem inne gui ;)
I szczerze powiedziawszy, trudno jest mi sobie wyobrazić oddzielenie modułu wyświetlania i gui, niestety.

Offline Adam B

  • Użytkownik

# Czerwiec 23, 2009, 12:59:12
Esidar mówisz o umieszczeniu funkcji rysującej w gui_button i gui_window. Tylko, że gui ma być zbudowane na zasadzaie: GUI osobno i WIZUALIZACJA GUI tez osobno.

Zamiast metody "draw" którą trzeba przeciążyć żeby narysować Button, to do kontrolki podaję coś w rodzaju dynamicznego XAML.

Ja nie mam metody draw w kontrolkach. Mam w rendererze "void draw( xaml_data* data);" z danymi pobranymi z kontrolki. To że tobie poradziłem użycie draw w kontrolce to dlatego że z jakiegoś powodu uparłeś się mieć 2 różne klasy gui_button i gui_window i powtórzę, nadal nie widzę między nimi różnicy :)


Do klasy windows można przypisywać/dodawać przyciski (buttony) oraz inne okna.
Do klasy button można przypisywać różne akcje, które uruchamiają się po kliknięciu w przycisk.
Tak to rozplanowałem jeżeli ma to jakąś wadę proszę o jej podanie bo na kartce wyglądało to dość dobrze ;)