Natychmiastowe GUI - yae czy nie? [Zamknięte]

38

Pracowałem nad tworzeniem aplikacji z wieloma „zachowanymi” systemami GUI (poniżej więcej o tym, co mam na myśli), takimi jak MFC, QT, Forms, SWING i kilka frameworków web-GUI kilka lat temu. Zawsze uważałem koncepcje większości systemów GUI za zbyt skomplikowane i niezdarne. Ilość zdarzeń oddzwaniania, detektorów, kopii danych, czegoś do czegoś ciągnąć - konwersje (i tak dalej) zawsze były źródłem błędów i problemów w porównaniu z innymi częściami aplikacji. (Nawet przy „właściwym” wykorzystaniu powiązań / modeli danych).

Teraz piszę gry komputerowe :). Do tej pory pracowałem z jednym GUI: Miyagi (mało znany, ale w zasadzie ten sam Idea, co wszystkie inne systemy).

To było okropne.

W przypadku środowisk renderowania w czasie rzeczywistym, takich jak Gry, mam wrażenie, że „zachowane” systemy GUI są jeszcze bardziej przestarzałe. Interfejsy użytkownika zwykle nie muszą być automatycznie układane ani mieć okien w trakcie pracy, których rozmiar można zmieniać. Zamiast tego muszą bardzo efektywnie współdziałać z ciągle zmieniającymi się danymi (takimi jak pozycje modeli na świecie w 3D)

Kilka lat temu natknąłem się na „IMGUI”, który jest w zasadzie jak tryb Natychmiastowej grafiki, ale dla interfejsów użytkownika. Nie poświęciłem zbyt wiele uwagi, ponieważ wciąż byłem w fazie rozwoju aplikacji, a sama scena IMGUI wydawała się niezbyt szeroka ani udana. Jednak podejście, które przyjęli, wydaje się być tak seksowne i eleganckie, że sprawiło, że chciałem napisać coś do następnego projektu przy użyciu tego interfejsu użytkownika (nie przekonałem nikogo w pracy: (...)

pozwól, że streszczę, co rozumiem przez „zachowane” i „natychmiastowe”:

Zachowane GUI: W osobnej fazie inicjalizacji tworzysz „kontrolki GUI”, takie jak Etykiety, Przyciski, TextBoxy itp., I używasz opisowego (lub programowego) sposobu umieszczania ich na ekranie - wszystko przed renderowaniem czegokolwiek. Elementy sterujące przechowują większość własnego stanu w pamięci, na przykład lokalizację X, Y, rozmiar, obramowania, elementy podrzędne, tekst etykiety, obrazy i tak dalej. Możesz dodać wywołania zwrotne i detektory, aby uzyskać informacje o zdarzeniach i zaktualizować dane w kontrolce GUI.

Natychmiastowe GUI: Biblioteka GUI składa się z jednorazowych funkcji „RenderButton”, „RenderLabel”, „RenderTextBox” ... (edycja: nie daj się pomylić przez Renderujprefiks. Funkcje te wykonują również logikę za elementami sterującymi, takimi jak odpytywanie danych wejściowych użytkownika, wstawianie znaków, obsługa powtarzania znaków, gdy użytkownik przytrzymuje klawisz i tak dalej ...), które można wywołać w celu „natychmiastowego” renderowania formantu (nie t musi być natychmiast zapisany na GPU. Zwykle jest on zapamiętywany dla bieżącej ramki i sortowany na odpowiednie partie później). Biblioteka nie przechowuje dla nich żadnego „stanu”. Jeśli chcesz ukryć przycisk ... po prostu nie wywoływaj funkcji RenderButton. Wszystkie funkcje RenderXXX, które mają interakcję użytkownika, takie jak przyciski lub pole wyboru, mają zwracane wartości wskazujące, czy np. Użytkownik kliknął przycisk. Więc twój „RenderGUI” funkcja wygląda jak duża funkcja if / else, w której wywołujesz lub nie wywołujesz funkcji RenderXXX, w zależności od stanu gry, a cała logika aktualizacji danych (po naciśnięciu przycisku) zostaje wplątana w przepływ. Całe przechowywanie danych odbywa się „poza” interfejsem GUI i przekazywane na żądanie do funkcji renderowania. (Oczywiście podzieliłbyś duże funkcje na kilka funkcji lub używałbyś abstrakcyjnych klas do grupowania części gui. Nie piszemy już kodu jak w 1980 roku, prawda?))

Teraz odkryłem, że Unity3D faktycznie stosuje to samo podstawowe podejście do swoich wbudowanych systemów GUI. Prawdopodobnie jest też kilka GUI z takim podejściem?

Nadal… kiedy się rozglądasz, wydaje się, że silna tendencja do zachowywania systemów GUI? Przynajmniej nie znalazłem takiego podejścia, z wyjątkiem Unity3D, a oryginalna społeczność IMGUI wydaje się raczej .... cicha.

