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

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Czerwiec 23, 2009, 13:07:01
Cytuj
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 ;)
Wada: za dużo tego przypisywania, ale to pewnie przez moje zboczenie na punkcie immediate mode GUI (gdzie przyciski się robi jedną linijką - bez żadnych new/delete, callbacków, przypisywania itp). :)

Offline Mr. Spam

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

Offline master18

  • Użytkownik

# Czerwiec 23, 2009, 13:21:23
Osobiście też mam atlas GUI, to bardzo ułatwia sprawę. A co do reakcji na button np. to może lepiej jak by ona wysyłała komunikat do aplikacji o tym fakcie ze swoim ID. Planuję w przyszłości zrobić sobie edytor GUI, a aplikacja ładowała by sobie kontrolki z pliku. Do tego podejścia skłoniło mnie długie czasy kompilacji dużego projektu tylko po to by przesunąć kontrolkę w lewo lub w prawo. No chyba, że ktoś ma to GUI w DLL.

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Czerwiec 23, 2009, 13:42:15
Cytuj
Do tego podejścia skłoniło mnie długie czasy kompilacji dużego projektu tylko po to by przesunąć kontrolkę w lewo lub w prawo.
Rozwiązanie: automatyczne układanie kontrolek. :)

poopa

  • Gość
# Czerwiec 23, 2009, 15:36:17
No chyba, że ktoś ma to GUI w DLL.
albo w jakimś zewnętrznym pliku...

Offline Adam B

  • Użytkownik

# Czerwiec 23, 2009, 15:53:47
A ja dalej nie wiem na jakiej zasadzie mogę odebrać poprawnie typy w funkcji rysującej. Jak rozpoznać czy addItem było wywołana dla gui_button czy gui_window ? Może jakiś mądrzejszy kolega mnie oświeci ??

Offline Paweł

  • Użytkownik

# Czerwiec 23, 2009, 15:58:56
zapewne przeszukałes forum?
http://forum.warsztat.gd/index.php/topic,11047.0.html

EDIT:
IMGUI wyglada conajmniej interesujaco :P googlowalem troche na ten temat, zastanawiam sie jednak czy uzywajac tego typu rozwiazania nie traci sie tej warstwy abstrakcji GUI -> render?
« Ostatnia zmiana: Czerwiec 23, 2009, 16:02:22 wysłana przez Turkov »

Offline yarpen

  • Użytkownik

# Czerwiec 23, 2009, 16:05:37
Osobiście też mam atlas GUI, to bardzo ułatwia sprawę. A co do reakcji na button np. to może lepiej jak by ona wysyłała komunikat do aplikacji o tym fakcie ze swoim ID. Planuję w przyszłości zrobić sobie edytor GUI, a aplikacja ładowała by sobie kontrolki z pliku. Do tego podejścia skłoniło mnie długie czasy kompilacji dużego projektu tylko po to by przesunąć kontrolkę w lewo lub w prawo. No chyba, że ktoś ma to GUI w DLL.
W duzych projektach uzywa sie po prostu Scaleforma albo podobnej biblioteki i robi GUI we Flashu. Ale do wiekszosci projektow domowych to jednak mocny overkill.

Offline Esidar

  • Użytkownik

# Czerwiec 23, 2009, 16:45:16
Nie wspominając że Adobe Flash CS4 to jakieś 4tyś zł :)

Scaleform używa rozwiązań z IMGUI czyli eventy, wspólna baza parametrów itd. Z drugiej strony Scaleform jest oparty o Flasha który nie jest IMGUI i ma często przemieszanie kodu z grafiką (nawet do takich pierdół jak zapętlanie animacji) i który jako program do animacji grafiki wektorowej jest ok, ale do robienia w nim UI super nie jest :) np. nie fajne połączenie kodu z grafiką, brak wsparcia dla 3D i shader'ów itp

Kiedyś był Anark Gameface który miał własne rozwiązania, własny edytor (i był ogólnie słaby pod względem możliwości), ale już przestał istnieć (przejęła go NVidia i słuch o nim zaginął :) ).

Ja tu widzę niszę OpenSource lub Indie dla kompleksowego rozwiązania GUI :)

Offline Adam B

  • Użytkownik

