{"id":3065,"date":"2021-01-02T13:50:30","date_gmt":"2021-01-02T05:50:30","guid":{"rendered":"http:\/\/blog.coolcoding.cn\/?p=3065"},"modified":"2021-01-02T19:44:20","modified_gmt":"2021-01-02T11:44:20","slug":"responding-to-property-changed-events-from-the-editor","status":"publish","type":"post","link":"https:\/\/blog.coolcoding.cn\/?p=3065","title":{"rendered":"Responding to property changed events from the editor"},"content":{"rendered":"\n<p>When a designer changes the properties of an\u00a0Actor\u00a0placed in the level, it is often important to show any visual results of that change immediately rather than just when the level is simulated or played. When changes are made using the\u00a0Details\u00a0panels, there&#8217;s a special event that the editor emits called\u00a0PostEditChangeProperty, which gives the class instance a chance to respond to the property being edited. This recipe shows you how to handle\u00a0PostEditChangeProperty\u00a0for immediate in-editor feedback.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">How to do it&#8230;<\/h1>\n\n\n\n<ol><li>Create a new&nbsp;Actor&nbsp;called&nbsp;PostEditChangePropertyActor&nbsp;based on&nbsp;StaticMeshActor:<\/li><\/ol>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/blog.coolcoding.cn\/wp-content\/uploads\/2021\/01\/45976a36-1621-403c-973b-afa3c859cabe.png\" alt=\"\"\/><\/figure>\n\n\n\n<ol><li>Add the following&nbsp;UPROPERTY&nbsp;and function definition to the class:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">UCLASS()<br>class CHAPTER_09_API APostEditChangePropertyActor : public <br>AStaticMeshActor<br>{<br>    GENERATED_BODY()<br><br><strong>    \/\/ Sets default values for this actor's properties<\/strong><br><strong>    APostEditChangePropertyActor();<\/strong><br><br><strong>    UPROPERTY(EditAnywhere)<\/strong><br><strong>    bool ShowStaticMesh = true;<\/strong><br><br><strong>    virtual void PostEditChangeProperty(FPropertyChangedEvent&amp; <br>                                        PropertyChangedEvent) override;<\/strong><br>    <br>};<\/pre>\n\n\n\n<ol><li>Create the class constructor by adding the following code to the&nbsp;PostEditChangePropertyActor.cpp&nbsp;file:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">#include \"PostEditChangePropertyActor.h\"<br><strong>#include \"ConstructorHelpers.h\"<\/strong><br><br><strong>APostEditChangePropertyActor::APostEditChangePropertyActor()<\/strong><br><strong>{<\/strong><br><strong>    \/\/ Set this actor to call Tick() every frame. You can turn<br>    \/\/ this off to improve performance if you don't need it.<\/strong><br><strong>    PrimaryActorTick.bCanEverTick = true;<\/strong><br><br><strong>    auto MeshAsset = ConstructorHelpers::FObjectFinder&lt;UStaticMesh&gt;<br>    (TEXT(\"StaticMesh'\/Engine\/BasicShapes\/Cone.Cone'\"));<\/strong><br><br><strong>    UStaticMeshComponent * SM = GetStaticMeshComponent();<\/strong><br><br><strong>    if (SM != nullptr)<\/strong><br><strong>    {<\/strong><br><strong>        if (MeshAsset.Object != nullptr)<\/strong><br><strong>        {<\/strong><br><strong>            SM-&gt;SetStaticMesh(MeshAsset.Object);<\/strong><br><strong>            SM-&gt;SetGenerateOverlapEvents(true);<\/strong><br><strong>        }<\/strong><br><strong>        SM-&gt;SetMobility(EComponentMobility::Movable);<\/strong><br><strong>    }<\/strong><br><strong>}<\/strong><\/pre>\n\n\n\n<ol><li>Implement&nbsp;PostEditChangeProperty:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">void APostEditChangePropertyActor::PostEditChangeProperty( FPropertyChangedEvent&amp; PropertyChangedEvent)<br>{<br>    \/\/ Check if property is valid<br>    if (PropertyChangedEvent.Property != nullptr)<br>    {<br>        \/\/ Get the name of the changed property<br>        const FName PropertyName( <br>                            PropertyChangedEvent.Property-&gt;GetFName());<br><br>        \/\/ If the changed property is ShowStaticMesh then we<br>        \/\/ will set the visibility of the actor<br>        if (PropertyName == GET_MEMBER_NAME_CHECKED( <br>                         APostEditChangePropertyActor, ShowStaticMesh))<br>        {<br>            UStaticMeshComponent * SM = GetStaticMeshComponent();<br><br>            if (SM != nullptr)<br>            {<br>                SM-&gt;SetVisibility(ShowStaticMesh);<br>            }<br>        }<br>    }<br><br>    \/\/ Then call the parent version of this function<br>    Super::PostEditChangeProperty(PropertyChangedEvent);<br>}<\/pre>\n\n\n\n<ol><li>Compile your code and launch the editor.<\/li><li>Drag an instance of your class into the game world and verify that toggling the Boolean value for&nbsp;ShowStaticMesh&nbsp;toggles the visibility of the mesh in the&nbsp;editor viewport:<\/li><\/ol>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/blog.coolcoding.cn\/wp-content\/uploads\/2021\/01\/dba850f4-0119-4dac-85a7-e24f6a9e78f0.png\" alt=\"\"\/><\/figure>\n\n\n\n<p>The location of the&nbsp;Show Static Mesh&nbsp;property<\/p>\n\n\n\n<p>Then, if you ever toggle it off, you&#8217;ll see the object disappear, as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/learning.oreilly.com\/library\/view\/unreal-engine-4x\/9781789809503\/assets\/340c8760-1eda-48ab-91fd-99f5034777b0.png\" alt=\"\"\/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">How it works&#8230;<\/h1>\n\n\n\n<p>We create a new&nbsp;Actor&nbsp;based on&nbsp;StaticMeshActor&nbsp;for easy access to a visual representation via the Static Mesh.<\/p>\n\n\n\n<p>UPROPERTY&nbsp;is added to give us a property to change, which causes&nbsp;PostEditChangeProperty&nbsp;events to be triggered.<\/p>\n\n\n\n<p>PostEditChangeProperty&nbsp;is a virtual function that&#8217;s defined in&nbsp;Actor.<\/p>\n\n\n\n<p>As a result, we override the function in our class.<\/p>\n\n\n\n<p>Within our class constructor, we initialize our mesh as usual, and set the default state of our&nbsp;bool&nbsp;property to match the visibility of the component it controls.<\/p>\n\n\n\n<p>Inside&nbsp;PostEditChangeProperty, we first check that the property is valid.<\/p>\n\n\n\n<p>Assuming it is, we retrieve the name of the property using&nbsp;GetFName().<\/p>\n\n\n\n<p>FNames&nbsp;are stored internally by the engine as a table of unique values.<\/p>\n\n\n\n<p>Next, we need to use the&nbsp;GET_MEMBER_NAME_CHECKED&nbsp;macro. The macro takes a number of parameters.<\/p>\n\n\n\n<p>The first one is the name of the class to check, while the second parameter is the property to check the class for.<\/p>\n\n\n\n<p>The macro will, at compile-time, verify that the class contains the member specified by name.<\/p>\n\n\n\n<p>We compare the class member name that the macro returns against the name that our property contains.<\/p>\n\n\n\n<p>If they are the same, then we verify that our&nbsp;StaticMeshComponent&nbsp;is initialized correctly.<\/p>\n\n\n\n<p>If it is, we set its visibility to match the value of our&nbsp;ShowStaticMesh&nbsp;Boolean.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When a designer changes the properties of an\u00a0Actor\u00a0plac [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27,1],"tags":[26],"_links":{"self":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/3065"}],"collection":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3065"}],"version-history":[{"count":2,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/3065\/revisions"}],"predecessor-version":[{"id":3349,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/3065\/revisions\/3349"}],"wp:attachment":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3065"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3065"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3065"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}