Czy ktoś pracował z obiema pomysłami i miał jakieś mocne zdanie?

Edycja: Najbardziej interesują mnie opinie wynikające z rzeczywistych doświadczeń. Myślę, że na forum IMGUI toczy się wiele gorących dyskusji na temat wszelkich „teoretycznych słabości” bezpośredniego podejścia do GUI, ale zawsze uważam, że lepiej jest wiedzieć o słabościach w świecie rzeczywistym .

Imi
źródło
Dzięki za link. Chyba masz na myśli komentarz Kylotana . Ciekawe ..;)
Imi
1
Hah, byłem już w połowie pisania poniższej odpowiedzi, kiedy zauważyłem, że moja opinia została już zobaczona ... ale i tak ją opublikuję.
Kylotan
2
Szkoda, że ​​pytania te się zamykają! Tego rodzaju opinii szukam, gdy mam to samo pytanie.
Harald Scheirich,

Odpowiedzi:

34

Nie. Zrobiłem płatną pracę dla gamedev nad okropnym GUI w trybie zatrzymanym i okropnym GUI w trybie natychmiastowym i chociaż oba sprawiły, że chciałem oderwać oczy, podejście w trybie zatrzymanym jest nadal zdecydowanie lepsze.

Wady trybu natychmiastowego są liczne:

  • nie ułatwiają artystom i projektantom konfiguracji układu;
  • sprawiają, że łączysz logikę z prezentacją;
  • utrudniają posiadanie jednego spójnego modelu wejściowego;
  • zniechęcają do kompleksowej kontroli danych dynamicznych (np. widoków listy);
  • nakładanie warstw staje się bardzo niewygodne (np. jeśli wywołam RenderComboBox, pole rozwijane nie może jeszcze renderować, ponieważ musi wychodzić poza resztę okna - tak samo jak w przypadku podpowiedzi) l
  • konfiguracja stylu renderowania kończy się na globals (ick) lub dodatkowych argumentach funkcji (ick);
  • wydajność może być niska, ponieważ wywoływanie wszystkich tych funkcji w celu zapytania o wartości, które mogły ulec zmianie lub nie, zwykle powoduje powstanie wielu małych obiektów, co stresuje menedżera pamięci;
  • ... i nawet nie wyobrażam sobie, jak bolesne byłoby pozwolenie komuś przeciągnąć kawałki GUI i zmienić ich kolejność. Musiałbyś zachować strukturę danych, która wskazywałaby Ci miejsce renderowania wszystkiego - co przypomina samodzielne przepisywanie systemu w trybie zatrzymanym.

Interfejsy GUI w trybie natychmiastowym są kuszące dla samotnych programistów, którzy chcą szybkiego systemu HUD, i do tego celu są świetne. Jeśli chodzi o cokolwiek innego ... po prostu powiedz nie.

Kylotan
źródło
1
@ImmanuelScholz: Czy zastanawiałeś się, czy zachowane GUI nie są tak naprawdę „takie brzydkie”?
Nicol Bolas
1
Biblioteki GUI są nieeleganckie, ponieważ dotyczą kilku problemów - wprowadzania, renderowania i dostępu do danych - a na każdą z nich duży wpływ ma reszta programu. Oznacza to, że ludzie dodają warstwy abstrakcji, aby GUI można było ponownie wykorzystywać w różnych programach, urządzeniach wejściowych i rendererach, kosztem uczynienia go bardziej złożonym w użyciu.
Kylotan
2
Dodaj do tego fakt, że nie ma zgody co do tego, jak tworzyć GUI w trybie zatrzymanym (MVC, MVP i MVVM to 3 popularne podejścia) lub jak to rozłożyć (z danych? Z kodu?) Lub jak dołączyć zachowanie wejściowe ( wbudowany skrypt, jak w przypadku Internetu? Nazwane sygnały / gniazda? Wyniki na miejscu, jak w przypadku IMGUI?), a ten brak standaryzacji utrudnił opracowanie One True Way dla GUI.
Kylotan
2
Konfigurowanie układu przez artystę wymaga edytora bez względu na to, czy używasz zachowanego, czy natychmiastowego interfejsu GUI. Ten punkt jest całkowicie nieprawidłowy. Mieszanie logiki i prezentacji jest powodem, dla którego używasz GUI w trybie natychmiastowym, to nie jest wada, to jest to, czego chcesz, w przeciwieństwie do bałaganu, który zachowuje więcej GUI. Nawet tak mało rozumiesz. Konfiguracja nie wymaga globalizacji ani dodatkowych argumentów, jeśli interfejs API jest dobrze zaprojektowany. Każdy wspomniany minus można rozwiązać w czystej sprawie. Co najważniejsze, piszesz interfejs użytkownika gry, a nie Photoshop.
dreta
3
@dreta: Chodzi mi o konfigurację wykonawców, że są rzeczy, które są całkowicie niepraktyczne, aby zmienić je za pomocą edytora bez pisania na nim własnej warstwy trybu zatrzymania (np. co zrobić, gdy kliknięty zostanie przycisk lub zmiana kolejności elementy). IMGUI działa dobrze dla bardzo prostych i trywialnych elementów wizualnych, nic więcej.
Kylotan
31