# Czerwiec 23, 2009, 17:02:13
zapewne przeszukałes forum?
http://forum.warsztat.gd/index.php/topic,11047.0.html

EDIT:
IMGUI wyglada conajmniej interesujaco :P googlowalem troche na ten temat, zastanawiam sie jednak czy uzywajac tego typu rozwiazania nie traci sie tej warstwy abstrakcji GUI -> render?

Tutaj funkcja draw jest wpisana do CElemnet i jest virtualna - wiem jak coś takiego zastosować. U mnie z założenia - co doradzili mi warsztatowicze (przynajmniej tak to zrozumiałem) w CElement i w innych po nim dziedziczących klasach nie ma być draw, ponieważ draw ma być niezależne od logiki GUI.

Nic nie umiem wymyślić jedyne co mi pozostało to statyczny wskaźnik na funkcję rysującą.
Pseudokod pokazuje to tak:
// funkcja, którą będziemy wywoływać
void AllegroInterface.DrawButton(){ // FUNKCJA Z INTERFEJSU ALLEGRO DO RYSOWANIA PRZYCIKSÓW
  std::cout << "Rysowanie" ; // RYSUJE :)
}
...
class Button{ // KLASA PRZYCISKU
  void (*Draw)();
};
...
Button.Draw = &AllegroInterface.DrawButton(); // Teraz wskaznik z klasy button wskazuje na funkcje z Interfejsu
...
vector <obj *> content; // Wektor z wskaznikami na wszytkie elementy gui

content[x]->(*Draw)(); // Wywołanie draw dla Buttona


Jednak rozwiązanie ma minus bo funkcję rysującą trzeba przypisywać do każdej z klas dla której może wystąpić rysowanie :/

No ale skoro nie ma lepsze metody - łatwiejszej w używaniu to nic będę musiał opierać się na tym.
« Ostatnia zmiana: Czerwiec 23, 2009, 17:05:21 wysłana przez Adam B »

poopa

  • Gość
# Czerwiec 23, 2009, 22:08:42
Ja mam i w takich sytuacjach uzywam zdarzen...

Events jest klasa bazowa... ma jeden skladnik, jest to wskaznik na eventHandler.

Kazda klasa dziedziczaca z Events przypisuje wlasna funkcje do obslugi zdarzen...

W ten sposob wywolanie rysowania na dowolnym obiekcie (dziedziczacego z Events) sprowadza sie do wywolania Events::OnDraw na eventHandler-ze z pod wskazanego adresu, zapodając sam adres jako jeden z parametrow.

To tylko kolejna z możliwości - oczywiście.



Offline djsmtih

  • Użytkownik

# Czerwiec 23, 2009, 22:26:45
U mnie wygląda to tak:
CElement{
CElement *Parrent;
vector<CElement*> Child;
int action,value;

virtual void GenerateEvent(CElement* Message)
{
       Parrent->GenerateEvent(Message);
}

};
I na przykład jeśli naciśnięty zostaje przycisk wywołuje on:
GenerateEvent(this);
Przycisk->Pole->Okienko->GuiMenager->CallbackFunc()

Ponieważ funkcja jest wirtualna to np. w obiektach typu CListBox dla niektórych akcji przesyłanie może być
przerywane bo przycisk odpowiada za dodanie elementu do list boxa.

I jeszcze jedna fajna sprawa :) Przycisk ma odpowiadać za dodanie jakiejś tekstury.
TextBox do którego wpisywany jest plik tekstury staje się dzieckiem tego przycisku dzięki czemu
w funkcji odbierającej komunikaty można zrobić tak:

Tex.Load(Message->Child[0]->ReturnCharValue());


Offline Dab

  • Redaktor
    • blog

# Czerwiec 24, 2009, 15:36:46
Mam pytanie do miłośników IMGUI. Jakie w zasadzie korzyści mamy z czegoś takiego w projekcie większym niż 500 linii kodu? (poza tym, że jest cool & trendy) Miałem nieprzyjemność dłubać przy jednej grze która korzystała z czegoś takiego (aczkolwiek nie wiedziałem, że ma to taką nazwę) -- Battle for Wesnoth i niestety był to istny koszmar. Podstawowym wzorcem projektowym jest tam magic button, GUI generalnie przechowuje połowę danych i zarządza 90% gry. Dopisanie czegokolwiek (albo nawet wyciągnięcie jakiś danych) do tego kodu to była masakra.

