UMG ScrollBox

  • Hallo zusammen,


    ich versuche gerade ein UMG Widget zu erstellen, dass mir mein Inventar anzeigt. Dafür wollte ich eine ScrollBox verwenden. Hier mein bisheriger Code:


    .h


    .cpp

    Code
    void MyUserWidget::Construct_Implementation()
    {
        UE_LOG(LogTemp, Warning, TEXT("MyUserWidget-------Construct-----"));
    
    
        //TSharedPtr<class SScrollBox> scrolli = ScrollBox->MyScrollBox;
    }


    Nun wollte ich entweder in der Construct oder RebuildWidget Methode in die ScrollBox Items hinzufügen. Nun ist mein Problem, dass es keine add Methode oder sonstige Methoden gibt, die ich gesehen habe, die mir irgendwie helfen könnten. Nur die SSrollBox (https://docs.unrealengine.com/…out/SScrollBox/index.html) besitzt eine AddSlot Methode. Da ich im Code von der UScrollBox gesehen habe, dass sie eine protected SScrollBox besitzt, wollte ich diese dann modifizieren, allerdings konnte ich dann auch nicht auf "MyScrollBox" zugreifen.


    Das Ziel sollte eine Anzeige vom Inventar sein, dass man durchscrollen kann und das mit Werten aus der Inventarklasse gefüttert wird. Von dem Modus (Kampf, Nicht-Kampf, ...) abhängig, kann man die Items dann einsetzen, d.h. ich brauche wahrscheinlich dynamische Buttons, bei denen ich dann das Textfeld setzen muss und bei denen ich dann das Event abfragen muss.


    Ich hoffe es kann mir jemand weiterhelfen.
    Vielen Dank schon einmal!

  • Warum willst du mit UMG aus C++ heraus Arbeiten? Macht die Sache nur unnötig kompliziert.


    Aber hier die Erklärung (auch wenn ich mit UMG noch nicht aus C++ raus gearbeitet habe):


    Aus der Dokumentation der SScrollBox entnehme ich folgendes:


    https://docs.unrealengine.com/…out/SScrollBox/index.html


    Die Scrollbox verwaltet eine Liste vom Typ "FSlot", dieser Liste kannst du mit "AddSlot" entsprechende Childs/Slots hinzufügen.


    "AddSlot" gibt dir nun einen neuen "FSlot" zurück, geht man nun die Vererbungshierarchie rauf, landet man bei "FSlotBase".
    "FSlotBase" enthält eine Methode "AttachWidget", diese ist nicht weiter Dokumentiert, aber aus dem Namen lässt sich schließen, dass du damit dem Slot ein Widget zuweist und somit deiner Scrollbox ein Widget hinzufügst.


    AddSlot:


    Code
    SScrollBox::FSlot& SScrollBox::AddSlot()
    {
        ScrollBox::FSlot& NewSlot = *new SScrollBox::FSlot();	
        ScrollPanel->Children.Add( &NewSlot );
        return NewSlot;
    }



    Ok mea culpa, hab nicht gesehen, dass "MyScrollBox" protected ist, müsstest also ne eigene "UScrollBox" erstellen (bzw. davon erben) und dir nen Getter dafür dazu schreiben.

  • Wenn Du alles in C++ machen möchtest kannst Du auch gleich Slate nehmen, das ist für C++ besser dokumentiert und UMG baut afaik nur darauf auf. Ist sozusagen die Blueprint Variante davon, aber mag mich irren, hab es noch nicht so mit GUI.


    Ansonsten kann ich Exklusiv nur zustimmen, Slots sind der Dreh und Angelpunkt der Widgets.
    Aber so wie ich dein Ziel interpretiert habe, ist vielleicht ne Wrapbox mit nen "Kategorie Schalter" einfacher und effizienter.

  • Zitat

    UMG baut afaik nur darauf auf. Ist sozusagen die Blueprint Variante davon, aber mag mich irren, hab es noch nicht so mit GUI.


    Vollkommen richtig, UMG ist sozusagen ein Wrapper für Blueprints um Slate.


    Bin gerade aber nochmal die Vererbungshierarchie der UScrollBox durch gegangen, die erbt doch von UPanelWidget und UPanelWidget bietet dir doch die Funtktion "AddChild" welcher du dein UWidget übergibst und einen UPanelSlot zurück bekommst. Hab mir den Code der Methode jetzt nicht nochmal genau angeguckt, aber damit könnte es auch gehen.

  • UMG ist darauf ausgelegt das UI über den Editor und Blueprints zu erstellen für C++ ist das gar nicht gedacht, geht zwar auch klar aber ist halt wie du selbst festgestellt hast nicht unbedingt der beste und einfachste weg.


    Wenn du es wirklich unbedingt in C++ machen willst dann wäre Slate deutlich besser

  • Ihr habt mir ein ordentliches Stück weitergeholfen!


    Ich hatte eure Tipps befolgt, von WrapBox geerbt und einen getter für das protected SWidget MyWrapBox geschrieben. Jetzt habe ich ein Style-Problem:


    [Blockierte Grafik: http://img1.picload.org/image/irlwrgc/screenshot_menu.png]


    Die Größe von "Label here..." kann ich ändern, weil das ein STextBlock ist, aber die Größe und den Style der Einträge von AddMenuEntry kann ich nicht ändern.



    #1 (Zeile 41) funktioniert und führt zu dem gezeigten Bild. #2 (Zeile 48) funktioniert nicht aufgrund "nicht matchender arguments". Hier alle Signature: https://docs.unrealengine.com/…r/AddMenuEntry/index.html
    So wirklich verstehe ich auch nicht, warum #1 funktioniert, da die Argumente auch zu keiner Signatur passen (ich habe gerade erst mit C++ angefangen).

  • #1 Doch die Argumente passen zu genauer einer Signatur:


    https://docs.unrealengine.com/…AddMenuEntry/3/index.html


    Die letzten 3 Parameter sind nur Optional und haben Default Werte


    #2 Warum willst du da Pointer verwenden? Macht an der Stelle keinen Sinn.


    Der Mismatch kommt übrigens durch deine Parameter "ftext" und "name" (Parameter 3 und 4), die Methode erwartet keinen Pointer, du wirfst ihr aber welche rein.


    Sollte dir Visual Studio aber eig. auch sagen wenn du über den Methodenaufruf hoverst



    BTW: Über den Editor hast du nen Visual Designer fürs UI und du machst dir das leben deutlich leichter

  • Hier mal mehrere (Anfänger-)Fragen:


    1. Das hab' ich mir auch schon gedacht, sonst würde es auch nicht funktionieren, aber wo wurde angegeben, dass die letzten drei Parameter optional sind?


    2. Das war nur die schnelle dreckige Version, damit ich zumindest einen Arugmentmatch bekomme. Selbst wenn ich bei 3 und 4 keinen Pointer anwende, bekomme ich eine Fehlermeldung:

    Code
    FName* name = new FName();
                //FText* ftext = new FText();
                MenuBuilder.AddMenuEntry(
                    Action,
                    swidget,
                    FName(),
                    FText(),
                    EUserInterfaceActionType::Button,
                    *name
                    );


    Zitat

    void FBaseMenuBuilder::AddMenuEntry(const FUIAction &,const TSharedRef<SWidget,0>,const FName &,const TAttribute<FText> &,const EUserInterfaceActionType::Type,FName)' : cannot convert argument 1 from 'FUIAction' to 'const TSharedPtr<const FUICommandInfo,0>'


    3. Wie könnte ich das im Editor ändern/ machen? Bis jetzt habe ich keine MenuBuilder gesehen, der dynamisch Items von mir entgegennimmt und bei Klicken ein Event mit Parameter startet.

  • 1. Im Source Code der Engine


    2. Hmm irgendwie versucht er auf die andere Überladung zurück zu greifen die als 1 Parameter den SharedPointer entgegen nimmt, kann ich so gerade auch nicht nach vollziehen.


    3. Weil du dich nicht richtig mit UMG und Blueprints auseinander gesetzt hast.


    Kurze Erklärung:


    Um UMG zu verwenden erstellst du ein Widget Blueprint dort hast du einen Designer mit dem du dein UI gestalten kannst (auch z.B. kombinieren aus verschiedenen Widgets) für z.B. Buttons kannst du dort dann im Blueprint Click Events erstellen welche z.B. C++ Funktionen aufrufen.


    Dort hast du auch Construct Events etc. alles da was du brauchst und 1000 mal einfacher als den ganzen kram in C++ zu schreiben (deswegen haben sie UMG ja überhaupt erst erstellt)

  • 1.
    Das ist mir schon klar, den habe ich auch die ganze Zeit gesehen, aber ich konnte nicht nachvollziehen, woraus aus der Signatur hervogeht, dass Parameter optionalisiert werden. Ich hatte mir vorher nur die .cpp angesehen, wahrscheinlich macht das das NAME_None aus der Headerdatei:

    Code
    void AddMenuEntry( const TAttribute<FText>& InLabel, const TAttribute<FText>& InToolTip, const FSlateIcon& InIcon, const FUIAction& UIAction, FName InExtensionHook = NAME_None, const EUserInterfaceActionType::Type UserInterfaceActionType = EUserInterfaceActionType::Button, FName InTutorialHighlightName = NAME_None );


    3. Danke, ich werde mal schauen, wie ich das mit Blueprints hinkriegen.

  • Generell würde ich den Design Aspekt von UMG nur im Editor nutzen, soll heißen du erstellst dir dein von UUserWidget abgeleitetes Widget packst alles an programmierung rein wie du es benötigst. Um an die einzelnen Elemente zu kommen kannst du folgende funktion nutzen


    https://docs.unrealengine.com/…WidgetFromName/index.html


    Danach erstellst du im editor ein neues UMG Widget und nutzt die Reparent Option. Nun Designst du dir dein Widget zurecht wie du es benötigst und kannst die ganzen annehmlichkeiten von UMG mit der geschwindigkeit von c++ vereinen.