Jako osoba z pięcio- lub sześcioletnim doświadczeniem z IMGUI na komputerze czuję się zobowiązany do jej obrony. Wszystkie odpowiedzi (i samo pytanie) oparte są na bardzo ograniczonej definicji IMGUI i wydaje się, że istnieje wiele wątpliwych twierdzeń.

Wiele z nich wynika z założenia, że ​​biblioteka IMGUI nie może przechowywać żadnych danych pod maską. To wcale nie jest prawda. Wyrafinowana biblioteka IMGUI faktycznie zachowa tyle danych, co równoważna biblioteka RMGUI. Różnica polega na tym, że biblioteka IMGUI głównie buforuje wyniki, podczas gdy biblioteka RMGUI utrzymuje autorytatywny stan. W IMGUI aplikacja udostępnia funkcję, która przyjmuje bieżący stan modelu i tworzy interfejs GUI dla tego stanu. To jest autorytatywna definicja GUI. Biblioteka jest odpowiedzialna za upewnienie się, że ekranowe GUI odpowiada wynikowi tej funkcji. Nie oznacza to, że musi w pełni ocenić tę funkcję dla każdej ramki i całkowicie przebudować GUI. Właśnie o to chodzi w buforowaniu.

Z tym widokiem IMGUI można w rzeczywistości wykonać zaawansowany układ, a wydajność jest całkiem rozsądna. Możesz również zachować aktualny stan autorytatywny, jeśli ułatwia to interfejs. Celem IMGUI nie jest sprawienie, aby aplikacja zachowała wszystko. Aplikacja prawdopodobnie nie chce przechowywać pozycji każdego paska przewijania oraz stanu rozwiniętego / zwiniętego każdego węzła drzewa. Chodzi o to, aby móc proceduralnie określać zawartość tych węzłów drzewa i ich istnienie.

Przejrzałbym i odpowiadał na wszystkie krytyki IMGUI punkt po punkcie, ale tak naprawdę nie rozumiem ich wielu. Większość z nich wydaje się wynikać z pewnego fundamentalnego przekonania, że ​​IMGUI jest hackerskie, a RMGUI ma dobrą strukturę, co, jak sądzę, wynika z powyższych nieporozumień. Nie ma nieodłącznego powodu, dla którego biblioteki IMGUI powinny mieć problemy ze złożonością lub być zaśmiecone globalsami lub mieszać logikę z prezentacją. Powiem, że zalety IMGUI stają się mniej ważne, im bardziej twórcy kierują się twoimi treściami, ale nie jestem pewien, dlaczego byłoby tak gorzej w przypadku treści kierowanych przez artystów. (Nie używam osobiście treści kierowanych przez artystów, oprócz arkuszy stylów do takich rzeczy, jak kolory, rozmiary czcionek / ramek itp., Ale nie rozumiem, dlaczego trudniej byłoby je wdrożyć niż w przypadku RMGUI.)

Moim zdaniem IMGUI jest bez wątpienia dobrą rzeczą. Daje ci znacznie lepszy model do rozumowania na temat GUI. Staje się znacznie bardziej funkcjonalny i reaktywny, a ty zminimalizujesz ilość stanu zmiennego, o którym musisz myśleć. Z drugiej strony implementacja wyrafinowanej biblioteki IMGUI jest sporym wyzwaniem i zdecydowanie trudniejszym niż implementacja równoważnej biblioteki RMGUI. Jest to kompromis między złożonością biblioteki a złożonością aplikacji. Jeśli planujesz budować złożone aplikacje (lub nawet wiele prostych aplikacji), kompromis jest bardzo dobry. Jeśli robisz to dla jednej aplikacji i jest to dość proste, prawdopodobnie osiągniesz swój cel szybciej dzięki RMGUI.

W każdym razie powodzenia!