Offline Esidar

  • Użytkownik

# Czerwiec 24, 2009, 16:14:20
Mam pytanie do miłośników IMGUI. Jakie w zasadzie korzyści mamy z czegoś takiego w projekcie większym niż 500 linii kodu? (poza tym, że jest cool & trendy) Miałem nieprzyjemność dłubać przy jednej grze która korzystała z czegoś takiego (aczkolwiek nie wiedziałem, że ma to taką nazwę) -- Battle for Wesnoth i niestety był to istny koszmar. Podstawowym wzorcem projektowym jest tam magic button, GUI generalnie przechowuje połowę danych i zarządza 90% gry. Dopisanie czegokolwiek (albo nawet wyciągnięcie jakiś danych) do tego kodu to była masakra.
Jak zwykle, kwestia realizacji :) W teorii IMGUI lepiej zarządza danymi bo są tylko w 1 miejscu. Nie ma kopii w 20 miejscach i nie musisz tego ręcznie update'ować. Jeżeli masz np. wyświetlić nazwę gracza to umieszczasz na ekranie dowolną ilość TextBox'ów które wyświetlają np. "=Player.Name" co oznacza wyświetlenie zawartości zmiennej Name w obiekcie Player. Każdy TextBox potrafi zmienić nazwę gracza i automatycznie o tym powiadomić wszystkich zainteresowanych.

Jeżeli każdy TextBox robi swoją kopię tego tekstu (np. tak jak to robi WinAPI, wxWidgets, WindowsForms itp itd) to masz parę godzin pracy na oprogramowanie kopiowania i modyfikacji każdej kopii tej jednej zmiennej.

Nie wiem w jaki sposób to było zrealizowane w BfW skoro to było takie upierdliwe :)

W teorii dorobienie kolejnej zmiennej + kontrolka to powinno wystarczyć coś w stylu:
GUI::AddVariable<float>( "Player.Race" );
AddControl( "TextBox", 10, 15, 100, 20, "=Player.Race" );
« Ostatnia zmiana: Czerwiec 24, 2009, 16:17:23 wysłana przez Esidar »

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Czerwiec 24, 2009, 16:26:50
Cytuj
W teorii dorobienie kolejnej zmiennej + kontrolka to powinno wystarczyć coś w stylu:

Kod:
GUI::AddVariable<float>( "Player.Race" );
AddControl( "TextBox", 10, 15, 100, 20, "=Player.Race" );
To chyba nie jest do końca Immediate Mode GUI, z tego, co wyczytałem. ;)


Przy podejściu IMGUI, żeby zrobić przycisk wystarczy jedna linijka:
if( Button("Kliknij mnie!") ) rob_cos();

Ciekawy tutorial na temat IMGUI można znaleźć tutaj: http://sol.gfxile.net/imgui/
(chociaż osobiście wolę stosować automatyczny layouter, który sam wyznacza gdzie ma rysować przyciski)


EDIT:
A jeżeli chodzi o editboxy, to też można to załatwić jedna linijką:
if( EditBox( &moje_dane, UICośtamConverter() ) ) data_changed();
« Ostatnia zmiana: Czerwiec 24, 2009, 16:28:52 wysłana przez Krzysiek K. »

Offline DamorK

  • Użytkownik

# Czerwiec 24, 2009, 18:34:14
A jeżeli chodzi o editboxy, to też można to załatwić jedna linijką:
if( EditBox( &moje_dane, UICośtamConverter() ) ) data_changed();

A moje_dane to strukturka zawierająca wszystkie dane które normalnie znalazłyby się w obiekcie, czyli aktualny tekst, pozycja kursora, czy editbox jest aktywny etc.? A jak nie to gdzie to trzymamy?
I jeszcze jedno. Nie wiem czy dobrze rozumiem ale czy poszczególne kontrolki nic o sobie nie wiedzą? Wobec tego co w przypadku kiedy dwie kontrolki zasłaniają się, skąd wiemy która jest nad która, tj. która ma przechwycić kliknięcie?