Announcement

Collapse
No announcement yet.

widget button to change object material - where to script the actions?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    widget button to change object material - where to script the actions?

    hey, so I'm making an interface to change an object's materials, it's really just a couple animated buttons on the screen, I made a widget blueprint with the buttons and a little scripted blueprint to animate them.

    what confuses me is where to script the things I want. I was trying to make the widget create itself on it's blueprint when I gave up because I couldn't find the event beginplay node there. I had to search where the template was creating it's interfaces and went from there, it has an actor blueprint with the menu being created there, so I tried to make my interface there and it worked, but it doesn't sound very logical to me.

    I mean, it's a random sphere placed in the world creating an important thing such as a menu, is this how it works generally? I'd assume there should be some sort of general stuff blueprint or something.

    and secondly, I wanted to make the buttons do something, so in the same place I was creating my interface (the random actor blueprint) I tried to have a button click event to do something, but couldn't find it or summon it from there or whatever it's called, so I went back to the widget blueprint and placed the actions there, so it kinda worked, but I had to place a "get all actors of class" node and find my object's blueprint (the one I wanted to change the materials).

    so it's still a bit confusing, I don't really know where to make stuff, and how to interact with things that are somewhere else, like an actor blueprint creating a widget interface that does something to another actor. I mean if I was going to try to figure it out, I'd make a variable for each material I want to change, and tell the buttons to switch that variable to another one, but that's not how it works at all.

    what is the proper way to set this up?
    behance.net/fael097

    #2
    [...] I was trying to make the widget create itself on it's blueprint when I gave up because I couldn't find the event beginplay node there.
    Widgets have a Event Construct instead of Begin Play. But you cannot create an object from within itself.

    it has an actor blueprint with the menu being created there, so I tried to make my interface there and it worked, but it doesn't sound very logical to me. I mean, it's a random sphere placed in the world creating an important thing such as a menu, is this how it works generally? I'd assume there should be some sort of general stuff blueprint or something.
    Not the worst idea (especially if it's a stand alone 3d menu) but could be done better. You could choose one of the framework classes (player controller, game mode, game instance) and create the widgets there. This allows you to store their references which, in turn, makes gaining access to them easy since the aforementioned classes are available from any other blueprint, including Level Blueprint.

    I particularly like using the HUD class for this as it has a couple of extra features - like drawing lines, for example. And it comes across as logical to use it as a communication hub for the widgets.

    but I had to place a "get all actors of class" node and find my object's blueprint (the one I wanted to change the materials).
    What I mentioned above regarding references will give you a direct way to gain access to an object without relaying on the get all of something nodes which I see misused way too often.

    Try creating your menu in the GameMode (check this out if you've yet to set one up), don't forget to store a menu reference by promoting the Return Value of the Create Widget node. Then, any time you need access to the menu, you can Get Game Mode > Cast (to your own GameMode > get Menu Reference > access buttons and variables in the widget.

    Comment


      #3
      So basically what you want is some object (i.e. a sphere or whatever) with a material, and you want some UMG widgets on screen that can manipulate that sphere.

      What i'd do is split it up between the player controller, the UMG widget and the actor that is going to be manipulated:

      In the Widget, say "UMGSphereInterfaceWidget"
      1) Add a "SuperSphere" actor reference and click "editable" and "expose on spawn". That makes it so when you create the widget you have an additional parameter so you can add the actor this widget is supposed to manipulate. That way you'll never have to "get all actors of class" when using this widget.

      CustomPlayerController :
      1) Add function "CreateSphereWidget", having a SuperSphere reference as input.
      In that function simply call "Create Widget" and create your UMGSphereInterfaceWidget and plug in/forward the reference from the function input to the create widget node

      Create the object to manipulate, say "SuperSphere".
      1) Create some function "ChangeMaterial" with the desired parameters and behavior to change the material
      2) On Begin Play make it get the player controller index 0, cast it to your custom player controller call custom player controllers function "CreateSphereWidget" and give it "reference to self" as input.

      Then in the Widget again, add your desired function "OnButtonPressed".
      In this function ,get your reference to the sphere that you saved in the widget, check if its valid (never hurts to check). If its valid, call the references "ChangeMaterial" and pass in the desired parameters

      Now you have your logic split up in a logical fashion :
      When the game begins, the SuperSphere actor gets the current players player controller, the player controller creates the widget.
      If the UMGButton is pressed, the buttons only responsibility is to tell the referenced SuperSphere "hey, do something with parameters a, x and z". The SuperSphere actor then itself has the functionality to do something with the input, aka change the material based on input.

      Alternatively, instead of using BeginPlay on the SuperSphere to spawn the widget, you can add a trigger box to the SuperSphere actor,and add an OnActorOverlap so only when the player comes close to it it'll create the widget on screen. And you can also make it so when the player moves away the UMG widget gets removed.

      Comment


        #4
        thanks guys.

        Originally posted by Everynone View Post
        I particularly like using the HUD class for this as it has a couple of extra features - like drawing lines, for example. And it comes across as logical to use it as a communication hub for the widgets.
        this makes sense, what I'm making is a product viewer, and the menu interface thing I said is actually just a 2d interface on top of the window, that will always be there. it has some sort of expand and collapse actions to open more buttons, but that's all UMG, the interface is always on top.

        Originally posted by Everynone View Post
        What I mentioned above regarding references will give you a direct way to gain access to an object without relaying on the get all of something nodes which I see misused way too often. [HR]
        yeah I figured that this "get all of something" couldn't be the best way, but it's the only way I managed to call for the object. I know I must be doing something wrong, but I looked for it and still can't add an actor reference to my object. clicking and draggin into the variable doesn't work, a red dashed line appears, and the picker button is grayed out, so basically I'm struggling on the first step

        Originally posted by Everynone View Post
        Try creating your menu in the GameMode (check this out if you've yet to set one up), don't forget to store a menu reference by promoting the Return Value of the Create Widget node. Then, any time you need access to the menu, you can Get Game Mode > Cast (to your own GameMode > get Menu Reference > access buttons and variables in the widget.
        I always overlooked game modes, since I do mostly archviz, and this product configurator is some sort of spin off for me, but still not really a game. I've read that documentation but I'm not sure if I need to set up a game mode for this, are there any particular reasons I should?

        Originally posted by StefanHohnwald View Post
        What i'd do is split it up between the player controller, the UMG widget and the actor that is going to be manipulated:

        In the Widget, say "UMGSphereInterfaceWidget"
        1) Add a "SuperSphere" actor reference and click "editable" and "expose on spawn". That makes it so when you create the widget you have an additional parameter so you can add the actor this widget is supposed to manipulate. That way you'll never have to "get all actors of class" when using this widget.
        I'm trying to do this, but as I mentioned above, I'm struggling in the first step for some reason. my actor reference doesn't seem to work or I don't understand it well enough, even though I've read quite a few things about it
        Last edited by fael097; 08-15-2018, 10:09 PM.
        behance.net/fael097

        Comment


          #5
          I've read that documentation but I'm not sure if I need to set up a game mode for this, are there any particular reasons I should?
          Having your own custom game mode allows you to have custom framework classes - without those, communication is much, much harder.

          Comment


            #6

            Originally posted by Everynone View Post

            Having your own custom game mode allows you to have custom framework classes - without those, communication is much, much harder.


            So I made a hud blueprint creating the widget there, and created a game mode blueprint. didn't set anything on it but my base pawn as the default pawn class and the hud blueprint as the hud class. it displays the widget, but I still can't get my object actor reference from any blueprints
            Last edited by fael097; 08-16-2018, 09:14 AM.
            behance.net/fael097

            Comment


              #7
              didn't set anything on it
              Game Mode:

              Click image for larger version

Name:	Untitled.png
Views:	125
Size:	44.8 KB
ID:	1516169

              Create widget in the MyHud:

              Click image for larger version

Name:	intheHud.PNG
Views:	123
Size:	65.2 KB
ID:	1516170

              And in the LevelBlueprint, for example:

              Click image for larger version

Name:	lb.PNG
Views:	124
Size:	74.8 KB
ID:	1516171


              You can, of course, create the widget directly in the level blueprint - but then accessing it from inside of other blueprints is a bit more difficult.

              Comment


                #8
                yep, this I managed to do. only difference is that I've set my game mode in the project settings, not in the world override, but it's working, the hud is being displayed, no problem

                the problem is that the hud isn't actually doing anything, I can't give the buttons any kind of interaction with my object from inside my widget blueprint.

                my intention is to change the material of my object in my scene, named "SuperSphere". it's an actor class blueprint with a sphere mesh positioned in the world

                so in my widget blueprint I have some "on buton xx clicked" events, but I'd have to tell them do do something to my SuperSphere, but I can't call it from inside the widget blueprint to make the buttons do anything to it
                behance.net/fael097

                Comment


                  #9
                  For something that simple you should honestly just create the widget in the SuperSphere object:

                  Click image for larger version

Name:	cap1.PNG
Views:	123
Size:	78.7 KB
ID:	1516203

                  Click image for larger version

Name:	cap2.PNG
Views:	123
Size:	68.8 KB
ID:	1516204

                  SuperSphere creates the widget which has a reference exposed on spawn. This will link these two together.

                  This is precisely what @StefanHohnwald said:

                  In the Widget, say "UMGSphereInterfaceWidget"
                  1) Add a "SuperSphere" actor reference and click "editable" and "expose on spawn". That makes it so when you create the widget you have an additional parameter so you can add the actor this widget is supposed to manipulate. That way you'll never have to "get all actors of class" when using this widget.

                  Comment


                    #10
                    huh, now for some reason I managed to get that super sphere reference variable into the widget. I really tried doing it in every blueprint on the scene and couldn't.

                    but that turned into another problem, the code worked with a "get all actors of class" node followed by a for "each loop", but with the reference it doesn't. btw teapot below is my supersphere

                    Click image for larger version  Name:	1.jpg Views:	2 Size:	113.7 KB ID:	1516326

                    did I miss something?
                    behance.net/fael097

                    Comment


                      #11
                      Show us how you set the teapot reference. It's the first pic in my previous post - the create widget node has an extra SphereRef pin.

                      Could you briefly tell what it's going to be all about - a showroom with items the user can interact with, change their looks? Anything else?

                      Comment


                        #12
                        Originally posted by fael097 View Post
                        huh, now for some reason I managed to get that super sphere reference variable into the widget. I really tried doing it in every blueprint on the scene and couldn't.

                        but that turned into another problem, the code worked with a "get all actors of class" node followed by a for "each loop", but with the reference it doesn't. btw teapot below is my supersphere

                        Click image for larger version Name:	1.jpg Views:	2 Size:	113.7 KB ID:	1516326

                        did I miss something?
                        When you do it with the reference and end the play with Escape, does the editor give any kind of error message, akin to "Got None while trying to get reference in node SetMaterial"?
                        If the reference doesn't work, chances are that you didn't set the reference variable properly to point to the SuperSphere actor.

                        I agree with Everynone, please show us how you set the TeapotRef in the widget, aka how you set the TeapotRef to point to the SuperSphere actor.

                        What you can do for debugging : Use a "IsValid"-node to check if the TeapotRef actually points to a valid actor. if not, you can print out an error message. If the error message gets printed, you know that your reference is invalid.

                        Comment


                          #13
                          Originally posted by StefanHohnwald View Post
                          When you do it with the reference and end the play with Escape, does the editor give any kind of error message, akin to "Got None while trying to get reference in node SetMaterial"?
                          If the reference doesn't work, chances are that you didn't set the reference variable properly to point to the SuperSphere actor.
                          it returns two different errors:

                          Code:
                          Blueprint Runtime Error: "Accessed None trying to read property TeapotRef". Blueprint:  MaterialSelector Function:  Execute Ubergraph Material Selector Graph:  EventGraph Node:  Set Material
                          Blueprint Runtime Error: "Accessed None". Blueprint:  MaterialSelector Function:  Execute Ubergraph Material Selector Graph:  EventGraph Node:  Set Material
                          I also did what you suggested with the isvalid node, and turns out the TeapotRef is invalid. I really thought it should work, only managed to get that ref after some time burning my brain. I must be doing something very wrong


                          Originally posted by Everynone View Post
                          Show us how you set the teapot reference. It's the first pic in my previous post - the create widget node has an extra SphereRef pin.
                          I just added a variable inside my widget blueprint side panel, and found the teapot there. like this:
                          Click image for larger version  Name:	2.jpg Views:	1 Size:	48.3 KB ID:	1516547

                          then the moment I exposed it, "teapot ref" appeared on the HUD blueprint where the widget is being created, last item on the create widget node. i didn't pin a reference to self there cuz it's in the hud, not the actor, but since it says "teapot ref" i thought it was already referring to the correct thing.
                          Click image for larger version  Name:	1.jpg Views:	1 Size:	55.1 KB ID:	1516546

                          Originally posted by Everynone View Post
                          Could you briefly tell what it's going to be all about - a showroom with items the user can interact with, change their looks? Anything else?
                          right, so this is a product configurator for the costumer to be able to see the product in 3d with different materials and colors, cause it's a little dificult sometimes for them to imagine just from a picture of the product and a fabric sample, how the product would look like with the materials they have chosen. it's also impracticable to do renders with combinations of all the materials.

                          right now this is just a proof of concept, it will have only one chair spawned into the world, that is basically an infinite plane, and a 2d interface with two buttons, and when clicked each will show a sub menu with a few more buttons with material options for the seat or the structure. you can orbit/pan/zoom the camera around the chair, aswell as move the chair around.

                          if that works, it'll probably grow from there to all our products, implement on website, have an app for vendors with all the products, have an app for costumers to download and place the products with AR into their homes, and finally, an add to cart option with the selected materials.

                          not quite a brief description, but that kinda explains why I'm being cautious with some aspects of this. I'm not sure where I want to have the widget created because maybe somewhere along the way I'll try to test a way to add two different products into the scene and still be able to change their materials. maybe each product is going to have their own interfaces anyways cause the materials and parts are different for each product, but I'm not sure right now, so I'm trying not to commit, and even though I'm in the early stages, it's a lot of work for me to try to figure this all out with little knowledge of ue4.

                          right now I have it working with a teapot, an interface to change the material of the body and the lid separately, and just finished adjusting the camera controls. the material changing code is not perfect as I'm using the get all actors of class node, but you know, I'm trying. I also think I got a working code for changing just some aspects of the materials dynamically, for example, instead of having a material for a black leather and a blue leather, only changing the base color parameter of the material.
                          Last edited by fael097; 08-17-2018, 01:32 AM.
                          behance.net/fael097

                          Comment


                            #14
                            You're not putting anything in the Teapot ref... it's stays invalid. The widget does know which teapot you mean - what if you have 5 teapots? If you're doing this in the Teapot object just plug in self. This method of direct communication is OK when you need 1 to 1 comms - anything that grows in scope will need a different approach or will drive you mad when you need to rewire things for the nth time. Also, if you will never have more than 1 object at a time, (it hurts to say but here we go it's probably OK with Get All Actors of Class.

                            Your description makes perfect sense, btw. A couple of extra question, will the widget that controls the visuals of the object be unique for every object or differ a lot? How does the user skip to the next item?

                            Comment


                              #15
                              Originally posted by Everynone View Post
                              You're not putting anything in the Teapot ref... it's stays invalid. The widget does know which teapot you mean - what if you have 5 teapots? If you're doing this in the Teapot object just plug in self. This method of direct communication is OK when you need 1 to 1 comms - anything that grows in scope will need a different approach or will drive you mad when you need to rewire things for the nth time. Also, if you will never have more than 1 object at a time, (it hurts to say but here we go it's probably OK with Get All Actors of Class.
                              well it's not in the teapot itself, it's in the hud blueprint, so "self" doesn't work, and I'm still no able to properly reference the teapot anywhere, really don't know why or how.

                              Originally posted by Everynone View Post
                              Your description makes perfect sense, btw. A couple of extra question, will the widget that controls the visuals of the object be unique for every object or differ a lot? How does the user skip to the next item?
                              so eventually I'll have more than one object in the scene, and they will have different options in the interface, but the interface will be essentially the same, Not sure how it works yet but I was thinking of storing information on the objects regarding how many elements they have and the different material options that those elements can have, and then from the widget I'd just read those variables in order to create the appropriate interface for each object. should be easier (maybe not easier, but less work) than having a different interface for each object.

                              since in this proof of concept ther will be only one object and thus one interface, I'm not worrying too much about this for now, but I'm concerned on where the widget will be created, cause from what I've seen, there are many different ways to call for a reference deppending on what blueprint class you are doing it.
                              behance.net/fael097

                              Comment

                              Working...
                              X