Tomek
źródło
5
„Nie ma nieodłącznego powodu, dla którego biblioteki IMGUI powinny mieć problemy ze złożonością lub być zaśmiecone globalsami lub mieszać logikę z prezentacją”. Bardzo trudno jest zobaczyć, jak zwykle wywołuje się przycisk IMGUI, np. „jeśli Button (x, y) to Action” nie można nazwać logiką mieszania z prezentacją. Jeśli nie przekazujesz szczegółów wywołania, nie możesz go ustawić ani nadać stylu (z wyjątkiem globalnego lub statycznego), a jeśli nie przetworzysz logiki przycisku od razu, to tak naprawdę nie jest to GUI trybu natychmiastowego. Czy możesz podać przykład do wyjaśnienia?
Kylotan
4
Kontekst OpenGL jest dużym źródłem błędów ze względu na ilość współużytkowanego stanu, a jednak nawet z tym interfejsem API przejście od lat do trybu zatrzymanego, ponieważ tryb natychmiastowy nie oferował wymaganej elastyczności ani wydajności.
Kylotan
1
Problemem nie jest współbieżność, lecz jeden wspólny blok stanu. GUI w trybie zatrzymanym hermetyzują odpowiedni stan z kontrolą, której dotyczą, i takie enkapsulacja jest zwykle uważana za dobrą z powodów, które nie muszą być tutaj powtarzane. Moje szczególne obawy są wymienione w mojej odpowiedzi powyżej i nie widziałem jeszcze żadnego podejścia IMGUI, które nie cierpiałoby na wszystkie z nich.
Kylotan
3
Czy arkusz stylów CSS kwalifikuje się również jako „jeden duży blok stanu, który jest współdzielony”? W każdym razie nie wiem, jakie jest twoje szczególne doświadczenie z IMGUI, ale jeśli jesteś zainteresowany podejściami IMGUI, które nie cierpią z powodu tych problemów, zachęcam do przeczytania mojej odpowiedzi powyżej i przeczytania Forum IMGUI na temat Molly Rocket. To prawda, że ​​nie ma gotowej gotowej biblioteki IMGUI, którą można pobrać i zacząć używać w kilka minut, ale jeśli chcesz ją zbudować, dostępne są informacje i osoby chętne do pomocy.
Tom
1
Arkusze stylów CSS mają stan statyczny; raczej różni się od kontekstów OpenGL, które są niezwykle dynamiczne!
Kylotan
12

Biblioteka GUI składa się z jednorazowych funkcji „RenderButton”, „RenderLabel”, „RenderTextBox” ... funkcji, które można wywołać w celu „natychmiastowego” renderowania formantu (nie trzeba od razu zapisywać go na GPU. Zwykle jest to zapamiętywane dla bieżącej ramki i później posortowane w odpowiednie partie).

I tak posunąłbym się do stwierdzenia, że ​​nie stanowi to biblioteki GUI. To tylko kilka funkcji renderowania.

Renderowanie GUI jest najłatwiejszą częścią tworzenia GUI. Weźmy na przykład pole tekstowe. Założę, że jest to najłatwiejszy możliwy przypadek: proste pole tekstowe z jednym wierszem.

RenderTextBoxpo prostu narysuje pole tekstowe. Wykona prosty pomiar tekstu i narysuje glify na ekranie. Będzie nie

  • Wykryj, że użytkownik kliknął myszą w kontrolce i przesunął kursor w odpowiednie miejsce w ciągu.
  • Wykryj, że użytkownik dwukrotnie kliknął myszą w kontrolce i wybrał blok tekstu.
  • Wykryj, że użytkownik nacisnął klawisz „Początek” i przesunął kursor na przód tekstu.
  • Wykryj, że użytkownik nacisnął prawidłowy klucz i odpowiednio zmodyfikuj ciąg. Jeśli zaznaczono tekst, wybrana część zostanie zastąpiona wstawionym tekstem.

Mogę iść dalej, ale myślę, że mój punkt widzenia jest jasny. Jeśli chcesz RenderTextBoxnarysować pole tekstowe, dostaniesz tylko statyczne, niefunkcjonalne pole tekstowe. Wszelkie rzeczywiste funkcje muszą być zaimplementowane przez Ciebie.

Robisz pomiary tekstu i rysujesz glify? To łatwa część pracy z GUI. GUI oznacza „graficzny interfejs użytkownika”. Ostatnie dwa słowa, w których bierzesz wkład od użytkownika i robisz z nim coś, są trudną częścią.

Gracze oczekują, że sterowanie GUI będzie działało rozsądnie. W środowisku PC (np. Mysz i klawiatura), jeśli gracze widzą pole tekstowe, oczekują, że będzie działać jak zwykłe pole tekstowe. Oczekują, że będą mogli się w nim poruszać za pomocą klawiszy strzałek, przeskakiwać do przodu i kończyć domem i usuwać, wybierać w nim litery itp.

Oznacza to, że będziesz musiał zaimplementować cały ten kod interfejsu użytkownika. Musisz sprawdzić, która kontrola została kliknięta. Następnie musisz zrobić coś, na podstawie którego kliknięto kontrolkę. Musisz mieć pojęcie „aktywnej” kontroli, takiej, która pobiera dane z klawiatury. Różne elementy sterujące muszą reagować w różny sposób na różne rodzaje interakcji użytkownika.

Zasadniczo będziesz potrzebować TextBoxWindowklasy.

Załóżmy, że wdrażasz ekran opcji gry. Masz więc różne grupy opcji: rozgrywkę, grafikę, dźwięk, sterowanie itp. Po lewej stronie ekranu masz listę różnych grup. Każda grupa zawiera szereg elementów sterujących, którymi użytkownik może manipulować. Co się stanie, gdy użytkownik naciśnie klawisz Tab?

Zależy to od tego, jaka kontrola jest aktywna. Jeśli jeden z elementów sterujących grupy jest aktywny (został ostatnio kliknięty), wówczas przechodzi do następnej grupy. Jeśli zamiast tego jeden z elementów sterujących w grupie jest aktywny, wówczas przechodzi do następnego elementu sterującego w tej grupie. Tak właśnie ma działać system.

Tak więc nie tylko wejście klawiatury musi być aktywnym procesem sterowania, ale teraz musi farmować wszelkie nieprzetworzone dane wejściowe dla kontrolki, która jest jego właścicielem . Albo to, albo elementy sterujące muszą znajdować się na jakiejś połączonej liście, aby można je było przewijać do przodu i do tyłu. Oznacza to, że w każdej kontrolce musi być domyślne zachowanie.

To brzmi coraz bardziej jak zachowane GUI, prawda? Jedyna różnica polega na tym, że ... to ty wykonujesz ciężką pracę. Używanie cudzego GUI powinno być sposobem na wykonanie mniejszej pracy. Ale wysiłek, jaki należy podjąć, aby GUI zareagował zgodnie z oczekiwaniami użytkownika, nie jest trywialny.

Pamiętaj: interfejs użytkownika nie jest dla ciebie, jest dla twoich użytkowników . To jest dla gracza. Powinno zachowywać się tak, jak tego oczekują. A jeśli nie, to nie powiodło się.

Interfejsy użytkownika zwykle nie muszą być automatycznie układane ani mieć okien w trakcie pracy, których rozmiar można zmieniać.

To ograniczona i ograniczająca myśl.

Mógłbym dać gadkę o różnych gier mających różne potrzeby UI, że niektóre gry zrobić potrzebę Resizeable okien i tak dalej. Ale jest o wiele większy problem.

Twój sposób myślenia prowadzi do problemu Gratuitous Space Battles.

Jeśli nigdy nie grałeś w tę grę, jest to tania, niezależna i bardzo obciążająca GUI gra. Właściwa rozgrywka odbywa się w GUI (jest to gra typu „ustaw jednostki i patrz, jak walczą”). Problem?

GUI NIE MOŻNA ODWOŁAĆ!

Och, w porządku, jeśli używasz normalnego monitora lub masz normalny wzrok. Ale jeśli na przykład jesteś mną, który prowadzi absurdalnie ogromny monitor (taki tak duży, że system Windows przeskalowuje rozmiar całego tekstu, aby można go było przeczytać), to jest okropne . Tekst jest mikroskopijny. Nie ma możliwości zmiany rozmiaru czcionki.

To prawda, że ​​GSB to gra oparta na GUI, więc jest dla nich absolutnie niewybaczalna. Gra z graficznym interfejsem użytkownika może prawdopodobnie uciec.

Nigdy nie zakładaj, że użytkownik patrzy na swoją grę dokładnie tak , jak Ty. Takie postępowanie jest głupotą.

Posiadanie systemu GUI, który może przeskalować się do rozdzielczości użytkownika, prawdziwie niezależny od rozdzielczości GUI, wymaga, aby układ był częścią samego systemu GUI. Jeśli tego nie zapewnisz, twój tekst będzie wyglądał na mały na czyimś gigantycznym monitorze. To nie jest dobra rzecz.

Powiedziałbym więc, że twoje myślenie na ten temat jest krótkowzroczne. Ci nie muszą takie rzeczy. Potrzebujesz tego, co zapewniają zachowane GUI. Och, możesz nie potrzebować wszystkiego, co zapewnia dany system GUI. Ale potrzebujesz trochę tego.

Podstawowa praca, którą musisz wykonać, aby uzyskać dane do systemu, to niewielka cena, którą musisz zapłacić, oprócz posiadania wystarczającej pewności, że użytkownik może poprawnie współpracować z elementami sterującymi i że zmieni rozmiar, aby dopasować się do potrzeb gracza.

Być może będziesz w stanie uciec z graficznym interfejsem użytkownika w trybie natychmiastowym, jeśli nie pobierzesz dużo danych od odtwarzacza. Ale to by było na tyle.

Nicol Bolas
źródło
5
Nie bierz tego w niewłaściwy sposób, ale czy mogę zapytać ponownie, czy mówisz na podstawie rzeczywistego doświadczenia z faktycznym użyciem bezpośredniego interfejsu GUI w rozwoju gry (i jak czytam twoją opinię: prawdopodobnie zastąpienie go w połowie rozwoju) frustracji;))? Nawiasem mówiąc: opisana funkcjonalność pola tekstowego może być (i jest np. W UnityGui.TextField) zaimplementowana w klasie RenderTextBox. Ponadto nic w podejściu do natychmiastowego GUI nie zabrania projektantowi biblioteki używania klas dla formantów GUI, jeśli jest to właściwe. Po prostu użycie byłoby zupełnie inne.
Imi
1
@Immanuel: „Nawiasem mówiąc: opisana funkcjonalność pola tekstowego może być (i jest np. W UnityGui.TextField) zaimplementowana w klasie RenderTextBox.” Powiedziałeś, że to RenderTextBoxbyła funkcja , a nie klasa. Więc twój podział na „tryb natychmiastowy” i „tryb zatrzymany” wydaje się dotyczyć miejsca przechowywania danych, a nie tego, kto nimi zarządza. Jeśli tak, musisz uwydatnić to rozróżnienie w swoim pytaniu, ponieważ sugeruje, że „GUI trybu natychmiastowego” po prostu rysuje rzeczy na ekranie. Że nie może uzyskać danych wejściowych (ponieważ wymagałoby to trwałego stanu) i tak dalej. Więc co to jest?
Nicol Bolas
1
@ImmanuelScholz: „Nie widzę argumentu przeciwko ogólnemu„ Natychmiastowemu podejściu do GUI ”w tym„ Pomyślałem, że całkiem dobrze to wytłumaczyłem: ktoś musi napisać kod . Ktoś musi uzyskać dane wejściowe, przesunąć kursor, zarządzać bieżącym sterowaniem, obsługiwać układ itp. Twój opis GUI „trybu natychmiastowego” traci to wszystko , a wszystko to jest ważne dla wszystkiego, z wyjątkiem najbardziej uproszczonego opartego na wynikach GUI. Dlatego nie widzę twojego argumentu, że „natychmiastowe podejście do GUI” ma jakiekolwiek zalety .
Nicol Bolas,
1
Wybacz, moja wina. „... zaimplementowane w funkcji RenderTextBox” (nie klasa). Jest to funkcja, która przetwarza dane wejściowe użytkownika, a biblioteka zachowuje pewien stan (jak bieżąca kontrola skupiona). Proszę, żadne przestępstwo nie jest zamierzone, ale czy mogę założyć, że znasz tylko „natychmiastowe GUI” z mojego postu tutaj i nie spojrzałeś na IMGUI ani GUI Unity3D? Z pewnością nie zrozumiałem tu szczegółowo, co zawiera „natychmiastowy GUI”, chciałem tylko podsumować, aby nie mówić o całkowicie różnych rzeczach (np. Nie mylić z „natychmiastowym trybem graficznym”).
Imi
2
@ImmanuelScholz: „Z pewnością nie zrozumiałem, co szczegółowo zawiera„ natychmiastowy interfejs GUI ”.„ Twoje pytanie jest niepełne. Rzeczywiście, jest to raczej mylące, ponieważ „tryb natychmiastowy” implikuje brak stanu. Termin „zachowany” pochodzi od tego, że ma stan. Więc jeśli „GUI trybu natychmiastowego” zachowuje stan ... to nie jest tryb natychmiastowy.
Nicol Bolas,
8

Jakiś czas temu zainteresowałem się również IMGUI, jako test napisałem kilka samouczków, aby zapoznać się z technikami (zacznij tutaj, jeśli jesteś zainteresowany, ale to niewiele więcej niż C # / XNA + oryginalny „samouczek” tutaj ) .

Naprawdę bardzo mi się podobały IMGUI, ponieważ wyświetlane przez nich informacje są zawsze aktualne i poprawne (ponieważ nie ma stanu, w którym zawsze podajesz rzeczywiste dane). Ale w końcu straciłem zainteresowanie, więc normalnie teraz znów używam zachowanych GUI.

W końcu pomyślałem, że bezpośredniość GUI utrudnia oddzielenie GUI od danych i czasami starałem się rozdzielić rzeczy wprowadzając jakiś stan, łamiąc elegancję IMGUI. Nie sądzę też, że pisanie kodu dla zachowanych GUI to więcej pracy niż pisanie kodu dla IMGUI i podoba mi się, że zachowane GUI można uruchomić i zapomnieć, a ja naprawdę lubię wydarzenia :).

Jednak za każdym razem, gdy ktoś wspomina o IMGUI, gdy coś we mnie chce spróbować jeszcze raz i starać się to naprawić, ponieważ naprawdę jest w tym trochę elegancji, nie jestem w 100% pewien, czy to zawsze ułatwi ci pracę. Powiedziałbym, że wypróbuj, może spróbuj tak samo, jak to zrobiłem i napisz kilka samouczków (znajduję najlepszy sposób, aby nauczyć się nowych technik, wyjaśniając je innym).

Roy T.
źródło
8

Dużo pracowałem z systemem GUI Unity3D, który działa tak, jak opisano. I muszę powiedzieć, że nienawidzę tego z pasją.

Podejście „natychmiastowe” działa naprawdę dobrze w niektórych przypadkach. Po pierwsze, gdy potrzebujesz tylko kilku przycisków i etykiet - na przykład HUD strzelanki. Tworzenie ich przy użyciu „zatrzymanego” podejścia nie jest bardzo trudne, ale jest bardzo łatwe dzięki UnityGUI. Drugi przypadek ma miejsce, gdy trzeba wypchać wiele elementów sterujących na ekranie, ale tak naprawdę nie obchodzi ich układ. Zwłaszcza, gdy dokładne kontrole są znane tylko w czasie wykonywania. Nie jest to w rzeczywistości przydatne w żadnej grze, ale jest bardzo pomocne, gdy narzędzia działają w edytorze Unity.

Jednak jakikolwiek na wpół złożony GUI - na przykład RPG (MMO) lub gra strategiczna - nieuchronnie zamienia się w okropny bałagan nieczytelnego kodu, pełnego specjalnych przypadków i mnóstwa sposobów. Podczas budowania takiego GUI zwykle masz dość specyficzny układ, który musi działać dla dowolnej rozdzielczości i być w stanie pokazać wszystkie dane, które wysyłasz. Potrzebujesz rzeczy, takich jak na przykład przesunięcie niektórych przycisków niżej, aby zrobić miejsce na dłuższy tekst. Dzięki „zachowanemu” GUI możesz mieć kontrolę, która robi to automatycznie. W trybie „natychmiastowym” nie ma żadnych elementów sterujących, więc musisz zrobić wszystko jawnie.

Innym problemem związanym z UnityGUI (nie jestem pewien, czy dzieje się to ze wszystkimi GUI trybu natychmiastowego) jest to, że na przykład Button()połączenie działa bez uwzględnienia innych wywołań GUI. Tak więc, jeśli jeden przycisk znajduje się na drugim, kliknięcie spowoduje naciśnięcie obu przycisków jednocześnie. To zdecydowanie nie jest to, czego oczekuje użytkownik, więc dodaje to kolejny specjalny przypadek do obsługi.

Aby żyć z tym wszystkim, zawsze pisałem własne opakowanie wokół UnityGUI, które zamienia go w system trybu „zatrzymanego”: elementy sterujące, które przechowują swój stan i po prostu wywołują GUIdla mnie wymagane funkcje dla każdej ramki.

Nie mogę powiedzieć, że tryb „natychmiastowy” jest zdecydowanie gorszy niż „zachowany”, ale z pewnością czuję się znacznie lepiej pracując w trybie „zatrzymany”.

Nieważne
źródło
1
Tak, doświadczyłem każdego z tych problemów z graficznym interfejsem Unity i nienawidzę tego. Świetnie nadaje się do szybkich statycznych interfejsów, ale stanowi prawdziwy kłopot dla wszystkiego innego.
Kylotan
6

Będę tutaj bronić IMGUI, ponieważ niektóre z wcześniej wymienionych problemów można rozwiązać, jeśli zechcesz napisać dla niego kod. Dodatkowo, jeśli napiszesz dla niego kod, będziesz mieć solidną bibliotekę, którą można ponownie wykorzystać i tylko bardzo rzadko wymaga modyfikacji.

  • ładowanie GUI ze schematu

być może początkowo wydaje się, że artyści nie mają dużej elastyczności dzięki IMGUI, jest to rozwiązane lub ulepszane poprzez ładowanie układu GUI ze schematu xml lub JSON.

  • warstwa menu rysuje połączenia

ten problem został rozwiązany przy sortowaniu, powinieneś utworzyć klasę UI Manager, która sortuje kolejność losowania, rozwiązałem ten problem w C # XNA z ruchomymi, klikalnymi panelami, które rysują jeden na drugim. Mogę opublikować pseudo kod, jeśli zostanie o to poproszony.

  • pola listy

czy możesz narysować ciągi z tablicy? czy możesz zdefiniować obszary prostokąta na podstawie wysokości i szerokości czcionek tych ciągów? czy możesz stworzyć stosunek wielkości przycisku przewijania do wysokości wszystkich tych prostokątów zsumowanych? Następnie jesteś w połowie drogi do utworzenia pola listy z przewijalnym przyciskiem, aby poruszać się w górę lub w dół. Myślałem, że to będzie trudne, ale okazało się, że jest o wiele prostsze niż myślałem. bez buforów, bez stanów, bez wywołań zwrotnych.

  • oddzielanie danych od GUI

nie pozwól, aby poszczególne panele, przyciski, pola przechowywały dane. Wiem, że moja pierwsza próba IMGUI była natychmiastowa, ale tylko w sensie graficznym. Popełniłem błąd zatrzymując dane w interfejsie użytkownika. To była niemal filozoficzna zmiana, aby inaczej myśleć o tym, gdzie umieścić i zmodyfikować dane za pomocą zmian interfejsu użytkownika.

  • GUI z zestawów SDK

to jest granica i funkcjonalność kodu SDK, a nie twój. Uważam, że SDK UI (Hammer, Unity, UDK) to prawie nowy język do nauki. W rzeczywistości są one podobne do mnie jak Windows. Formaty, oba są skonfigurowane dla najszerszej możliwości i dlatego mają dodatkową wagę w złożoności.

i na koniec obejrzyj to> http://mollyrocket.com/861

Bixel
źródło
4

Interfejsy użytkownika zwykle nie muszą być automatycznie układane ani mieć okien w trakcie pracy, których rozmiar można zmieniać. Zamiast tego muszą bardzo efektywnie współdziałać z ciągle zmieniającymi się danymi (takimi jak pozycje modeli na świecie w 3D)

To zależy od gatunku i gry. Dobry system zarządzania zapasami jest niezbędny w większości gier RPG. Będziesz chciał czegoś, co obsługuje układy dla Ciebie, obsługuje paski przewijania, przeciągnij i upuść, podpowiedzi i inne funkcje o wiele łatwiejsze do zaimplementowania przy użyciu Zachowanego GUI.

Nie mogę wymyślić sposobu przeciągnięcia i upuszczenia za pomocą natychmiastowego interfejsu GUI, który nie wymaga dużo żonglowania lub oszczędzania stanu użytkownika, takich jak tymczasowa zmiana bufora Z i przechowywanie informacji o czasie w celu wykluczenia kliknięcia, które zdarzyło się przenieść kawałek.

Ale z perspektywy projektowania mam problem z wyobrażeniem sobie świata bez moich wydarzeń z GUI. Natychmiastowe GUI nie jest kompatybilne z OOP, co zmusza Cię do programowania proceduralnego.

Prostota zapewniana przez bezpośrednie interfejsy GUI wiąże się z kosztem dodatkowej złożoności kodu, który szybko rośnie wraz ze wzrostem złożoności wymaganej przez interfejs użytkownika; gdzie jako dobrze zachowane GUI jest początkowo bardziej złożone, ale skaluje się lepiej. Tak więc poniżej pewnego poziomu złożoności wystarcza bezpośredni GUI, ale w większości sytuacji wolę zachować GUI.

ClassicThunder
źródło
1
Chcę cię zapytać: czy twoja opinia pochodzi z rzeczywistych doświadczeń, czy z myśli teoretycznej, patrząc na oba systemy? Uhm .. to brzmi bardziej ostro niż zamierzałem, przepraszam .. Mam na myśli: dzielę się twoją opinią i oceną z teoretycznego punktu widzenia. Systemy podobne do IMGUI najprawdopodobniej prowadzą do mniejszego kodu OOPish (jeśli jest to problem), mają problemy z kontrolkami, które wymagają pewnego stanu i tak dalej. To po prostu ... normalne systemy GUI są już same w sobie bardzo duże i złożone, więc masz dużo złożoności do dodania, dopóki nie zbliżysz się do tych systemów.
Imi
1
Immanuel, nie musisz mieć prawdziwego doświadczenia programistycznego, aby wiedzieć, że wiele gier wymaga automatycznego układu i skalowalnych okien.
Kylotan
1
@Immanuel Scholz Przyznaję, że mam znacznie więcej doświadczenia z zachowanymi interfejsami użytkownika; utrzymywanie jednego z nich jako projektów OSS i współpraca z nimi przez mojego przewoźnika (co prawda jest bardzo młoda). Jednak użyłem systemu interfejsu użytkownika Unity3D i zduplikowałem go po przejściu na XNA. Mój zachowany interfejs użytkownika został opracowany, ponieważ zmęczyło mnie kopiowanie wklejania tego samego hacka od projektu do projektu, aby osiągnąć jednolitą funkcjonalność.
ClassicThunder
@Kylotan przez „okna o zmiennym rozmiarze” Mam na myśli to, że możesz aktywnie zmieniać rozmiar elementów interfejsu użytkownika poprzez przeciąganie (lub w inny sposób) i automatyczne układanie, że po zmianie rozmiaru interfejs użytkownika dostosowuje się w „miły” sposób, jak wyświetlanie pasków przewijania, przydzielanie wielu linie do pasków przycisków i tak dalej. Tak, czasami widzę to w grach, ale jest to znacznie bardziej powszechne w aplikacjach komputerowych. Poza tym myślę, że tworzenie dobrych, skalowalnych interfejsów użytkownika nie jest najłatwiejszą rzeczą dla zachowanych systemów GUI.
Imi
1
Okna o zmiennym rozmiarze i autolayout to w zasadzie to samo. W trybie zatrzymanym GUI każda kontrolka zna swój rozmiar (niezależnie od tego, czy zmienia się w środowisku wykonawczym, czy nie), a autoukład jest w zasadzie rekurencyjnym sprawdzaniem wielkości. Prawdopodobnie jest to ważniejsze w grach niż w aplikacjach komputerowych, ponieważ oczekujemy pełnoekranowych interfejsów GUI w różnych proporcjach i na różnych platformach.
Kylotan,