<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>AYU MAX</title>
    <link>https://ayumax.net/</link>
    <description>Recent content on AYU MAX</description>
    <image>
      <title>AYU MAX</title>
      <url>https://ayumax.net/profile.jpg</url>
      <link>https://ayumax.net/profile.jpg</link>
    </image>
    <generator>Hugo -- 0.147.1</generator>
    <language>en</language>
    <lastBuildDate>Mon, 05 May 2025 21:55:20 +0900</lastBuildDate>
    <atom:link href="https://ayumax.net/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Released Froola</title>
      <link>https://ayumax.net/entry/2025/05/05/215520/</link>
      <pubDate>Mon, 05 May 2025 21:55:20 +0900</pubDate>
      <guid>https://ayumax.net/entry/2025/05/05/215520/</guid>
      <description>&lt;h2 id=&#34;froola&#34;&gt;Froola&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/ayumax/Froola&#34;&gt;https://github.com/ayumax/Froola&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Froola is a tool I created for testing Unreal Engine code plugins on multiple platforms simultaneously and generating plugin packages.&lt;/p&gt;
&lt;p&gt;Originally, I had developed several UE plugins that supported Windows and Mac platforms, which made package creation a tedious process each time.&lt;/p&gt;
&lt;p&gt;This is because in a Windows environment, you can create packages for Windows, Android, and Linux, but not for Mac and iOS.&lt;/p&gt;
&lt;p&gt;Therefore, I had to build the plugin in both Windows and Mac environments, and then combine them to create a single plugin package.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="froola">Froola</h2>
<p><a href="https://github.com/ayumax/Froola">https://github.com/ayumax/Froola</a></p>
<p>Froola is a tool I created for testing Unreal Engine code plugins on multiple platforms simultaneously and generating plugin packages.</p>
<p>Originally, I had developed several UE plugins that supported Windows and Mac platforms, which made package creation a tedious process each time.</p>
<p>This is because in a Windows environment, you can create packages for Windows, Android, and Linux, but not for Mac and iOS.</p>
<p>Therefore, I had to build the plugin in both Windows and Mac environments, and then combine them to create a single plugin package.</p>
<p>It would have been nice if Unreal Editor had such functionality, but I couldn&rsquo;t find it within my research, so I was manually combining them each time.</p>
<p>However, I thought others might also benefit from having these capabilities in a single tool, so I created Froola.</p>
<h2 id="comparison-with-cicd-features-like-github-actions">Comparison with CI/CD features like GitHub Actions</h2>
<p>Normally, when wanting to accomplish such tasks, the first thing that comes to mind is using CI/CD features like GitHub Actions.</p>
<p>However, running Unreal Engine in the cloud is challenging, primarily from a financial perspective.</p>
<p>A single version of Unreal Engine is approximately 50GB, and preparing multiple versions requires even more storage.</p>
<p>Additionally, a fairly powerful CPU is necessary, making it difficult to set up an execution environment.</p>
<p>Although you can rent Mac EC2 instances on AWS, they are quite expensive with a minimum one-day rental. Other Mac cloud services I found were also costly.</p>
<p>Therefore, I believe many people are likely using on-premises servers as self-hosted runners.</p>
<p>However, when dealing with public repositories as an individual, I wanted to avoid self-hosted runners for security reasons, which led me to conclude that building directly on my development PC was the best option.</p>
<h2 id="froolas-structure">Froola&rsquo;s Structure</h2>
<p>Froola generates multi-platform compatible plugin packages, but what it does is straightforward: it builds the plugin in both Windows and Mac environments and then combines them to create a single plugin package.</p>
<p>After consideration, I decided to use Linux UE through Docker instead of using Windows UE for Linux builds. I&rsquo;ll explain the reason for this later.</p>
<p>Therefore, it operates with the following workflow:</p>
<ol>
<li>Clone the plugin project from a remote repository to the Windows environment</li>
<li>Create directories for Windows and Linux builds in the Windows environment and copy the repository files there</li>
<li>Copy the repository files cloned in (1) to Mac via SCP</li>
<li>Launch UE on Windows and UE in Docker on Windows simultaneously to build the plugin</li>
<li>Build the plugin using Mac&rsquo;s UE via SSH</li>
<li>Download the package built on Mac to Windows via SCP</li>
<li>Combine the packages built for Windows, Mac, and Linux to create a single plugin package</li>
</ol>
<pre class="mermaid">
    sequenceDiagram
    participant Windows
    participant Windows(Docker)
    participant Mac

    Windows-&gt;&gt;Windows: Clone from remote repository
    Windows-&gt;&gt;Windows: Create Windows, Linux build directories &amp; copy files
    Windows-&gt;&gt;Mac: Copy repository files via SCP
    Windows-&gt;&gt;Windows: Build plugin with UE
    Windows-&gt;&gt;Windows(Docker): Build plugin with UE in Docker
    Mac-&gt;&gt;Mac: Build plugin with Mac&#39;s UE via SSH
    Mac-&gt;&gt;Windows: Download Mac-built package to Windows via SCP
    Windows-&gt;&gt;Windows: Combine build packages from each OS into a single plugin package
</pre>

<p>As you can see, there&rsquo;s nothing particularly complex about this process.</p>
<p>Simplicity is best.</p>
<p>In fact, I believe there are no other viable methods currently available. At most, you could build for Linux alongside Windows using Windows UE.</p>
<h2 id="automated-testing">Automated Testing</h2>
<p>When creating Froola, I made it possible to run tests on each platform in addition to creating packages.</p>
<p>Unreal Engine&rsquo;s C++ is designed for multiple platforms, so the same code should work on different platforms, but whether it actually performs as expected varies case by case.</p>
<p>One of my plugins, <a href="https://www.fab.com/ja/listings/b6ffd7d7-80da-483f-a7fa-09cb46b72651">ObjectDeliverer</a>, uses network functionality, and since network features differ by OS, code that works fine on Windows might fail on Mac.</p>
<p>Therefore, running tests on each platform is essential to maintain plugin quality.</p>
<p>Froola uses Unreal Editor on Windows, Mac, and Linux to run tests, allowing you to verify test results across all three platforms.</p>
<p>Test results and Editor execution logs are saved on the Windows PC, which helps in identifying the cause when tests fail.</p>
<p>Incidentally, this testing capability is the reason why I don&rsquo;t use Windows UE for Linux builds.</p>
<h2 id="how-to-run-froola">How to Run Froola</h2>
<p>Froola is provided as a Windows executable application.</p>
<p>For operation instructions, please refer to <a href="https://github.com/ayumax/Froola">this link</a>.</p>
<p>You can run it using a command like the following:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>Froola.exe plugin -n ObjectDeliverer -p ObjectDelivererTest -u git@github.com:ayumax/ObjectDeliverer.git -b master -e <span style="color:#f92672">[</span>Windows,Mac,Linux<span style="color:#f92672">]</span>  -v <span style="color:#f92672">[</span>5.5<span style="color:#f92672">]</span> -t -c -g <span style="color:#f92672">[</span>Win64,Mac,Android,IOS,Linux<span style="color:#f92672">]</span>
</span></span></code></pre></div><p>After execution, results are saved in a directory structure like this:</p>
<p>All results are centrally stored in one location, making it easy to troubleshoot when problems occur.</p>
<p>Additionally, the final plugin package is saved in the releases directory. This contains merged files generated for the target platforms, so you can submit this directory to Fab to publish it as a multi-platform compatible plugin.</p>
<pre tabindex="0"><code>20250502_205034_ObjectDeliverer/
├── build
│   ├── Windows_UE5.5
│   │   └── Build.log
│   ├── Mac_UE5.5
│   │   └── Build.log
│   └── Linux_UE5.5
│       └── Build.log
├── tests
│   ├── Windows_UE5.5
│   │   ├── AutomationTest.log
│   │   ├── index.html
│   │   └── index.json
│   ├── Mac_UE5.5
│   │   ├── AutomationTest.log
│   │   ├── index.html
│   │   └── index.json
│   └── Linux_UE5.5
│       ├── AutomationTest.log
│       ├── index.html
│       └── index.json
├── packages
│   ├── Windows_UE5.5
│   │   ├── BuildPlugin.log
│   │   └── Plugin
│   │       ├── ObjectDeliverer.uplugin
│   │       ├── Binaries
│   │       ├── Intermediate
│   │       ├── Resources
│   │       └── Source
│   ├── Mac_UE5.5
│   │   ├── BuildPlugin.log
│   │   └── Plugin
│   │       ├── ObjectDeliverer.uplugin
│   │       ├── Binaries
│   │       ├── Intermediate
│   │       ├── Resources
│   │       └── Source
│   └── Linux_UE5.5
│       ├── BuildPlugin.log
│       └── Plugin
│           ├── ObjectDeliverer.uplugin
│           ├── Binaries
│           ├── Intermediate
│           ├── Resources
│           └── Source
├── releases
│   └── ObjectDeliverer_UE5.5
│       ├── ObjectDeliverer.uplugin
│       ├── Binaries
│       ├── Intermediate
│       ├── Resources
│       └── Source
├── froola.log
└── settings.json
</code></pre><h2 id="froolas-design">Froola&rsquo;s Design</h2>
<p>Froola is built as a C# console application, partly because I like C#.</p>
<p>I hadn&rsquo;t created many full-fledged console applications in C# before, so initially I was concerned about how to handle numerous command-line arguments.</p>
<p>However, I discovered an excellent library called <a href="https://github.com/Cysharp/ConsoleAppFramework">ConsoleAppFramework</a>, which made it easy to handle a large number of command-line arguments.</p>
<p>This library apparently uses source generators and creates command-line argument information from function comments. It&rsquo;s impressive.</p>
<p>By using this library, the implementation doesn&rsquo;t get messy even when the application has multiple commands, so I think I can implement additional commands in the future without much difficulty.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span>    <span style="color:#75715e">/// &lt;summary&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">///     Runs the plugin build, test, and packaging process.</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// &lt;/summary&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// &lt;param name=&#34;pluginName&#34;&gt;-n,Name of the plugin&lt;/param&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// &lt;param name=&#34;projectName&#34;&gt;-p,Name of the project&lt;/param&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// &lt;param name=&#34;gitRepositoryUrl&#34;&gt;-u,URL of the git repository&lt;/param&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// &lt;param name=&#34;gitBranch&#34;&gt;-b,Branch of the git repository&lt;/param&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// &lt;param name=&#34;editorPlatforms&#34;&gt;-e,Editor platforms&lt;/param&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// &lt;param name=&#34;engineVersions&#34;&gt;-v,Engine versions&lt;/param&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// &lt;param name=&#34;resultPath&#34;&gt;-o,Path to save results&lt;/param&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// &lt;param name=&#34;runTest&#34;&gt;-t,Run tests&lt;/param&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// &lt;param name=&#34;runPackage&#34;&gt;-c,Run packaging&lt;/param&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// &lt;param name=&#34;packagePlatforms&#34;&gt;-g,Game platforms&lt;/param&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// &lt;param name=&#34;cancellationToken&#34;&gt;token for cancellation&lt;/param&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">    [Command(&#34;plugin&#34;)]</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">    [SuppressMessage(&#34;ReSharper&#34;, &#34;ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator&#34;)]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">async</span> Task Run(
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">        [Required]</span> <span style="color:#66d9ef">string</span> pluginName,
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">        [Required]</span> <span style="color:#66d9ef">string</span> projectName,
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">        [Required]</span> <span style="color:#66d9ef">string</span> gitRepositoryUrl,
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">        [MinLength(1)]</span> [Required] <span style="color:#66d9ef">string</span> gitBranch,
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">        [EnumArray(typeof(EditorPlatform))]</span> <span style="color:#66d9ef">string</span>[]? editorPlatforms = <span style="color:#66d9ef">null</span>,
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">        [EnumArray(typeof(UEVersion))]</span> <span style="color:#66d9ef">string</span>[]? engineVersions = <span style="color:#66d9ef">null</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">string?</span> resultPath = <span style="color:#66d9ef">null</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">bool?</span> runTest = <span style="color:#66d9ef">null</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">bool?</span> runPackage = <span style="color:#66d9ef">null</span>,
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">        [EnumArray(typeof(GamePlatform))]</span> <span style="color:#66d9ef">string</span>[]? packagePlatforms = <span style="color:#66d9ef">null</span>,
</span></span><span style="display:flex;"><span>        CancellationToken cancellationToken = <span style="color:#66d9ef">default</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    }
</span></span></code></pre></div><h2 id="conclusion">Conclusion</h2>
<p>Froola includes features that I personally wanted, so it may not have all the functions that other developers are looking for.</p>
<p>However, I believe there must be someone in the world facing similar challenges, so I hope this tool will be helpful to those people.</p>
<p>At the moment, Froola has only been tested in my own environment. If you encounter any issues or if Froola does not work well in your environment, please let me know by creating an issue on <a href="https://github.com/ayumax/Froola">GitHub</a>.</p>
<p>I will continue to use Froola myself to make plugin development more efficient!</p>
]]></content:encoded>
    </item>
    <item>
      <title>HUAWEI FreeBuds 3 vs FreeBuds 3i</title>
      <link>https://ayumax.net/entry/2020/09/20/014544/</link>
      <pubDate>Sun, 20 Sep 2020 01:45:44 +0000</pubDate>
      <guid>https://ayumax.net/entry/2020/09/20/014544/</guid>
      <description>&lt;h1 id=&#34;freebuds-3-and-freebuds-3i&#34;&gt;FreeBuds 3 and FreeBuds 3i&lt;/h1&gt;
&lt;p&gt;FreeBuds 3 and FreeBuds 3i are wireless earphones sold by HUAWEI.&lt;/p&gt;
&lt;p&gt;Since FreeBuds 3i came out after FreeBuds 3, it might seem like the 3i is more powerful, but it feels more like a power-down in features other than noise cancellation.&lt;/p&gt;
&lt;p&gt;The price also reflects this; as of writing this article, the 3 costs around 20,000 yen on Amazon, while the 3i is around 13,000 yen.
This also suggests that more effort was put into making the FreeBuds 3.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="freebuds-3-and-freebuds-3i">FreeBuds 3 and FreeBuds 3i</h1>
<p>FreeBuds 3 and FreeBuds 3i are wireless earphones sold by HUAWEI.</p>
<p>Since FreeBuds 3i came out after FreeBuds 3, it might seem like the 3i is more powerful, but it feels more like a power-down in features other than noise cancellation.</p>
<p>The price also reflects this; as of writing this article, the 3 costs around 20,000 yen on Amazon, while the 3i is around 13,000 yen.
This also suggests that more effort was put into making the FreeBuds 3.</p>
<p>I had been using FreeBuds 3 for a long time, but I recently purchased FreeBuds 3i, so I compared them to the FreeBuds 3 I had been using.</p>
<p>Comparisons of various features and specs have been done in many places, so it feels a bit late, thus this comparison is based on my personal impressions.</p>
<figure>
    <img loading="lazy" src="/images/2020/09/20/014544/20200920004611.jpg"/> 
</figure>

<p>For details on the two products, please see the official pages below.</p>
<p><a href="https://consumer.huawei.com/jp/audio/freebuds3/">HUAWEI FreeBuds 3, HUAWEI Kirin A1 Chipset, Intelligent Noise Cancelling | HUAWEI Japan</a></p>
<p><a href="https://consumer.huawei.com/jp/audio/freebuds-3i/">HUAWEI FreeBuds 3i - HUAWEI Japan</a></p>
<h1 id="comfort">Comfort</h1>
<p>First is the difference in wearing comfort when put in the ear.</p>
<p>In this regard, FreeBuds 3 was a complete victory for me.</p>
<p>Please note that this aspect is highly dependent on the individual, so take it as a reference.</p>
<p>First, there is a major difference between these two models: open-fit and in-ear canal type. Therefore, their appearance is also significantly different, as shown below.</p>
<figure>
    <img loading="lazy" src="/images/2020/09/20/014544/20200920005644.jpg"/> 
</figure>

<p>Because of this, the FreeBuds 3 fit gently into the ear, whereas the FreeBuds 3i need to be pushed in firmly.</p>
<p>Putting on the 3 after wearing the 3i feels really light, with less burden on the ear and a gentler feel.</p>
<p>However, this might change depending on the ear shape, so not everyone might have the same impression.</p>
<p>Looking at various reviews, some people say the 3 &ldquo;falls out of the ear easily,&rdquo; but I can use them even when running without them falling out at all, so they seem to fit my ears quite well.</p>
<h1 id="case-portability">Case Portability</h1>
<p>A point that bothers me quite a bit is carrying the case.</p>
<p>In the photo below, the left is FreeBuds 3 and the right is FreeBuds 3i.</p>
<figure>
    <img loading="lazy" src="/images/2020/09/20/014544/20200920010738.jpg"/> 
</figure>

<figure>
    <img loading="lazy" src="/images/2020/09/20/014544/20200920005519.jpg"/> 
</figure>

<p>As you can see, the 3i is thicker.</p>
<p>I usually put it in my left pants pocket, and the thickness of the 3i is quite noticeable then.</p>
<p>My impression is that I wish they had reduced the thickness even if it meant making it a bit wider.</p>
<h1 id="noise-cancelling">Noise Cancelling</h1>
<p>Both of these models have active noise cancelling features.</p>
<p>Comparing the noise cancelling, the in-ear 3i wins hands down.</p>
<p>Comparing the rattling sound on a train, FreeBuds 3 reduces the sound by about 20% subjectively, whereas FreeBuds 3i reduces it by about 60-70%.</p>
<p>Given that the 3 manages to put noise cancelling on an open-fit design is amazing in itself, so this difference is understandable.</p>
<p>For the 3i, the noise cancelling effect changes considerably depending on the angle it&rsquo;s worn in the ear, so it&rsquo;s best to test which angle is quietest initially for better use.</p>
<p>Also, a minor point: the 3 resets to noise cancelling OFF each time you use it, but the 3i remembers the previous ON/OFF state, which is another difference.</p>
<p>However, I&rsquo;ve come to think that it&rsquo;s not necessarily clear which is better.</p>
<p>This is because if some time has passed since the last use, I might not remember if I ended with noise cancelling ON, and I&rsquo;ve already found myself wondering which state the 3i is in (noise cancelling ON or ambient sound passthrough) several times after putting them on.</p>
<p>With the 3, it&rsquo;s always OFF, so you just need to perform the routine of double-tapping the earphone to turn it ON, eliminating any confusion.</p>
<p>Also, the 3 requires adjusting the noise cancelling via an app, but the 3i doesn&rsquo;t need it, or rather, it wasn&rsquo;t in the app menu.</p>
<h1 id="connection-with-smartphone">Connection with Smartphone</h1>
<p>I use a HUAWEI P30 Pro as my smartphone.</p>
<p>Personally, I find Bluetooth devices that frequently disconnect incredibly stressful, so I prefer to stick with the same manufacturer as much as possible, which is why both are HUAWEI now.</p>
<p>However, I felt there was a significant difference in connection stability between these two models.</p>
<p>First, I don&rsquo;t feel any difference in the time it takes to connect to the smartphone after taking them out of the case.
Both connect instantly.</p>
<p>However, while playing music, the sound cutting out abruptly is something I rarely encountered with FreeBuds 3, but with 3i, it happens about once during my daily commute.</p>
<p>This is quite noticeable and a minus point for the 3i.</p>
<p>Perhaps this is influenced by the fact that only the 3 uses the Kirin A1 chipset for Bluetooth?</p>
<h1 id="sound-quality">Sound Quality</h1>
<p>I&rsquo;m not an expert on this, so I lack the knowledge and experience to comment in detail, and don&rsquo;t have much to say.</p>
<p>Personally, I don&rsquo;t think either is bad.</p>
<h1 id="charging">Charging</h1>
<p>FreeBuds 3 supports wireless charging, but 3i does not.</p>
<p>This isn&rsquo;t a problem as I carry a type-c charger anyway, but wireless charging is convenient, so it would have been nice if the 3i had it too.</p>
<p>(I once tried charging the FreeBuds 3 using the P30 Pro&rsquo;s wireless reverse charging feature, and it was convenient!)</p>
<h1 id="final-verdict">Final Verdict</h1>
<p>For me, the FreeBuds 3 I bought first will likely be the one I use daily from now on.</p>
<p>Overall, they are more user-friendly, and I really like how gently they fit my ears.</p>
<p>So what about the 3i? My current workplace has quite a bit of noise from air conditioning and various machines, which significantly drains concentration. So, I&rsquo;m thinking of using the 3i specifically when I want to concentrate at work, letting the noise cancelling help me.</p>
<p>Therefore, I want to utilize both effectively according to the situation.</p>
<h1 id="bonus">Bonus</h1>
<p>The day after I bought the FreeBuds 3i, a model called &ldquo;FreeBuds Pro&rdquo; was announced&hellip;</p>
<p>This one has even more powerful noise cancelling than the 3i, and its appearance is cooler than the previous two models.</p>
<p>However, the price is also Pro level (around 25,000 yen on Aliexpress), so I&rsquo;m debating whether to buy it&hellip;</p>
]]></content:encoded>
    </item>
    <item>
      <title>Updating a WinUI 3 Preview 1 Project to Preview 2</title>
      <link>https://ayumax.net/entry/2020/08/07/192535/</link>
      <pubDate>Fri, 07 Aug 2020 19:25:35 +0000</pubDate>
      <guid>https://ayumax.net/entry/2020/08/07/192535/</guid>
      <description>&lt;h1 id=&#34;winui-3-preview-2&#34;&gt;WinUI 3 Preview 2&lt;/h1&gt;
&lt;p&gt;I didn&amp;rsquo;t notice for about half a month, but WinUI 3 Preview 2 was released.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.microsoft.com/en-us/windows/apps/winui/winui3/&#34;&gt;WinUI 3 Preview 2 (July 2020)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So, I tried updating the following WinUI 3 Desktop project, which I previously created using WinUI 3 Preview 1, to Preview 2.&lt;/p&gt;
&lt;p&gt;This is a record of that process.&lt;/p&gt;
&lt;p&gt;Since I basically just followed the official instructions, there isn&amp;rsquo;t much useful information here.&lt;/p&gt;
&lt;div class=&#34;github-card&#34; data-user=&#34;ayumax&#34; data-repo=&#34;WinUIExplorer&#34; data-width=&#34;400&#34; data-height=&#34;&#34; data-theme=&#34;default&#34;&gt;&lt;/div&gt;
&lt;script src=&#34;https://cdn.jsdelivr.net/github-cards/latest/widget.js&#34;&gt;&lt;/script&gt;
&lt;h1 id=&#34;updating-the-environment&#34;&gt;Updating the Environment&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ll check the environment according to the description on the official page.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="winui-3-preview-2">WinUI 3 Preview 2</h1>
<p>I didn&rsquo;t notice for about half a month, but WinUI 3 Preview 2 was released.</p>
<p><a href="https://docs.microsoft.com/en-us/windows/apps/winui/winui3/">WinUI 3 Preview 2 (July 2020)</a></p>
<p>So, I tried updating the following WinUI 3 Desktop project, which I previously created using WinUI 3 Preview 1, to Preview 2.</p>
<p>This is a record of that process.</p>
<p>Since I basically just followed the official instructions, there isn&rsquo;t much useful information here.</p>
<div class="github-card" data-user="ayumax" data-repo="WinUIExplorer" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<h1 id="updating-the-environment">Updating the Environment</h1>
<p>I&rsquo;ll check the environment according to the description on the official page.</p>
<h3 id="ensure-windows-10-version-1803-build-17134-or-later-is-installed-on-your-development-computer">Ensure Windows 10 version 1803 (build 17134) or later is installed on your development computer</h3>
<p>I have Windows 10 2004, so it&rsquo;s OK.</p>
<h3 id="install-visual-studio-2019-version-167-preview-3">Install Visual Studio 2019 version 16.7 Preview 3</h3>
<p>Checking the version of the installed VS2019 Preview, it was 16.7.0 Preview 3.1.</p>
<p>So, I decided to proceed with this version.</p>
<figure>
    <img loading="lazy" src="/images/2020/08/07/192535/20200807183353.png"/> 
</figure>

<p>When I checked for updates, 16.8.0 Preview 1.0 was available, but since updating the .NET 5 version to the latest previously caused WinUI 3 Preview 1 to fail to launch, I decided against recklessly updating to the latest version.</p>
<figure>
    <img loading="lazy" src="/images/2020/08/07/192535/20200807183508.png"/> 
</figure>

<h3 id="net-5-preview-5">.NET 5 Preview 5</h3>
<p>It seems WinUI 3 Preview 2 supports .NET 5 Preview 5.
Checking the current latest version, Preview 7 was available, but to ensure it works reliably, I&rsquo;ll stick with Preview 5.</p>
<p>However, this time, the official page description didn&rsquo;t include the note &ldquo;Don&rsquo;t install anything newer than Preview 5&rdquo; (it did last time), so perhaps Preview 7 might work as well.</p>
<h3 id="install-the-winui-3-preview-2-vsix-package">Install the WinUI 3 Preview 2 VSIX package</h3>
<p>Install the extension for VS.
However, when I downloaded and tried to install it, it indicated that it was already installed, so I think it hasn&rsquo;t changed from Preview 1.</p>
<h1 id="updating-the-project">Updating the Project</h1>
<p>It seems that projects created with WinUI Preview 1 won&rsquo;t work as-is with Preview 2, and some edits are necessary.</p>
<p>Details are written on the following page.</p>
<div class="github-card" data-user="microsoft/microsoft-ui-xaml/blob/master/docs" data-repo="preview_upgrade_instructions.md" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<p>Now, let&rsquo;s edit according to the page above.</p>
<h3 id="install-microsoftwinui-preview-2-via-nuget">Install Microsoft.WinUI Preview 2 via NuGet</h3>
<p>It didn&rsquo;t show up when searching in the NuGet Package Manager.</p>
<p>However, the workaround was also described: install it from the Package Manager Console by entering <code>install-package Microsoft.WinUI -Version 3.0.0-preview2.200713.0</code>.</p>
<h3 id="edit-csproj">Edit .csproj</h3>
<p>Change the TargetFramework description from <code>netcoreapp5.0</code> to <code>net5.0</code>.</p>
<p>That&rsquo;s all for this file.</p>
<h3 id="edit-wapproj">Edit .wapproj</h3>
<p>Edit the package project&rsquo;s configuration file (.wapproj) in a few places.</p>
<h4 id="change-1">Change 1</h4>
<p>Insert the line <code>&lt;AppxTargetsLocation Condition=&quot;'$(AppxTargetsLocation)'==''&quot;&gt;$(MSBuildThisFileDirectory)build\&lt;/AppxTargetsLocation&gt;</code> inside the <code>PropertyGroup</code> after <code>&lt;Import Project=&quot;$(WapProjPath)\Microsoft.DesktopBridge.props&quot; /&gt;</code>.</p>
<h4 id="change-2">Change 2</h4>
<p>Change <code>&lt;Import Project=&quot;build\Microsoft.WinUI.AppX.targets&quot; /&gt;</code> to <code>&lt;Import Project=&quot;$(AppxTargetsLocation)Microsoft.WinUI.AppX.targets&quot; /&gt;</code>.</p>
<h3 id="replace-files-in-the-package-projects-build-folder">Replace files in the package project&rsquo;s build folder</h3>
<p>First, create a new project.
This is disposable, so creating it in a temporary folder is fine.</p>
<p>Use the <code>Blank App, Packaged (WinUI in Desktop)</code> template.</p>
<p>Once the project is created, copy the following two files from <code>[Package project folder]/build/</code>:</p>
<ul>
<li>LiftedWinRTClassRegistrations.xml</li>
<li>Microsoft.WinUI.AppX.targets</li>
</ul>
<p>Then, overwrite the files in the same hierarchy in your own package project.</p>
<h1 id="build-and-run">Build and Run</h1>
<p>After restarting VS, building, and running, it launched properly.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">儀式完了。WinUI Preview1のプロジェクトをPreview2にアップデートできた。 <a href="https://t.co/b509OoP6K8">pic.twitter.com/b509OoP6K8</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1291015445181390850?ref_src=twsrc%5Etfw">August 5, 2020</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>It seems many bugs have been fixed in WinUI 3 Preview 2 compared to Preview 1, so I&rsquo;d like to explore various aspects.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Handling Unfocused State in UE4 Windows Packages (Sound Playback, GamePad Input)</title>
      <link>https://ayumax.net/entry/2020/05/31/004502/</link>
      <pubDate>Sun, 31 May 2020 00:45:02 +0000</pubDate>
      <guid>https://ayumax.net/entry/2020/05/31/004502/</guid>
      <description>&lt;h1 id=&#34;behavior-when-unfocused&#34;&gt;Behavior When Unfocused&lt;/h1&gt;
&lt;p&gt;I use UE4 for non-game purposes at work, often alongside other applications on Windows.&lt;/p&gt;
&lt;p&gt;A common pattern is creating the display part with UE4 and a controller-like part with WPF, then using them together.&lt;/p&gt;
&lt;p&gt;In this pattern, the focus inevitably goes to the WPF application, leaving the UE4 window unfocused.&lt;/p&gt;
&lt;p&gt;This caused the following problems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sound cannot be heard&lt;/li&gt;
&lt;li&gt;GamePad input cannot be captured&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I couldn&amp;rsquo;t find solutions for these for a while, but after checking the Engine source, I found countermeasures for both, so I&amp;rsquo;m writing them down as a memo.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="behavior-when-unfocused">Behavior When Unfocused</h1>
<p>I use UE4 for non-game purposes at work, often alongside other applications on Windows.</p>
<p>A common pattern is creating the display part with UE4 and a controller-like part with WPF, then using them together.</p>
<p>In this pattern, the focus inevitably goes to the WPF application, leaving the UE4 window unfocused.</p>
<p>This caused the following problems:</p>
<ul>
<li>Sound cannot be heard</li>
<li>GamePad input cannot be captured</li>
</ul>
<p>I couldn&rsquo;t find solutions for these for a while, but after checking the Engine source, I found countermeasures for both, so I&rsquo;m writing them down as a memo.</p>
<p>Note that the environment where I applied these measures was 4.24, but since the implementation in that part seems unchanged in 4.25, I believe the same measures should work (though I haven&rsquo;t confirmed the operation in 4.25).</p>
<h1 id="sound-playback-when-unfocused">Sound Playback When Unfocused</h1>
<p>I found the following description in <code>WindowsPlatformApplicationMisc::PumpMessages</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">// if its our window, allow sound, otherwise apply multiplier
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>FApp<span style="color:#f92672">::</span>SetVolumeMultiplier( HasFocus <span style="color:#f92672">?</span> <span style="color:#ae81ff">1.0f</span> <span style="color:#f92672">:</span> FApp<span style="color:#f92672">::</span>GetUnfocusedVolumeMultiplier() );
</span></span></code></pre></div><p>It seems <code>SetVolumeMultiplier</code> is a function to set the sound volume. Here, it uses 1.0 if focused, and the value of <code>GetUnfocusedVolumeMultiplier</code> otherwise.</p>
<p>Checking the value returned by <code>GetUnfocusedVolumeMultiplier</code>, it was 0.
That&rsquo;s why I couldn&rsquo;t hear anything.</p>
<p>However, I found that the initial value of this is taken from the Config.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">bool</span> GUnfocusedVolumeMultiplierInitialised <span style="color:#f92672">=</span> false;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">float</span> FApp<span style="color:#f92672">::</span>GetUnfocusedVolumeMultiplier()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>GUnfocusedVolumeMultiplierInitialised)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        GUnfocusedVolumeMultiplierInitialised <span style="color:#f92672">=</span> true;
</span></span><span style="display:flex;"><span>        GConfig<span style="color:#f92672">-&gt;</span>GetFloat(TEXT(<span style="color:#e6db74">&#34;Audio&#34;</span>), TEXT(<span style="color:#e6db74">&#34;UnfocusedVolumeMultiplier&#34;</span>), UnfocusedVolumeMultiplier, GEngineIni);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> UnfocusedVolumeMultiplier;
</span></span></code></pre></div><p>So, I wrote the following setting in <code>Config/DefaultEngine.ini</code> to make the value of <code>UnfocusedVolumeMultiplier</code> also 1.0 and confirmed the operation.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ini" data-lang="ini"><span style="display:flex;"><span><span style="color:#66d9ef">[Audio]</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">UnfocusedVolumeMultiplier</span><span style="color:#f92672">=</span><span style="color:#e6db74">1.0</span>
</span></span></code></pre></div><p>Success! Sound can now be heard even when unfocused.</p>
<h1 id="gamepad-input-when-unfocused">GamePad Input When Unfocused</h1>
<p>In UE4, GamePad input on Windows uses an API called XInput.</p>
<p>Searching from there, I found a class called <code>XInputInterface</code>.
Checking its contents, it calls the XInput API, so it&rsquo;s highly likely that this is where GamePad input is received.</p>
<p>Next, searching for where <code>XInputInterface</code> is used, I found it&rsquo;s used in <code>FWindowsApplication</code>.</p>
<p>Then, it seems <code>FWindowsApplication::PollGameDeviceState</code> fires the XInput input events.
Furthermore, this function is called from <code>FSlateApplication::PollGameDeviceState()</code>.</p>
<p>Looking inside <code>FSlateApplication::PollGameDeviceState()</code>, it&rsquo;s guarded by an if statement.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">if</span>( ActiveModalWindows.Num() <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">!</span>GIntraFrameDebuggingGameThread <span style="color:#f92672">&amp;&amp;</span> (<span style="color:#f92672">!</span>bRequireFocusForGamepadInput <span style="color:#f92672">||</span> IsActive()))
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Don&#39;t poll when a modal window open or intra frame debugging is happening
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    PlatformApplication<span style="color:#f92672">-&gt;</span>PollGameDeviceState( GetDeltaTime() );
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>There are three conditions here, and the last one, <code>IsActive()</code>, feels like it means having focus.
However, there&rsquo;s a variable here, <code>bRequireFocusForGamepadInput</code>, which seems directly related.</p>
<p>Checking its definition, it looked like the value could be changed via a console command.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">bool</span> bRequireFocusForGamepadInput <span style="color:#f92672">=</span> false;
</span></span><span style="display:flex;"><span>FAutoConsoleVariableRef <span style="color:#a6e22e">CVarRequireFocusForGamepadInput</span>(
</span></span><span style="display:flex;"><span>    TEXT(<span style="color:#e6db74">&#34;Slate.RequireFocusForGamepadInput&#34;</span>),
</span></span><span style="display:flex;"><span>    bRequireFocusForGamepadInput,
</span></span><span style="display:flex;"><span>    TEXT(<span style="color:#e6db74">&#34;&#34;</span>)
</span></span><span style="display:flex;"><span>);
</span></span></code></pre></div><p>For my work purposes, I use a development build, so I tried entering the above command using Ctrl+@, and I was able to get GamePad input even when unfocused.</p>
<p>However, typing it every time is tedious (calling it from BluePrint is an option, but I&rsquo;d rather not if possible).</p>
<p>Doing a bit more research, it seems console commands can also be defined in an ini file, so I decided to go with that approach.</p>
<p><a href="https://qiita.com/EGJ-Takashi_Suzuki/items/07ef02bf6eb08cdc1664">[UE4] Special Nature of ConsoleVariables.ini - Qiita</a></p>
<h1 id="summary">Summary</h1>
<p>When a UE4 application loses focus, various things become impossible, but I managed to adjust it to behave as desired.</p>
<p>Being able to see the engine source makes this kind of investigation easier, which is really great!</p>
]]></content:encoded>
    </item>
    <item>
      <title>Change from UProperty to FProperty (UE4 4.25)</title>
      <link>https://ayumax.net/entry/2020/03/22/144226/</link>
      <pubDate>Sun, 22 Mar 2020 14:42:26 +0000</pubDate>
      <guid>https://ayumax.net/entry/2020/03/22/144226/</guid>
      <description>&lt;h1 id=&#34;unreal-engine-425-preview&#34;&gt;Unreal Engine 4.25 Preview&lt;/h1&gt;
&lt;p&gt;The other day, the Preview of UE4 4.25 became available for download.&lt;/p&gt;
&lt;p&gt;(As of writing this article, it is Preview 3)&lt;/p&gt;
&lt;p&gt;The contents are described on the following page.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://forums.unrealengine.com/unreal-engine/announcements-and-releases/1728453-unreal-engine-4-25-preview&#34;&gt;Unreal Engine 4.25 Preview - Unreal Engine Forums&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Among the many updates, the following item caught my eye.
(The FProperty Refactor&amp;hellip; part)&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://ayumax.net/images/2020/03/22/144226/20200322125250.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;The content is &amp;ldquo;From 4.25, UProperty has become FProperty and is no longer a UObject.&amp;rdquo;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="unreal-engine-425-preview">Unreal Engine 4.25 Preview</h1>
<p>The other day, the Preview of UE4 4.25 became available for download.</p>
<p>(As of writing this article, it is Preview 3)</p>
<p>The contents are described on the following page.</p>
<p><a href="https://forums.unrealengine.com/unreal-engine/announcements-and-releases/1728453-unreal-engine-4-25-preview">Unreal Engine 4.25 Preview - Unreal Engine Forums</a></p>
<p>Among the many updates, the following item caught my eye.
(The FProperty Refactor&hellip; part)</p>
<figure>
    <img loading="lazy" src="/images/2020/03/22/144226/20200322125250.png"/> 
</figure>

<p>The content is &ldquo;From 4.25, UProperty has become FProperty and is no longer a UObject.&rdquo;</p>
<p>Until now, UProperty inherited from UObject.
In UE4, classes inheriting from UObject have a naming convention starting with U. Hence the class name UProperty.</p>
<ul>
<li>Reference
[Coding Standard](https://docs.unrealengine.com/en-US/Programming/Development/CodingStandard/index.html)</li>
</ul>
<p>Since it no longer inherits from UObject (it now inherits from a class called FField), the class name changed to FProperty.</p>
<h2 id="what-is-uproperty">What is UProperty?</h2>
<p>First of all, what is the UProperty (FProperty) that was changed this time? It is information about member variables or function arguments of a C++ class created by the UE4 property system.</p>
<p>Details are explained thoroughly on the official page below.</p>
<ul>
<li>Reference
[Unreal Property System (Reflection)](https://www.unrealengine.com/en-US/blog/unreal-property-system-reflection)</li>
</ul>
<p>Furthermore, UProperty is derived into UStringProperty, UBoolProperty, etc., depending on the property type.</p>
<p>It is used for various purposes within the UE4 engine, but from the perspective of us UE4 users, it is used when we want to do things like the following:</p>
<ul>
<li>Access properties of an object defined in Blueprint from the C++ side</li>
<li>Create a custom serializer for an object</li>
<li>Manipulate object properties by specifying the property name</li>
</ul>
<p>Using the UE4 property system with UProperty like this allows for building mechanisms to manipulate objects more flexibly.</p>
<h4 id="reference-example-of-getting-the-values-of-all-properties-of-an-object">(Reference) Example of getting the values of all properties of an object</h4>
<p>The following code gets the values of all properties of Obj.</p>
<p>(* This example assumes that the type of all properties is uint8)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (TFieldIterator<span style="color:#f92672">&lt;</span>UProperty<span style="color:#f92672">&gt;</span> PropIt(Obj<span style="color:#f92672">-&gt;</span>GetClass()); PropIt; <span style="color:#f92672">++</span>PropIt)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    UProperty<span style="color:#f92672">*</span> Property <span style="color:#f92672">=</span> <span style="color:#f92672">*</span>PropIt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Get property name
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    FString PropertyName <span style="color:#f92672">=</span> Property<span style="color:#f92672">-&gt;</span>GetName();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Get property value
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    uint8 CurrentPropAddr <span style="color:#f92672">=</span> <span style="color:#f92672">*</span>(PropIt<span style="color:#f92672">-&gt;</span>ContainerPtrToValuePtr<span style="color:#f92672">&lt;</span>uint8<span style="color:#f92672">&gt;</span>(Obj));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="why-was-it-changed-to-fproperty">Why was it changed to FProperty?</h2>
<p>I haven&rsquo;t followed all the information, so this includes a lot of personal speculation, but I think a major reason was to remove it from the management scope of GC (Garbage Collection) by making it not a UObject.</p>
<p>When an instance is allocated in memory as a UObject, the GC checks whether the instance should be destroyed at the appropriate timing.
Instances determined to be destroyable by the check result will be destroyed.</p>
<p>If the number of UObject instances in the entire project is large, the search time for the GC to check for destroyable targets increases.
(Because the absolute number of items to check increases)</p>
<p>Increased search time can lead to severe adverse effects, such as the frame rate dropping sharply at the GC check timing (experienced this).</p>
<p>Therefore, although it depends on the case, having fewer UObject instances is generally considered better for performance.</p>
<h2 id="building-conventional-up-to-424-c-code-with-425">Building conventional (up to 4.24) C++ code with 4.25</h2>
<p>I tried building the code that enumerates object properties written earlier with 4.25.</p>
<p>It didn&rsquo;t result in an error, but the following Warning appeared.</p>
<pre tabindex="0"><code>warning C4996: UProperty has been renamed to FProperty Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile.
</code></pre><p>The Warning says, &ldquo;UProperty has changed to FProperty, so change it quickly.&rdquo; However, being a Warning means it will still work for now.</p>
<p>The reason for this can be understood by looking at the definition of UProperty in 4.25.</p>
<p>It was defined as follows in the header <code>DefineUPropertyMacros.h</code>.</p>
<figure>
    <img loading="lazy" src="/images/2020/03/22/144226/20200322135332.png"/> 
</figure>

<p>All U<del>Property are set to be replaced with F</del>Property.</p>
<p>Since DEPRECATED_MACRO is also embedded during this replacement, the previous Warning seems to appear.</p>
<p>So, does this mean that code using UProperty can be left as is for the time being? It seems not.</p>
<p>It&rsquo;s just being replaced; the UProperty written in the C++ code is already not a UObject, so code like the following will result in an error.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>UProperty<span style="color:#f92672">*</span> Property <span style="color:#f92672">=</span> <span style="color:#f92672">*</span>PropIt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (UBoolProperty<span style="color:#f92672">*</span> BoolProperty <span style="color:#f92672">=</span> Cast<span style="color:#f92672">&lt;</span>UBoolProperty<span style="color:#f92672">&gt;</span>(Property))
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">bool</span> bValue <span style="color:#f92672">=</span> BoolProperty<span style="color:#f92672">-&gt;</span>GetPropertyValue(Obj);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The code above means &ldquo;if the type of a certain property is bool, get the value as bool.&rdquo;</p>
<p>In this, <code>Cast&lt;UBoolProperty&gt;(Property)</code> is used to check if UProperty can be cast to UBoolProperty, but Cast can only be used for UObjects.</p>
<p>Therefore, building this code results in an error.</p>
<p>(* In the example above, the same can be achieved with FProperty by replacing it with the CastField function)</p>
<p>For the same reason, <code>IsValid</code> and similar functions are likely to become unusable.</p>
<p>Additionally, if there are parts where UProperty is passed as a UObject argument to functions, they need to be changed appropriately.</p>
<h1 id="summary">Summary</h1>
<ul>
<li>From 4.25, UProperty became FProperty</li>
<li>Replace箇所 where U~Property is used in C++ with F~Property</li>
<li>Check not only for replacement but also if UProperty is used as UObject anywhere</li>
</ul>
<h3 id="bonus">Bonus</h3>
<p>Since the old UProperty definition remains in UnrealTypePrivate.h, it feels like UProperty could be extended for a while longer by including this header, but it seems better not to use it as it would deviate from the proper flow.</p>
]]></content:encoded>
    </item>
    <item>
      <title>ObjectDeliverer Ver 1.5.0 Released - Enhanced Object Json Serialization Feature</title>
      <link>https://ayumax.net/entry/2020/01/24/233816/</link>
      <pubDate>Fri, 24 Jan 2020 23:38:16 +0000</pubDate>
      <guid>https://ayumax.net/entry/2020/01/24/233816/</guid>
      <description>&lt;p&gt;Today, ObjectDeliverer Ver 1.5.0 was released to the Marketplace.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.unrealengine.com/marketplace/en-US/product/objectdeliverer&#34;&gt;ObjectDeliverer: ayumax: Code Plugins - UE4 Marketplace&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The main implementation this time is the enhancement of the Object Json serialization feature.&lt;/p&gt;
&lt;p&gt;I previously wrote about this as a current issue in a past article.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.ayumax.net/entry/2019/12/20/000000&#34;&gt;Let&amp;rsquo;s Serialize UObjects to Json - AYU MAX&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This release implements features to improve the issues mentioned above.&lt;/p&gt;
&lt;h1 id=&#34;implemented-items&#34;&gt;Implemented Items&lt;/h1&gt;
&lt;p&gt;The following two items have been addressed.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Today, ObjectDeliverer Ver 1.5.0 was released to the Marketplace.</p>
<p><a href="https://www.unrealengine.com/marketplace/en-US/product/objectdeliverer">ObjectDeliverer: ayumax: Code Plugins - UE4 Marketplace</a></p>
<p>The main implementation this time is the enhancement of the Object Json serialization feature.</p>
<p>I previously wrote about this as a current issue in a past article.</p>
<p><a href="https://www.ayumax.net/entry/2019/12/20/000000">Let&rsquo;s Serialize UObjects to Json - AYU MAX</a></p>
<p>This release implements features to improve the issues mentioned above.</p>
<h1 id="implemented-items">Implemented Items</h1>
<p>The following two items have been addressed.</p>
<h2 id="property-name-conversion">Property Name Conversion</h2>
<p><a href="https://github.com/ayumax/ObjectDeliverer/wiki/How-to-change-property-name-when-serializing-UObject-with-Json(Version-1.5.0-or-later)">How to change property name when serializing UObject with Json(Version 1.5.0 or later) · ayumax/ObjectDeliverer Wiki · GitHub</a></p>
<p>By implementing the <code>IODConvertPropertyName</code> interface in the class to be serialized, property name conversion is now possible.</p>
<p>Usage Example)</p>
<p><a href="https://user-images.githubusercontent.com/8191970/72532017-fc383700-38b5-11ea-9dc0-b73581393e35.png" class="http-image"><img src="https://user-images.githubusercontent.com/8191970/72532017-fc383700-38b5-11ea-9dc0-b73581393e35.png" class="http-image" alt="https://user-images.githubusercontent.com/8191970/72532017-fc383700-38b5-11ea-9dc0-b73581393e35.png"/></a></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span><span style="color:#75715e">// Before conversion
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;Prop2&#34;</span>: <span style="color:#ae81ff">1</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;ObjProp&#34;</span>:
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;ValueB&#34;</span>: <span style="color:#ae81ff">0</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;ValueA&#34;</span>: <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;ObjProp2&#34;</span>:
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;ValueC&#34;</span>: <span style="color:#e6db74">&#34;abc&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// After conversion
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;IntProperty&#34;</span>: <span style="color:#ae81ff">1</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;ObjectPropertyA&#34;</span>:
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;ValueB&#34;</span>: <span style="color:#ae81ff">0</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;ValueA&#34;</span>: <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;ObjectPropertyB&#34;</span>:
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;ValueC&#34;</span>: <span style="color:#e6db74">&#34;abc&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Using this feature allows the following:</p>
<ul>
<li>Resolution of the case-insensitivity issue with FName</li>
<li>Using different property names between the target class and Json</li>
</ul>
<p>It&rsquo;s subtle but should be genuinely useful.</p>
<h2 id="selection-of-serialization-format">Selection of Serialization Format</h2>
<p><a href="https://github.com/ayumax/ObjectDeliverer/wiki/Selection-of-Json-serialize-method-in-ObjectDeliveryBoxUsingJson(Version-1.5.0-later)">Selection of Json serialize method in ObjectDeliveryBoxUsingJson(Version 1.5.0 later) · ayumax/ObjectDeliverer Wiki · GitHub</a></p>
<p>This is the item I put the most effort into implementing this time.
It is now possible to embed the class name within the Json.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span><span style="color:#75715e">// Conventional method without class name
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;Prop&#34;</span>: <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Method embedding class name
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;Type&#34;</span>: <span style="color:#e6db74">&#34;SampleClassName&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;Body&#34;</span>:
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;Prop&#34;</span>: <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This enables the following:</p>
<ul>
<li>Support for serialization and deserialization of multiple classes with a single DeliveryBox</li>
<li>Restoration is possible even when an instance of a derived class is in an Object type property</li>
</ul>
<p>Also, while the method of embedding class names alone has the advantages mentioned above, it also has the disadvantage of increasing the character count (data size). Therefore, an option is provided to switch between the conventional method and the new method depending on the Object type.</p>
<p>For example, it is possible to use it in a way where only certain properties embed the class name, as shown below.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;Prop2&#34;</span>: <span style="color:#ae81ff">1</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;ObjProp&#34;</span>:
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;Type&#34;</span>: <span style="color:#e6db74">&#34;CustomObjB_C&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;Body&#34;</span>:
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;ValueB&#34;</span>: <span style="color:#ae81ff">2</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;ValueA&#34;</span>: <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;ObjProp2&#34;</span>:
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;ValueC&#34;</span>: <span style="color:#e6db74">&#34;abc&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h1 id="summary">Summary</h1>
<p>This time, I focused on enhancing the Object Json serialization feature.</p>
<p>There are still other features I want to implement, so please look forward to the steadily improving ObjectDeliverer.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Looking Back on 2019</title>
      <link>https://ayumax.net/entry/2019/12/31/005025/</link>
      <pubDate>Tue, 31 Dec 2019 00:50:25 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/12/31/005025/</guid>
      <description>&lt;p&gt;This year went by fast. It felt like the year ended in the blink of an eye, but just like last year, I want to try looking back on the year.&lt;/p&gt;
&lt;p&gt;Last year&amp;rsquo;s reflection is here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.ayumax.net/entry/2019/01/02/111426&#34;&gt;Looking Back on the Year and Resolutions for the New Year - AYU MAX&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&#34;what-did-i-do&#34;&gt;What Did I Do?&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Month&lt;/th&gt;
&lt;th&gt;What I Did&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;January&lt;/td&gt;
&lt;td&gt;Created ObjectDeliverer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;February&lt;/td&gt;
&lt;td&gt;Listed ObjectDeliverer on the Marketplace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;March&lt;/td&gt;
&lt;td&gt;Created VR content and presented it to the company&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;April&lt;/td&gt;
&lt;td&gt;Got VR work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May&lt;/td&gt;
&lt;td&gt;Tried Pimax 8K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Tried .NET Core&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;June&lt;/td&gt;
&lt;td&gt;Listed EasyXMLParser on the Marketplace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Listed EasyJsonParser on the Marketplace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;July&lt;/td&gt;
&lt;td&gt;Listed WindowCapture2D on the Marketplace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;August&lt;/td&gt;
&lt;td&gt;Created AR content with UE4 + ARKit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;September&lt;/td&gt;
&lt;td&gt;Experimented with IL2C + UE4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Got AR work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;October&lt;/td&gt;
&lt;td&gt;Gave a Lightning Talk at .NET Conf 2019 meetup in AICHI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;November&lt;/td&gt;
&lt;td&gt;Exhausted and an empty shell&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;December&lt;/td&gt;
&lt;td&gt;Posted one article each for C# and UE4 Advent Calendars&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;vr-development&#34;&gt;VR Development&lt;/h1&gt;
&lt;p&gt;A major event this year was starting VR development at work.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>This year went by fast. It felt like the year ended in the blink of an eye, but just like last year, I want to try looking back on the year.</p>
<p>Last year&rsquo;s reflection is here:</p>
<p><a href="https://www.ayumax.net/entry/2019/01/02/111426">Looking Back on the Year and Resolutions for the New Year - AYU MAX</a></p>
<h1 id="what-did-i-do">What Did I Do?</h1>
<table>
<thead>
<tr>
<th>Month</th>
<th>What I Did</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>Created ObjectDeliverer</td>
</tr>
<tr>
<td>February</td>
<td>Listed ObjectDeliverer on the Marketplace</td>
</tr>
<tr>
<td>March</td>
<td>Created VR content and presented it to the company</td>
</tr>
<tr>
<td>April</td>
<td>Got VR work</td>
</tr>
<tr>
<td>May</td>
<td>Tried Pimax 8K</td>
</tr>
<tr>
<td></td>
<td>Tried .NET Core</td>
</tr>
<tr>
<td>June</td>
<td>Listed EasyXMLParser on the Marketplace</td>
</tr>
<tr>
<td></td>
<td>Listed EasyJsonParser on the Marketplace</td>
</tr>
<tr>
<td>July</td>
<td>Listed WindowCapture2D on the Marketplace</td>
</tr>
<tr>
<td>August</td>
<td>Created AR content with UE4 + ARKit</td>
</tr>
<tr>
<td>September</td>
<td>Experimented with IL2C + UE4</td>
</tr>
<tr>
<td></td>
<td>Got AR work</td>
</tr>
<tr>
<td>October</td>
<td>Gave a Lightning Talk at .NET Conf 2019 meetup in AICHI</td>
</tr>
<tr>
<td>November</td>
<td>Exhausted and an empty shell</td>
</tr>
<tr>
<td>December</td>
<td>Posted one article each for C# and UE4 Advent Calendars</td>
</tr>
</tbody>
</table>
<h1 id="vr-development">VR Development</h1>
<p>A major event this year was starting VR development at work.</p>
<p>VR isn&rsquo;t that rare in the world anymore, but it was the first attempt at our company, so I heard various things (expectations, anxieties) from those around me, but I was able to achieve certain results.</p>
<p>How far this can be expanded in the future is still a challenge, so I will continue to work hard next year.</p>
<h1 id="ar-development">AR Development</h1>
<p>This year, I also started AR development with UE4 and ARKit. This is still at the stage of tracing the basics of developing with ARKit in UE4, but I&rsquo;m satisfied because I was able to do everything I wanted to do.</p>
<p>I&rsquo;d like to think about how to incorporate it into work from next year onwards.</p>
<p>I also want to try not just mobile devices but also HoloLens and Magic Leap.</p>
<p>Also, I want to do something in personal development.</p>
<h1 id="ue4-marketplace">UE4 Marketplace</h1>
<p>As for private activities, listing on the Marketplace was a big event.</p>
<p>At the beginning of the year, I wondered if I could list things myself, started researching, and somehow ended up releasing four code plugins.</p>
<p>I put my soul into making all of them, so I&rsquo;d be happy if many people could use them.</p>
<p>Also, some projects are open source, so interacting with others on GitHub was fun.
Since it&rsquo;s in English, conversations wouldn&rsquo;t work without the help of Google Translate, but thanks to that, I feel like my ability to generate Japanese that&rsquo;s easy to translate has improved!</p>
<p>The ratings on the Marketplace are also very encouraging, so I&rsquo;m grateful.</p>
<p>A point of reflection is that I got carried away and released four plugins, and maintenance hasn&rsquo;t kept up.</p>
<p>There are ideas I want to implement for each plugin but haven&rsquo;t been able to, so I want to work on those next year.</p>
<h1 id="presentations">Presentations</h1>
<p>This year, my initial goal was to give presentations somewhere twice, but in the end, it was only once.</p>
<p>But I&rsquo;m grateful just for getting such an opportunity, and I think I grew a little, so I&rsquo;d like to continue doing it if I have the chance in the future.</p>
<p>For that, I need to keep gathering material regularly.</p>
<h1 id="summary">Summary</h1>
<p>For me, it was a very rich year compared to previous years.</p>
<p>I want to do even more various things next year than this year, so I&rsquo;ll do my best!</p>
]]></content:encoded>
    </item>
    <item>
      <title>Creating a Remote Touch Display with UE4&#43;ARKit</title>
      <link>https://ayumax.net/entry/2019/12/28/142724/</link>
      <pubDate>Sat, 28 Dec 2019 14:27:24 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/12/28/142724/</guid>
      <description>&lt;p&gt;The other day, wanting to give shape to an idea I had, I created something like this ↓.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;ja&#34; dir=&#34;ltr&#34;&gt;ARKitを使ったリモートタッチパッドの実験。精度がまだ荒いけど基本的には上手くいってる。&lt;a href=&#34;https://twitter.com/hashtag/ue4?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#ue4&lt;/a&gt; &lt;a href=&#34;https://twitter.com/hashtag/arkit?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#arkit&lt;/a&gt; &lt;a href=&#34;https://t.co/Kt5E5fPCQn&#34;&gt;pic.twitter.com/Kt5E5fPCQn&lt;/a&gt;&lt;/p&gt;&amp;mdash; ayuma (@ayuma_x) &lt;a href=&#34;https://twitter.com/ayuma_x/status/1210122895520718849?ref_src=twsrc%5Etfw&#34;&gt;December 26, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;


&lt;p&gt;When you trace your finger over the iPad, a line is drawn on the display inside the iPad, but when you remove the iPad, the same line is drawn on the actual display.&lt;/p&gt;
&lt;p&gt;This might be confusing at first glance, but actually, nothing is added to the iPad side display. Only the camera feed is shown on the iPad&amp;rsquo;s display.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>The other day, wanting to give shape to an idea I had, I created something like this ↓.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ARKitを使ったリモートタッチパッドの実験。精度がまだ荒いけど基本的には上手くいってる。<a href="https://twitter.com/hashtag/ue4?src=hash&amp;ref_src=twsrc%5Etfw">#ue4</a> <a href="https://twitter.com/hashtag/arkit?src=hash&amp;ref_src=twsrc%5Etfw">#arkit</a> <a href="https://t.co/Kt5E5fPCQn">pic.twitter.com/Kt5E5fPCQn</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1210122895520718849?ref_src=twsrc%5Etfw">December 26, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>When you trace your finger over the iPad, a line is drawn on the display inside the iPad, but when you remove the iPad, the same line is drawn on the actual display.</p>
<p>This might be confusing at first glance, but actually, nothing is added to the iPad side display. Only the camera feed is shown on the iPad&rsquo;s display.</p>
<h1 id="what-did-i-want-to-do">What Did I Want to Do?</h1>
<p>A while ago, I was creating AR content using an iPad for work, and that&rsquo;s when I thought, &ldquo;I want to think about uses for AR other than [overlaying some display].&rdquo;</p>
<p>I&rsquo;m sure someone has probably done something similar to what I did this time, but I tried it because &ldquo;there&rsquo;s meaning in thinking up and shaping ideas yourself.&rdquo;</p>
<p>In this experiment, the iPad is used as an input device.
The idea is to create a remote touch display by skillfully using ARKit&rsquo;s image detection and object detection features.</p>
<h1 id="things-to-do">Things to Do</h1>
<p>I&rsquo;ve summarized the things that need to be done to shape this idea below.</p>
<p>This time, the iPad application is built based on UE4 (4.24)&rsquo;s Handheld AR Blueprint template.</p>
<ul>
<li>Know the position and angle of the display shown on the iPad</li>
<li>Know the position of the finger touching the iPad as relative coordinates on the display</li>
<li>Send coordinates from the iPad to the PC side</li>
<li>Draw lines on the PC side according to the sent coordinates</li>
</ul>
<h2 id="know-the-position-and-angle-of-the-display-shown-on-the-ipad">Know the position and angle of the display shown on the iPad</h2>
<p>First, we need to know the position of the display.</p>
<p>I considered two methods for knowing the position: &ldquo;marker method using images&rdquo; and &ldquo;object detection,&rdquo; but this time I chose object detection.</p>
<p>I wrote an article before about how to use object detection with UE4+ARKit, so please take a look if you&rsquo;re interested.</p>
<p><a href="https://www.ayumax.net/entry/2019/08/15/230221">Using ARKit&rsquo;s Object Detection Feature in UE4 - AYU MAX</a></p>
<p>First, I tried creating detection data by scanning the display, but the display&rsquo;s shape had few feature points, and I couldn&rsquo;t get satisfactory results.</p>
<p>So, I created detection data for the cluttered area next to the display and decided to determine the display&rsquo;s position and angle based on the relative position from that point.</p>
<p>Naturally, this method breaks down if the positional relationship with the display changes.</p>
<p>↓ Scanning process
<figure>
    <img loading="lazy" src="/images/2019/12/28/142724/20191228115323.jpg"/> 
</figure>
</p>
<p>Knowing the display&rsquo;s position and angle after scanning is exactly as described in the previous article mentioned above.</p>
<h2 id="know-the-position-of-the-finger-touching-the-ipad-as-relative-coordinates-on-the-display">Know the position of the finger touching the iPad as relative coordinates on the display</h2>
<p>Next, let&rsquo;s think about how to know the position of the finger touching the iPad.</p>
<p>In the implementation within the UE4 AR template used this time, there is logic (WorldHitTest function in BP_ARPawn) to check if there is an Actor at the touched point.</p>
<p>I thought about tweaking this to know the display&rsquo;s position.</p>
<p>First, prepare a flat mesh that is the same size as the real-world display and place it in the level. This mesh doesn&rsquo;t need to be visible, so I applied a transparent material.</p>
<p>Next, on every Tick, move this mesh to the position and angle where ARKit detects the real display.</p>
<figure>
    <img loading="lazy" src="/images/2019/12/28/142724/20191228115926.png"/> 
</figure>

<p>Next, looking inside the WorldHitTest function, you can see that the <code>LineTraceForObjects</code> node is used.</p>
<p><code>LineTraceForObjects</code> can determine if there is a 3D object between two specified points.</p>
<p>Combining this node with the <code>Deproject Screen to World</code> placed just before it allows identifying the 3D object placed at the touched location from the screen coordinates (x, y) on the iPad when touched.</p>
<p>Using this mechanism, we can determine whether the mesh placed earlier is being touched by a finger.</p>
<p>However, what we want to know this time is where on the display is being touched, so we need more detailed information.</p>
<p>Therefore, I tried adding a part that feeds the value returned by <code>LineTraceForObjects</code> into <code>Find Collision UV</code>.</p>
<p>This allows us to get information down to which part (UV coordinates) of the surface of the touched 3D object.</p>
<figure>
    <img loading="lazy" src="/images/2019/12/28/142724/20191228120122.png"/> 
</figure>

<ul>
<li>To use <code>Find Collision UV</code>, you need to check <code>Support UV From Hit Results</code> in Project Settings. (Turning it ON probably increases processing load)</li>
</ul>
<figure>
    <img loading="lazy" src="/images/2019/12/28/142724/20191228121500.png"/> 
</figure>

<h2 id="send-coordinates-from-the-ipad-to-the-pc-side">Send coordinates from the iPad to the PC side</h2>
<p>We will send coordinates from the iPad to the PC (Windows) via socket communication (UDP).</p>
<p>We use ObjectDeliverer for UDP transmission.
For ObjectDeliverer, please see <a href="https://www.ayumax.net/archive/category/ObjectDeliverer">past articles</a>.</p>
<p>First, create a container for sending. It&rsquo;s simple, just define a Blueprint like the one below. I named the object TouchPosition.
Only variables for X and Y coordinates are defined.</p>
<figure>
    <img loading="lazy" src="/images/2019/12/28/142724/20191228122246.png"/> 
</figure>

<p>Initialize ObjectDeliverer to send this object.</p>
<p>↓ Like this.</p>
<figure>
    <img loading="lazy" src="/images/2019/12/28/142724/20191228122845.png"/> 
</figure>

<p>And at the place where the UV of the flat mesh is obtained with <code>Find Collision UV</code>, send the coordinates to the PC using UDP as follows.</p>
<figure>
    <img loading="lazy" src="/images/2019/12/28/142724/20191228122159.png"/> 
</figure>

<p>With this, every time the display shown on the iPad is touched, the coordinates of where on the display is being touched are continuously sent to the PC.</p>
<h2 id="draw-lines-on-the-pc-side-according-to-the-sent-coordinates">Draw lines on the PC side according to the sent coordinates</h2>
<p>The PC side isn&rsquo;t doing anything complicated; it just receives UDP using ObjectDeliverer, extracts the sent X, Y coordinates, and then draws lines using UMG.</p>
<p>This part is not crucial this time, so I&rsquo;ll omit it.</p>
<h1 id="thoughts-after-trying-it">Thoughts After Trying It</h1>
<p>I was able to achieve the movement exactly as I had thought.</p>
<p>Although nothing other than the camera feed is displayed on the iPad, I was able to create something interesting by utilizing ARKit&rsquo;s features.
I feel that this kind of usage holds various possibilities.</p>
<p>I&rsquo;ll try to shape new ideas when they come up.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Let&#39;s Serialize UObjects to Json</title>
      <link>https://ayumax.net/entry/2019/12/20/000000/</link>
      <pubDate>Fri, 20 Dec 2019 00:00:00 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/12/20/000000/</guid>
      <description>&lt;p&gt;This article is the 20th day post for the Unreal Engine 4 (UE4) Advent Calendar 2019.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://qiita.com/advent-calendar/2019/ue4&#34;&gt;Unreal Engine 4 (UE4) Advent Calendar 2019 - Qiita&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I have a plugin called ObjectDeliverer published on the Marketplace.&lt;/p&gt;
&lt;p&gt;This article is about the &amp;ldquo;function to serialize objects to Json&amp;rdquo; implemented in this plugin.&lt;/p&gt;
&lt;p&gt;For example, if you have a Blueprint (inheriting from Object) with Variables defined like this,&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://ayumax.net/images/2019/12/20/000000/20191219000136.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;It will be converted into a Json string like this.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>This article is the 20th day post for the Unreal Engine 4 (UE4) Advent Calendar 2019.</p>
<p><a href="https://qiita.com/advent-calendar/2019/ue4">Unreal Engine 4 (UE4) Advent Calendar 2019 - Qiita</a></p>
<p>I have a plugin called ObjectDeliverer published on the Marketplace.</p>
<p>This article is about the &ldquo;function to serialize objects to Json&rdquo; implemented in this plugin.</p>
<p>For example, if you have a Blueprint (inheriting from Object) with Variables defined like this,</p>
<figure>
    <img loading="lazy" src="/images/2019/12/20/000000/20191219000136.png"/> 
</figure>

<p>It will be converted into a Json string like this.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;IntValue&#34;</span>:<span style="color:#ae81ff">0</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;BoolValue&#34;</span>:<span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;StringValue&#34;</span>:<span style="color:#e6db74">&#34;ABC&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Since Json is represented as a string, it can be saved directly to a text file.
Also, being a string, its content is easily understandable by humans.</p>
<p>By also creating a function to restore objects from this Json, saving and restoring objects via Json becomes possible.</p>
<p>In ObjectDeliverer, by sending and receiving this Json string over communication, objects can be delivered to another location (another application).</p>
<h1 id="handling-json-in-ue4">Handling Json in UE4</h1>
<p>UE4 comes standard with modules named <code>Json</code> and <code>JsonUtilities</code>.</p>
<h2 id="json-module">Json Module</h2>
<p>A module that supports reading and writing Json. However, it cannot be used in Blueprints and is only supported in C++.</p>
<p>It can be used like this.</p>
<h3 id="json-object---json-string">Json Object -&gt; Json String</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">// Create FJsonObject (container for Json data)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>TSharedPtr<span style="color:#f92672">&lt;</span>FJsonObject<span style="color:#f92672">&gt;</span> jsonObject <span style="color:#f92672">=</span> MakeShareable(<span style="color:#66d9ef">new</span> FJsonObject());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Add properties to jsonObject
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Create a Writer to write Json to FString
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>FString OutputString;
</span></span><span style="display:flex;"><span>TSharedRef<span style="color:#f92672">&lt;</span>TJsonWriter<span style="color:#f92672">&lt;&gt;&gt;</span> Writer <span style="color:#f92672">=</span> TJsonWriterFactory<span style="color:#f92672">&lt;&gt;::</span>Create(<span style="color:#f92672">&amp;</span>OutputString);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Write Json to FString
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>FJsonSerializer<span style="color:#f92672">::</span>Serialize(jsonObject.ToSharedRef(), Writer);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Json string is in OutputString, do something with it
</span></span></span></code></pre></div><h3 id="json-string---json-object">Json String -&gt; Json Object</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">// FString containing the json string
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>FString jsonString;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Create a Reader to read Json from FString
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>TSharedRef<span style="color:#f92672">&lt;</span>TJsonReader<span style="color:#f92672">&lt;</span>TCHAR<span style="color:#f92672">&gt;&gt;</span> JsonReader <span style="color:#f92672">=</span> TJsonReaderFactory<span style="color:#f92672">&lt;</span>TCHAR<span style="color:#f92672">&gt;::</span>Create(jsonString);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Create FJsonObject (container for Json data)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>TSharedPtr<span style="color:#f92672">&lt;</span>FJsonObject<span style="color:#f92672">&gt;</span> JsonObject <span style="color:#f92672">=</span> MakeShareable(<span style="color:#66d9ef">new</span> FJsonObject());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Read from Json string into Json object
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>FJsonSerializer<span style="color:#f92672">::</span>Deserialize(JsonReader, JsonObject);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Extract properties from jsonObject and do something
</span></span></span></code></pre></div><h3 id="get-set-json-object-values">Get, Set Json Object Values</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>TSharedPtr<span style="color:#f92672">&lt;</span>FJsonObject<span style="color:#f92672">&gt;</span> JsonObject <span style="color:#f92672">=</span> MakeShareable(<span style="color:#66d9ef">new</span> FJsonObject());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Set values
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>JsonObject<span style="color:#f92672">-&gt;</span>SetNumberField(<span style="color:#e6db74">&#34;IntValue&#34;</span>, <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>JsonObject<span style="color:#f92672">-&gt;</span>SetBoolField(<span style="color:#e6db74">&#34;BoolValue&#34;</span>, true);
</span></span><span style="display:flex;"><span>JsonObject<span style="color:#f92672">-&gt;</span>SetStringField(<span style="color:#e6db74">&#34;StringValue&#34;</span>, <span style="color:#e6db74">&#34;ABCDEFG&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Get values
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>int32 intValue <span style="color:#f92672">=</span> JsonObject<span style="color:#f92672">-&gt;</span>GetIntegerField(<span style="color:#e6db74">&#34;IntValue&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> boolValue <span style="color:#f92672">=</span> JsonObject<span style="color:#f92672">-&gt;</span>GetBoolField(<span style="color:#e6db74">&#34;BoolValue&#34;</span>);
</span></span><span style="display:flex;"><span>FString stringValue <span style="color:#f92672">=</span> JsonObject<span style="color:#f92672">-&gt;</span>GetStringField(<span style="color:#e6db74">&#34;StringValue&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Array and Object properties can also be Get, Set
</span></span></span></code></pre></div><p>Knowing the above patterns should cover most cases.</p>
<h2 id="jsonutilities-module">JsonUtilities Module</h2>
<p>Separate from the Json module, there is a JsonUtilities module.
This is a support module that uses the Json module.</p>
<p>Inside it, there is a class called <code>FJsonObjectConverter</code>, which sounds like it could convert objects to Json based on the name.</p>
<p>However, looking inside, it was a class that provides mutual conversion between UStruct and JSON.
What I want to achieve is mutual conversion between UObject and JSON, so it was slightly different. Disappointing.</p>
<p>By the way, this functionality can be used by calling the following two static methods.</p>
<ul>
<li>UStructToJsonObject</li>
<li>JsonObjectToUStruct</li>
</ul>
<h1 id="creating-uobject-and-json-mutual-conversion-yourself">Creating UObject and JSON Mutual Conversion Yourself</h1>
<p>First, although I wrote <em><strong>creating yourself</strong></em>, it&rsquo;s almost the same as the implementation of the <code>FJsonObjectConverter</code> class.</p>
<p><a href="https://github.com/ayumax/ObjectDeliverer/blob/master/Plugins/ObjectDeliverer/Source/ObjectDeliverer/Private/Utils/ObjectJsonSerializer.cpp"><a href="https://github.com/ayumax/ObjectDeliverer/blob/master/Plugins/ObjectDeliverer/Source/ObjectDeliverer/Private/Utils/ObjectJsonSerializer.cpp">https://github.com/ayumax/ObjectDeliverer/blob/master/Plugins/ObjectDeliverer/Source/ObjectDeliverer/Private/Utils/ObjectJsonSerializer.cpp</a></a></p>
<p>If you compare it side-by-side with the <code>FJsonObjectConverter</code> class, you&rsquo;ll see they are almost identical.</p>
<p>I only added the UObject handling process to the implementation of the <code>FJsonObjectConverter</code> class.</p>
<p>The complete code is at the link above, but I will explain only the representative parts for realizing the functionality.</p>
<h2 id="uobject---jsonobject">UObject -&gt; JsonObject</h2>
<p>This is the process of converting UObject to Json.</p>
<p>First, use TFieldIterator to get a list of UObject properties (including variables defined in Blueprints) and process them sequentially.</p>
<p>In a pure C++ program not using Unreal Engine, this kind of thing (reflection) is not possible.
(Although I&rsquo;ve seen articles discussing it for future C++ plans)</p>
<p>In UE4 C++, reflection is apparently called the property system.</p>
<p>Details are written here.
<a href="https://www.unrealengine.com/en-US/blog/unreal-property-system-reflection">Unreal Property System (Reflection)</a></p>
<p>Once property information (UProperty) is obtained, the property name and the actual property value can also be retrieved using it.</p>
<p>After that, Json properties can be created in the same way as setting properties on a Json object described earlier.</p>
<p>However, since nested structures where a UObject contains a UObject property also need to be considered, the processing here is done recursively.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>TSharedPtr<span style="color:#f92672">&lt;</span>FJsonObject<span style="color:#f92672">&gt;</span> UObjectJsonSerializer<span style="color:#f92672">::</span>CreateJsonObject(<span style="color:#66d9ef">const</span> UObject<span style="color:#f92672">*</span> Obj)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    TSharedPtr<span style="color:#f92672">&lt;</span>FJsonObject<span style="color:#f92672">&gt;</span> JsonObject <span style="color:#f92672">=</span> MakeShareable(<span style="color:#66d9ef">new</span> FJsonObject());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>Obj) <span style="color:#66d9ef">return</span> JsonObject;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Process the list of UObject properties sequentially
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">for</span> (TFieldIterator<span style="color:#f92672">&lt;</span>UProperty<span style="color:#f92672">&gt;</span> PropIt(Obj<span style="color:#f92672">-&gt;</span>GetClass(), EFieldIteratorFlags<span style="color:#f92672">::</span>IncludeSuper); PropIt; <span style="color:#f92672">++</span>PropIt)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        UProperty<span style="color:#f92672">*</span> Property <span style="color:#f92672">=</span> <span style="color:#f92672">*</span>PropIt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Get property name
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        FString PropertyName <span style="color:#f92672">=</span> Property<span style="color:#f92672">-&gt;</span>GetName();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Get property value
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        uint8<span style="color:#f92672">*</span> CurrentPropAddr <span style="color:#f92672">=</span> PropIt<span style="color:#f92672">-&gt;</span>ContainerPtrToValuePtr<span style="color:#f92672">&lt;</span>uint8<span style="color:#f92672">&gt;</span>((UObject<span style="color:#f92672">*</span>)Obj);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        FJsonObjectConverter<span style="color:#f92672">::</span>CustomExportCallback CustomCB;
</span></span><span style="display:flex;"><span>        CustomCB.BindStatic(UObjectJsonSerializer<span style="color:#f92672">::</span>ObjectJsonCallback);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Set to Json property
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e">// FJsonObjectConverter::UPropertyToJsonValue is processed recursively
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        JsonObject<span style="color:#f92672">-&gt;</span>SetField(PropertyName, FJsonObjectConverter<span style="color:#f92672">::</span>UPropertyToJsonValue(Property, CurrentPropAddr, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>, <span style="color:#f92672">&amp;</span>CustomCB));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> JsonObject;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="jsonobject---uobject">JsonObject -&gt; UObject</h2>
<p>This is the process of restoring UObject from Json.</p>
<p>Similar to the process of converting UObject to Json, this also uses the UE4 property system to dynamically obtain the property list and process it sequentially.</p>
<p>The flow is to obtain UProperty, get the property name from it, then get the Json property from JsonObject and set it to the UObject&rsquo;s property.</p>
<p>This function is also called recursively to support nested structures.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> UObjectJsonSerializer<span style="color:#f92672">::</span>JsonObjectToUObject(<span style="color:#66d9ef">const</span> TSharedPtr<span style="color:#f92672">&lt;</span>FJsonObject<span style="color:#f92672">&gt;&amp;</span> JsonObject, UObject<span style="color:#f92672">*</span> OutObject)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">auto</span><span style="color:#f92672">&amp;</span> JsonAttributes <span style="color:#f92672">=</span> JsonObject<span style="color:#f92672">-&gt;</span>Values;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Get the property list of the UObject to restore
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">for</span> (TFieldIterator<span style="color:#f92672">&lt;</span>UProperty<span style="color:#f92672">&gt;</span> PropIt(OutObject<span style="color:#f92672">-&gt;</span>GetClass()); PropIt; <span style="color:#f92672">++</span>PropIt)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        UProperty<span style="color:#f92672">*</span> Property <span style="color:#f92672">=</span> <span style="color:#f92672">*</span>PropIt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Get Json property from JsonObject using property name as key
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#66d9ef">const</span> TSharedPtr<span style="color:#f92672">&lt;</span>FJsonValue<span style="color:#f92672">&gt;*</span> JsonValue <span style="color:#f92672">=</span> JsonAttributes.Find(Property<span style="color:#f92672">-&gt;</span>GetName());
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>JsonValue)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">continue</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (JsonValue<span style="color:#f92672">-&gt;</span>IsValid() <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">!</span>(<span style="color:#f92672">*</span>JsonValue)<span style="color:#f92672">-&gt;</span>IsNull())
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// Get pointer to UObject property
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#66d9ef">void</span><span style="color:#f92672">*</span> Value <span style="color:#f92672">=</span> Property<span style="color:#f92672">-&gt;</span>ContainerPtrToValuePtr<span style="color:#f92672">&lt;</span>uint8<span style="color:#f92672">&gt;</span>(OutObject);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// Read value from Json property and set to UObject property
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#75715e">// JsonValueToUProperty is processed recursively
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>JsonValueToUProperty(<span style="color:#f92672">*</span>JsonValue, Property, Value))
</span></span><span style="display:flex;"><span>            {
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">return</span> false;
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> true;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h1 id="some-problems">Some Problems</h1>
<p>In ObjectDeliverer, the above ObjectJsonSerializer is used within UObjectDeliveryBoxUsingJson to serialize UObjects to Json.</p>
<p>I also use this feature in my own projects, and while it generally works as intended, some points for improvement have emerged.</p>
<h2 id="need-to-specify-uobject-type-during-jsonobject---uobject">Need to Specify UObject Type During JsonObject -&gt; UObject</h2>
<p>As explained in the JsonObject -&gt; UObject process description above, the UObject type must be predetermined for this process.</p>
<p>Looking at the Json format, you can see that Json has no mechanism to store the object type.</p>
<p>Therefore, just looking at the Json, it&rsquo;s impossible to know which UObject to restore to, so the UObject type needs to be decided beforehand.</p>
<p>Because of this, communication using ObjectDeliverer&rsquo;s UObjectDeliveryBoxUsingJson currently only supports sending and receiving a single UObject type. It cannot handle multiple types with normal usage.</p>
<h2 id="potential-information-loss-when-having-uobject-type-properties">Potential Information Loss When Having UObject Type Properties</h2>
<p>This problem also arises because Json cannot store type information, similar to the previous issue.</p>
<p>For example, consider an environment where ClassB inherits from ClassA.</p>
<p>In that environment, the UObject saved to Json has a property of type ClassA.</p>
<p>An instance of ClassB can be put into this ClassA type property.</p>
<p>When saving to and restoring from Json at this time, properties that exist only in ClassB but not in ClassA will not be restored&hellip;</p>
<p>This is because the UProperty indicating ClassA type is used during property restoration.</p>
<p>This can be avoided if understood and used correctly, but it might lead to hard-to-notice bugs.</p>
<h2 id="json-property-name-may-not-match-the-specified-string">Json Property Name May Not Match the Specified String</h2>
<p>For example, when converting the Blueprint shown in the example at the beginning to Json, it might end up like this.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;Intvalue&#34;</span>:<span style="color:#ae81ff">0</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;boolValue&#34;</span>:<span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;Stringvalue&#34;</span>:<span style="color:#e6db74">&#34;ABC&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>At first glance, it seems to be working correctly, but the case of the property names is wrong.</p>
<p>This is because UE4 properties use the FName type.</p>
<p><a href="https://docs.unrealengine.com/en-US/Programming/UnrealArchitecture/StringHandling/FName/index.html">FName</a></p>
<p>As mentioned on the page above, FName is case-insensitive, which causes this phenomenon.</p>
<p>No problem occurs if both saving to and restoring from Json use ObjectDeliverer within the same UE4 project, but problems (property name mismatch) may arise when exchanging Json with applications created in other development environments.</p>
<h1 id="countermeasures-for-problems">Countermeasures for Problems</h1>
<p>Actually, I wanted to release an update with countermeasures for the above problems by the time this article was published, but it&rsquo;s not complete yet&hellip; (Testing isn&rsquo;t finished)</p>
<p>The work is being done on the following branch, and the implementation is almost complete, so you can see what it looks like.</p>
<p>The Json serialization part has undergone significant changes.</p>
<p><a href="https://github.com/ayumax/ObjectDeliverer/tree/Remodeling-ObjectJsonSerializer"><a href="https://github.com/ayumax/ObjectDeliverer/tree/Remodeling-ObjectJsonSerializer">https://github.com/ayumax/ObjectDeliverer/tree/Remodeling-ObjectJsonSerializer</a></a></p>
<p>The countermeasures taken are the following two.</p>
<h2 id="write-uobject-type-information-into-json-based-on-user-selection">Write UObject Type Information into Json Based on User Selection</h2>
<p>The first and second problems can be resolved by writing the UObject type information into the Json.</p>
<p>However, doing so changes the Json format from before, breaking compatibility, and purely increases the Json string length, making the data size larger, which might be undesirable from the perspective of data transmission, ObjectDeliverer&rsquo;s main purpose.</p>
<p>Therefore, a mechanism is introduced where the user can choose whether or not to write type information into the Json for each UObject type.</p>
<p>This allows creating the same Json as before under the condition that only one type is sent/received and UObject properties using class inheritance are not created.</p>
<p>Also, by choosing to write the actual instance&rsquo;s type information, reliable restoration can be achieved when saving and restoring UObjects.</p>
<p>Specifically, the following differences arise in the created Json.</p>
<h3 id="when-not-writing-type-information-implementation-up-to-now">When not writing type information (implementation up to now)</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;IntValue&#34;</span>:<span style="color:#ae81ff">0</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;BoolValue&#34;</span>:<span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;StringValue&#34;</span>:<span style="color:#e6db74">&#34;ABC&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="when-writing-type-information">When writing type information</h3>
<p>Example when serializing a UObject named <code>NewBlueprint</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;Type&#34;</span>:<span style="color:#e6db74">&#34;NewBlueprint&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;Body&#34;</span> :
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;IntValue&#34;</span>:<span style="color:#ae81ff">0</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;BoolValue&#34;</span> : <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;StringValue&#34;</span> : <span style="color:#e6db74">&#34;ABC&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="definition-of-an-interface-to-implement-property-name-conversion-function">Definition of an Interface to Implement Property Name Conversion Function</h2>
<p>Since conversion from FName type to FString type might not result in the intended string if left to automatic conversion, an interface for property name conversion was added so users can define it reliably themselves.</p>
<p>If this interface is implemented on the UObject to be serialized, the custom property name conversion function will be used for writing and reading Json properties.</p>
<p>If the interface is not implemented, automatic FName -&gt; FString conversion will occur as before.</p>
<p>By using this feature, it becomes possible to create Json properties with completely different strings, so I believe it has uses beyond solving the current problem.</p>
<figure>
    <img loading="lazy" src="/images/2019/12/20/000000/20191219164339.png"/> 
</figure>

<figure>
    <img loading="lazy" src="/images/2019/12/20/000000/20191219164521.png"/> 
</figure>

<h1 id="finally">Finally</h1>
<p>This time, I wrote about serializing UObjects to JsonObjects.</p>
<p>The source code of FJsonObjectConverter from the JsonUtilities module mentioned in this article contains implementations that are helpful not only for creating UObject serialization to formats other than Json but also for utilizing the UE4 property system, so please take a look.</p>
<p>Also, the ObjectDeliverer I have published aims to easily create communication using TCP/IP, UDP, etc., using only Blueprints. It&rsquo;s available for Free, so please try it if you like.</p>
<p><a href="https://www.unrealengine.com/marketplace/en-US/product/objectdeliverer">ObjectDeliverer: ayumax: Code Plugins - UE4 Marketplace</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Unloading Assemblies in .NET Core</title>
      <link>https://ayumax.net/entry/2019/12/10/000000/</link>
      <pubDate>Tue, 10 Dec 2019 00:00:00 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/12/10/000000/</guid>
      <description>&lt;h1 id=&#34;mechanism-for-unloading-assemblies&#34;&gt;Mechanism for Unloading Assemblies&lt;/h1&gt;
&lt;p&gt;This article is for the 10th day of the &lt;a href=&#34;https://qiita.com/advent-calendar/2019/c-sharp&#34;&gt;C# Advent Calendar 2019&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;An application I create for work (made with .NET Framework) has a user plugin (DLL) loading feature.&lt;/p&gt;
&lt;p&gt;This feature allows users to add functionality to the development tool by creating their own DLLs according to rules.&lt;/p&gt;
&lt;p&gt;This feature involves the development tool loading the relevant DLLs once, querying them, and then unloading DLLs that don&amp;rsquo;t need to be loaded.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="mechanism-for-unloading-assemblies">Mechanism for Unloading Assemblies</h1>
<p>This article is for the 10th day of the <a href="https://qiita.com/advent-calendar/2019/c-sharp">C# Advent Calendar 2019</a>.</p>
<p>An application I create for work (made with .NET Framework) has a user plugin (DLL) loading feature.</p>
<p>This feature allows users to add functionality to the development tool by creating their own DLLs according to rules.</p>
<p>This feature involves the development tool loading the relevant DLLs once, querying them, and then unloading DLLs that don&rsquo;t need to be loaded.</p>
<p>When porting this development tool to .NET Core, a different method than .NET Framework was required, which I will introduce.</p>
<h1 id="appdomain-cannot-be-used">AppDomain Cannot Be Used</h1>
<p>In .NET Framework, AppDomain was used to unload assemblies.</p>
<p>Besides the application&rsquo;s default AppDomain, another domain is created, and assemblies are loaded within it.</p>
<p>After using the assembly&rsquo;s functionality via interfaces, etc., the AppDomain&rsquo;s Unload method is called to unload the assembly along with the domain.</p>
<p>However, in .NET Core, only one AppDomain is supported, so this method cannot be used.</p>
<p>Instead, .NET Core provides AssemblyLoadContext for unloading assemblies, so I will try using this.</p>
<h1 id="what-is-assemblyloadcontext">What is AssemblyLoadContext?</h1>
<p>AssemblyLoadContext, similar to AppDomain, allows assembly loading within a closed scope.</p>
<p>Assemblies loaded into it can be unloaded together by calling the AssemblyLoadContext&rsquo;s Unload method, but there are points to note.</p>
<h2 id="note-1-set-iscollectible-to-true">Note 1: Set isCollectible to true</h2>
<p>The <code>isCollectible</code> constructor argument of AssemblyLoadContext must be set to true.</p>
<p>This is because, for performance reasons, it defaults to false.</p>
<p>Calling Unload while it&rsquo;s false will cause an exception.</p>
<pre tabindex="0"><code>System.InvalidOperationException
  HResult=0x80131509
  Message=Cannot unload non-collectible AssemblyLoadContext.
  Source=System.Private.CoreLib
</code></pre><h2 id="note-2-unloading-is-cooperative-not-forced">Note 2: Unloading is Cooperative, Not Forced</h2>
<p>Calling the AssemblyLoadContext&rsquo;s Unload method only initiates the process; it does not complete it immediately.</p>
<p>Unloading completes only when the following conditions are met:</p>
<ul>
<li>No threads have methods from assemblies loaded into the AssemblyLoadContext on their call stacks.</li>
<li>Types from assemblies loaded into the AssemblyLoadContext, instances of those types, and the assemblies themselves are no longer referenced.</li>
</ul>
<p>In other words, without careful design, unloading might never complete.</p>
<h1 id="creating-a-sample">Creating a Sample</h1>
<p>Let&rsquo;s actually implement a mechanism to unload assemblies.</p>
<h2 id="1-create-the-class-library-to-be-loaded">1. Create the Class Library to be Loaded</h2>
<p>Anything will do, but I defined a simple class like the one below.
I specified netstandard2.1 for the TargetFramework.
Make sure this is output as ClassLibrary1.dll.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#66d9ef">namespace</span> ClassLibrary1
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Class1</span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Hello(<span style="color:#66d9ef">int</span> arg)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            Console.WriteLine(arg);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="2-implement-assemblyloadcontext-on-the-loading-side">2. Implement AssemblyLoadContext on the Loading Side</h2>
<p>First, create an AssemblyLoadContext for loading assemblies.
This time, I created a simple class like the one below.</p>
<p>The important part is setting <code>isCollectible</code> to true in the constructor.
Setting this flag to true enables unloading support.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TestAssemblyLoadContext</span> : AssemblyLoadContext
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> TestAssemblyLoadContext() : <span style="color:#66d9ef">base</span>(isCollectible: <span style="color:#66d9ef">true</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="3-implement-the-dll-loading--unloading-mechanism">3. Implement the DLL Loading &amp; Unloading Mechanism</h2>
<p>Create a function to load the ClassLibrary1.dll created earlier, call a function, and then unload it.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#a6e22e">[MethodImpl(MethodImplOptions.NoInlining)]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> ExecuteAndUnload(<span style="color:#66d9ef">string</span> assemblyPath, <span style="color:#66d9ef">out</span> WeakReference alcWeakRef)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Create AssemblyLoadContext to load the assembly</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> alc = <span style="color:#66d9ef">new</span> TestAssemblyLoadContext();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Load the assembly</span>
</span></span><span style="display:flex;"><span>    Assembly a = alc.LoadFromAssemblyPath(assemblyPath);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Set a weak reference to detect unloading from outside</span>
</span></span><span style="display:flex;"><span>    alcWeakRef = <span style="color:#66d9ef">new</span> WeakReference(alc, trackResurrection: <span style="color:#66d9ef">true</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Call function via reflection</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> type = a.GetType(<span style="color:#e6db74">&#34;ClassLibrary1.Class1&#34;</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> instance = Activator.CreateInstance(type);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> helloMethod = type.GetMethod(<span style="color:#e6db74">&#34;Hello&#34;</span>);
</span></span><span style="display:flex;"><span>    helloMethod.Invoke(instance, <span style="color:#66d9ef">new</span> <span style="color:#66d9ef">object</span>[] { <span style="color:#ae81ff">1</span> });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Perform unload</span>
</span></span><span style="display:flex;"><span>    alc.Unload();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Add MethodImplOptions.NoInlining to the function just in case.</p>
<p>This is to prevent the ExecuteAndUnload function from being inlined.</p>
<p>Unloading using AssemblyLoadContext cannot be performed if types or instances within the AssemblyLoadContext are referenced from outside.</p>
<p>Therefore, if inlined, there is a risk that references might remain in the caller of ExecuteAndUnload (in this case, the Main function).</p>
<p>(* However, in the sample created this time, unloading completed even with MethodImplOptions.AggressiveInlining)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#a6e22e">[MethodImpl(MethodImplOptions.NoInlining)]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> ExecuteAndUnload(<span style="color:#66d9ef">string</span> assemblyPath, <span style="color:#66d9ef">out</span> WeakReference alcWeakRef)
</span></span></code></pre></div><p>Create an instance of AssemblyLoadContext and load the assembly into it.</p>
<p><code>assemblyPath</code> contains the file path of the dll or exe.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span> <span style="color:#75715e">// Create AssemblyLoadContext to load the assembly</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> alc = <span style="color:#66d9ef">new</span> TestAssemblyLoadContext();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// Load the assembly</span>
</span></span><span style="display:flex;"><span>Assembly a = alc.LoadFromAssemblyPath(assemblyPath);
</span></span></code></pre></div><p>Keep a weak reference to the AssemblyLoadContext.</p>
<p>This reference is used by the caller of ExecuteAndUnload to determine if unloading is complete.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#75715e">// Set a weak reference to detect unloading from outside</span>
</span></span><span style="display:flex;"><span>alcWeakRef = <span style="color:#66d9ef">new</span> WeakReference(alc, trackResurrection: <span style="color:#66d9ef">true</span>);
</span></span></code></pre></div><p>For this experiment, I specified the class name to create an instance and called the function using reflection.</p>
<p>When creating a plugin, it&rsquo;s more practical to have ClassLibrary1.dll implement an interface defined in a separate assembly and call it via the interface.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#75715e">// Call function via reflection</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> type = a.GetType(<span style="color:#e6db74">&#34;ClassLibrary1.Class1&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> instance = Activator.CreateInstance(type);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> helloMethod = type.GetMethod(<span style="color:#e6db74">&#34;Hello&#34;</span>);
</span></span><span style="display:flex;"><span>helloMethod.Invoke(instance, <span style="color:#66d9ef">new</span> <span style="color:#66d9ef">object</span>[] { <span style="color:#ae81ff">1</span> });
</span></span></code></pre></div><p>Call the Unload method to perform unloading.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#75715e">// Perform unload</span>
</span></span><span style="display:flex;"><span>alc.Unload();
</span></span></code></pre></div><h2 id="trying-to-unload-assembly-using-executeandunload">Trying to Unload Assembly Using ExecuteAndUnload</h2>
<p>I implemented the Main function as follows and actually tried dynamically loading and then unloading the assembly.</p>
<p>This time, I checked if unloading was successful by seeing if the dll file could be deleted.
If unloading is not complete, Delete will fail.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> Main(<span style="color:#66d9ef">string</span>[] args)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> myDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Path to the assembly (dll) to load</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> assemblyPath = Path.Combine(myDirectory, <span style="color:#e6db74">@&#34;..\..\..\..\ClassLibrary1\bin\Debug\netstandard2.1\ClassLibrary1.dll&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Load the assembly and call the function</span>
</span></span><span style="display:flex;"><span>    ExecuteAndUnload(assemblyPath, <span style="color:#66d9ef">out</span> WeakReference alcWeakRef);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">try</span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        File.Delete(assemblyPath);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">catch</span>(UnauthorizedAccessException)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        Console.WriteLine(<span style="color:#e6db74">&#34;Cannot delete because unloading is not complete&#34;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Wait until unloaded</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> counter = <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (counter = <span style="color:#ae81ff">0</span>; alcWeakRef.IsAlive &amp;&amp; (counter &lt; <span style="color:#ae81ff">10</span>); counter++)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        GC.Collect();
</span></span><span style="display:flex;"><span>        GC.WaitForPendingFinalizers();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (counter &lt; <span style="color:#ae81ff">10</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// At this stage, it&#39;s unloaded, so it can be deleted</span>
</span></span><span style="display:flex;"><span>        File.Delete(assemblyPath);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        Console.WriteLine(<span style="color:#e6db74">&#34;Unload successful&#34;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        Console.WriteLine(<span style="color:#e6db74">&#34;Unload failed&#34;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Console.ReadKey();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>After calling ExecuteAndUnload to load the assembly -&gt; execute the function within the assembly -&gt; unload, I checked the completion of unloading using WeakReference.</p>
<p>To remove references to the AssemblyLoadContext being unloaded, I forced garbage collection using GC.Collect().</p>
<p>In the results I tried this time, when unloading was successful, the value of <code>counter</code> was 2 when exiting the loop.</p>
<p>Also, immediately after exiting ExecuteAndUnload, deleting the dll always failed, but after waiting for unloading to complete, deletion succeeded, confirming that assembly unloading was successful.</p>
<h1 id="trying-to-be-mean">Trying to Be Mean</h1>
<p>The above sample was a case where unloading succeeded, but I tried a bit to see what kind of description would cause it to fail.</p>
<h2 id="case-where-thread-inside-loaded-assembly-doesnt-end">Case Where Thread Inside Loaded Assembly Doesn&rsquo;t End</h2>
<p>I changed the content of the Hello method in ClassLibrary1.dll as follows.</p>
<p>Once Hello is called, a non-terminating thread is created with Task.Run.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Hello(<span style="color:#66d9ef">int</span> arg)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    Task.Run(() =&gt;
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">while</span>(<span style="color:#66d9ef">true</span>)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            Thread.Sleep(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>    Console.WriteLine(arg);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Loading this assembly and attempting to unload it failed.</p>
<h2 id="trying-to-hold-assemblyloadcontext">Trying to Hold AssemblyLoadContext</h2>
<p>Created a static variable like the one below in the class that loads the assembly,</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> AssemblyLoadContext assemblyLoadContext;
</span></span></code></pre></div><p>And tried holding the reference to TestAssemblyLoadContext within ExecuteAndUnload.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> alc = <span style="color:#66d9ef">new</span> TestAssemblyLoadContext();
</span></span><span style="display:flex;"><span>assemblyLoadContext = alc;
</span></span></code></pre></div><p>This case also failed to unload because a reference to AssemblyLoadContext remained.</p>
<h2 id="trying-to-hold-type-within-loaded-assembly">Trying to Hold Type Within Loaded Assembly</h2>
<p>Created a static variable like the one below in the class that loads the assembly,</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> Type class1Type;
</span></span></code></pre></div><p>And tried holding the Type of ClassLibrary1.Class1 within ExecuteAndUnload.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> type = a.GetType(<span style="color:#e6db74">&#34;ClassLibrary1.Class1&#34;</span>);
</span></span><span style="display:flex;"><span>class1Type = type;
</span></span></code></pre></div><p>This case also failed to unload because a reference to the Type remained.</p>
<h1 id="summary">Summary</h1>
<p>Even in a .NET Core environment, it was possible to load and unload assemblies using AssemblyLoadContext.</p>
<p>However, if you forget to clean up the assembly being unloaded, unloading will fail, so it seems best to perform the process from loading to unloading within a closed area as much as possible.</p>
<p>Realistically, cases requiring assembly unloading might not be that common, but knowing about it might be useful somewhere.</p>
<h1 id="sample-project">Sample Project</h1>
<p>The sample created this time is in the repository below.</p>
<div class="github-card" data-user="ayumax" data-repo="UnloadAssenbly" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<h1 id="reference-sites">Reference Sites</h1>
<p><a href="https://docs.microsoft.com/en-us/dotnet/standard/assembly/unloadability">How to use and debug assembly unloadability in .NET Core</a></p>
<p><a href="https://www.strathweb.com/2019/01/collectible-assemblies-in-net-core-3-0/">Collectible assemblies in .NET Core 3.0 | StrathWeb. A free flowing web tech monologue.</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>ObjectDeliverer Ver 1.4.0 Released - Added Feature to Get Sender IP Address</title>
      <link>https://ayumax.net/entry/2019/10/20/230758/</link>
      <pubDate>Sun, 20 Oct 2019 23:07:58 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/10/20/230758/</guid>
      <description>&lt;h1 id=&#34;objectdeliverer-ver-140&#34;&gt;ObjectDeliverer Ver 1.4.0&lt;/h1&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://ayumax.net/images/2019/10/20/230758/20190731231924.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;Speaking of a few days ago, a new version of ObjectDeliverer has been released.
(I meant to write a blog post but forgot)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.unrealengine.com/marketplace/en-US/slug/objectdeliverer&#34;&gt;ObjectDeliverer: ayumax: Code Plugins - UE4 Marketplace&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&#34;added-feature-to-get-sender-ip-address&#34;&gt;Added Feature to Get Sender IP Address&lt;/h1&gt;
&lt;p&gt;This feature is only available when the communication protocol is set to TCP/IP Server or UDP Receiver.&lt;/p&gt;
&lt;p&gt;With these two communication protocols, the sender can potentially have multiple IP addresses.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="objectdeliverer-ver-140">ObjectDeliverer Ver 1.4.0</h1>
<figure>
    <img loading="lazy" src="/images/2019/10/20/230758/20190731231924.png"/> 
</figure>

<p>Speaking of a few days ago, a new version of ObjectDeliverer has been released.
(I meant to write a blog post but forgot)</p>
<p><a href="https://www.unrealengine.com/marketplace/en-US/slug/objectdeliverer">ObjectDeliverer: ayumax: Code Plugins - UE4 Marketplace</a></p>
<h1 id="added-feature-to-get-sender-ip-address">Added Feature to Get Sender IP Address</h1>
<p>This feature is only available when the communication protocol is set to TCP/IP Server or UDP Receiver.</p>
<p>With these two communication protocols, the sender can potentially have multiple IP addresses.</p>
<p>However, in previous versions, there was no way to know where the transmission came from.
(Strictly speaking, TCP/IP Server had a function to distinguish and recognize the sender, but there was no function to know the IP address.)</p>
<p>This is because, to realize ObjectDeliverer&rsquo;s design philosophy of &ldquo;being able to switch and use different communication protocols in the same way,&rdquo; I didn&rsquo;t want to include features too specific to individual protocols.</p>
<p>However, realistically, there were situations where it was inconvenient not to have it, so I implemented it this time.</p>
<p>Below is an example specification.</p>
<p><a href="https://user-images.githubusercontent.com/8191970/66717219-6ce03b00-ee11-11e9-91fc-a831a770d8fe.png" class="http-image" target="_blank"><img src="https://user-images.githubusercontent.com/8191970/66717219-6ce03b00-ee11-11e9-91fc-a831a770d8fe.png" class="http-image" alt="https://user-images.githubusercontent.com/8191970/66717219-6ce03b00-ee11-11e9-91fc-a831a770d8fe.png"/></a></p>
<p>Information can be obtained by using the ClientSocket object of the ReceiveData event through the GetIPV4Info interface.</p>
<p>The newly added GetIPV4Info interface includes GetIPAddress, which retrieves the IP address as an array of 4 uint8 elements, and GetIPAddressinString, which retrieves it as a string in the format &ldquo;<em>.</em>.<em>.</em>&rdquo;.</p>
<p>For communication protocols other than the supported ones, the ClientSocket object of the ReceiveData event does not implement the GetIPV4Info interface, so casting to the interface will fail.</p>
<p>I want to maintain the concept of being able to use things in the same way as much as possible in the future, but I plan to make individual protocol-specific features available via interfaces.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Gave a Lightning Talk at .NET Conf 2019 Meetup in AICHI</title>
      <link>https://ayumax.net/entry/2019/10/10/224452/</link>
      <pubDate>Thu, 10 Oct 2019 22:44:52 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/10/10/224452/</guid>
      <description>&lt;h1 id=&#34;net-conf-2019-meetup-in-aichi&#34;&gt;.NET Conf 2019 Meetup in AICHI&lt;/h1&gt;
&lt;p&gt;This was a local event for &amp;ldquo;.NET Conf 2019&amp;rdquo; held on October 5th.
I participated this time and gave a lightning talk (LT).&lt;/p&gt;
&lt;h1 id=&#34;presentation-content&#34;&gt;Presentation Content&lt;/h1&gt;
&lt;p&gt;Since this was a .NET Core 3.0 event, I thought content related to Core 3 would be better, so I decided to talk about WPF, which was added in .NET Core 3.0.&lt;/p&gt;
&lt;p&gt;The materials for the presentation I gave are below.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="net-conf-2019-meetup-in-aichi">.NET Conf 2019 Meetup in AICHI</h1>
<p>This was a local event for &ldquo;.NET Conf 2019&rdquo; held on October 5th.
I participated this time and gave a lightning talk (LT).</p>
<h1 id="presentation-content">Presentation Content</h1>
<p>Since this was a .NET Core 3.0 event, I thought content related to Core 3 would be better, so I decided to talk about WPF, which was added in .NET Core 3.0.</p>
<p>The materials for the presentation I gave are below.</p>
<iframe src="https://www.slideshare.net/slideshow/embed_code/key/cD4sdzNH5avLcB" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen=""> </iframe> <div style="margin-bottom:5px"> <strong> <a href="https://www.slideshare.net/AyumaKaminosono/net-core30wpf" title=".NET Core 3.0 and WPF" target="_blank">.NET Core 3.0 and WPF</a> </strong> from <strong><a href="https://www.slideshare.net/AyumaKaminosono" target="_blank">AyumaKaminosono</a></strong> </div><cite class="hatena-citation"><a href="https://www.slideshare.net/AyumaKaminosono/net-core30wpf">www.slideshare.net</a></cite>
<p>Also, the presentation content from the day was made into a video.
Thank you, @kekyo2.</p>
<iframe width="480" height="270" src="https://www.youtube.com/embed/YEcduqbNj4I?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?time_continue=3&v=YEcduqbNj4I">www.youtube.com</a></cite>
<p>I thought I should reflect on my presentation, so I tried watching the video that was shared, but watching a video of myself speaking is incredibly embarrassing!!</p>
<p>I was so embarrassed I haven&rsquo;t been able to watch the whole thing yet.</p>
<p>I want to watch it again later after composing myself.</p>
<h1 id="about-theme-selection">About Theme Selection</h1>
<p>I don&rsquo;t have enough knowledge to talk about the deep parts of .NET, so I thought it would be better to present practical experiences rather than discussing language specifications.</p>
<p>Thinking about what to do, I remembered trying out WPF using the .NET Core 3 preview around Golden Week this year, and thought, &ldquo;This will be good presentation material!&rdquo; so I chose WPF as the theme.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">.NET Core 3.0のWPFを試している進捗です。<br>HoudiniみたいなノードベースUIを作成中。なかなか面白いのでこのまま作りこむ予定。<a href="https://twitter.com/hashtag/WPF?src=hash&amp;ref_src=twsrc%5Etfw">#WPF</a> <a href="https://twitter.com/hashtag/dotnetcore?src=hash&amp;ref_src=twsrc%5Etfw">#dotnetcore</a> <a href="https://t.co/C9TNKZOUHS">pic.twitter.com/C9TNKZOUHS</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1125397415937208321?ref_src=twsrc%5Etfw">May 6, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>So, I first listed the content I wanted to talk about for this theme in bullet points to create a foundation for the presentation materials.</p>
<p>Then I realized one crucial thing.</p>
<p><strong>It&rsquo;s not interesting&hellip;</strong></p>
<p>I tried writing plainly about how WPF became usable in .NET Core 3.0, but the content was thin and uninteresting.</p>
<p>At this point, I worried, &ldquo;Was the theme a bad choice??&rdquo;, &ldquo;Would talking about C# 8, which I tried at the same time, have more content??&rdquo; But I decided that since I use WPF regularly, I could answer questions if something came up, so I stuck with it.</p>
<p>Therefore, although not specific to WPF, I added topics that seemed highly relevant, like being able to include the Runtime in the application and creating a single executable file. I also made a video showing how it actually works to let people see it in action.</p>
<p>After writing everything and practicing the presentation a few times, it came out to be about 13-14 minutes, so I decided to go with it.</p>
<p>I still felt the content might be a bit thin, but I couldn&rsquo;t add more at that point, so I decided to brace myself.
(Now, a few days after the event ended, I have more ideas for Core 3 + WPF. Well, that&rsquo;s how it goes.)</p>
<h1 id="presentation-day">Presentation Day</h1>
<p>My turn was towards the end, and until then, I listened with great interest to the talks by the other speakers.</p>
<p>@kekyo2&rsquo;s talk on asynchronous programming personally hit home, as just a little before that day, I had been working on eliminating Task.Wait from code I wrote long ago.</p>
<p>I&rsquo;m very interested in async iterators, so I definitely want to try writing them soon.</p>
<p>This was my second presentation, following an LT last year, but today I felt calmer than last time and was optimistic, thinking, &ldquo;Maybe I won&rsquo;t panic today.&rdquo;</p>
<p>However, my turn was right after a break, so there was some waiting time. As I prepared my PC and waited, I gradually got nervous, and my stomach started hurting lol.</p>
<p>But today, my goals were &ldquo;Don&rsquo;t speak too fast, speak slowly&rdquo; and &ldquo;Look at the faces of the listeners while speaking,&rdquo; so I tried my best to stay calm and speak bit by bit, ensuring I could at least keep those promises.</p>
<p>There was an accident, though; the video output of the MacBook I brought that day was acting up, and the projector turned to static several times, causing me to panic slightly. But in the end, the timing was just right, and I finished, which was good.</p>
<p>Self-evaluation: I think I presented better than last time!</p>
<p>The stomach ache also disappeared after the presentation ended w</p>
<h1 id="reflections-for-next-time">Reflections for Next Time</h1>
<p>Listening to the other presentations, I felt that everyone deeply understood the content they were speaking about.</p>
<p>For my own content, I had researched and tried things out, but I wasn&rsquo;t speaking with perfect confidence everywhere. There were parts I wasn&rsquo;t sure about, and although I actually had more material, I cut out those parts I lacked confidence in.</p>
<p>I felt that to give a confident presentation, a vast amount of knowledge backed by everyday technical practice is necessary.</p>
<p>I can&rsquo;t change the time I&rsquo;ve spent so far, but I feel that from now on, when learning, I want to delve one step deeper into the content than before and gain knowledge I can confidently share with others.</p>
<p>This time too, I learned a lot, and finishing the LT boosted my confidence, so I felt glad I participated.</p>
<h1 id="bonus">Bonus</h1>
<p>After the event ended, there was a rock-paper-scissors tournament, and incredibly, I received a Kinect V1 from matsujirushi-san!!!</p>
<p>I tried it immediately, and it&rsquo;s fun! Motion capture was a first-time experience for me, so it opens up possibilities.</p>
<p>I&rsquo;m currently considering what to create with this.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Kinect V1を動かせた。<br>何これ！控えめに言って面白い！ <a href="https://t.co/RzjbdSIXbR">pic.twitter.com/RzjbdSIXbR</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1181233809309593600?ref_src=twsrc%5Etfw">October 7, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


]]></content:encoded>
    </item>
    <item>
      <title>XPS 15 2-in-1 Review (Dell Ambassador Program)</title>
      <link>https://ayumax.net/entry/2019/10/08/223621/</link>
      <pubDate>Tue, 08 Oct 2019 22:36:21 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/10/08/223621/</guid>
      <description>&lt;h1 id=&#34;i-won-the-dell-ambassador-program-lottery&#34;&gt;I Won the Dell Ambassador Program Lottery&lt;/h1&gt;
&lt;p&gt;Recently, while browsing Twitter, I saw someone reviewing a laptop they borrowed through the Dell Ambassador Program. I decided to register and apply myself on a whim.&lt;/p&gt;
&lt;p&gt;To my surprise, I actually won and got the opportunity to borrow the XPS 15 2-in-1, so I&amp;rsquo;d like to review it.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m sure many others have reviewed the XPS 15 2-in-1 for drawing and similar uses, so I&amp;rsquo;d like to review it from a software developer&amp;rsquo;s perspective.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="i-won-the-dell-ambassador-program-lottery">I Won the Dell Ambassador Program Lottery</h1>
<p>Recently, while browsing Twitter, I saw someone reviewing a laptop they borrowed through the Dell Ambassador Program. I decided to register and apply myself on a whim.</p>
<p>To my surprise, I actually won and got the opportunity to borrow the XPS 15 2-in-1, so I&rsquo;d like to review it.</p>
<p>I&rsquo;m sure many others have reviewed the XPS 15 2-in-1 for drawing and similar uses, so I&rsquo;d like to review it from a software developer&rsquo;s perspective.</p>
<p>I mainly want to write my impressions comparing it to the DELL ALIENWARE 13 R3 I currently use.</p>
<h1 id="size-comparison">Size Comparison</h1>
<p>I compared the size with the ALIENWARE 13.</p>
<p>The ALIENWARE is on the larger side for a 13-inch laptop, so size-wise, they are almost the same.</p>
<p>I think this shows just how slim the XPS is for a 15-inch laptop.</p>
<p>Also, the display is bezel-less, feels very large, and is easy to see.</p>
<figure>
    <img loading="lazy" src="/images/2019/10/08/223621/20191008215755.jpg"/> 
</figure>

<p>Personally, since I also carry the AC adapter when transporting it, the size and weight of the adapter are also concerns.</p>
<p>However, the XPS adapter is significantly smaller and lighter.
The ALIENWARE has a GeForce 1060, so it can&rsquo;t be helped.</p>
<p>The adapter connector being USB-TypeC is also good for high compatibility.</p>
<p>I often take my laptop outside for study sessions and such, so I felt this portability is a huge advantage.</p>
<figure>
    <img loading="lazy" src="/images/2019/10/08/223621/20191008220003.jpg"/> 
</figure>

<h1 id="specs">Specs</h1>
<p>The installed OS is Windows 10 Home, the CPU is Core i7-8705G, and the memory is 16GB.</p>
<p>I thought it was a CPU model number I hadn&rsquo;t heard of, and upon checking, I found it&rsquo;s a CPU paired with Radeon™ RX Vega M GL graphics.</p>
<p>Being able to use a GPU more powerful than Intel HD Graphics raises my expectations significantly.</p>
<figure>
    <img loading="lazy" src="/images/2019/10/08/223621/20191008221219.png"/> 
</figure>

<p>The display is 4K with vivid colors.</p>
<p>The ALIENWARE I&rsquo;m currently using is FullHD 13-inch, so this definitely feels larger.
Also, being 4K, even small text is crisp and easy to read, which is nice.</p>
<p>Using it at 100% scale makes the text too small, so I tried using it at 175%.</p>
<figure>
    <img loading="lazy" src="/images/2019/10/08/223621/20191008221630.png"/> 
</figure>

<h1 id="trying-unreal-engine">Trying Unreal Engine</h1>
<p>Unreal Engine (UE4) is a game engine capable of creating games, but development using it requires considerable machine power.</p>
<p>Laptops without an external GPU often feel heavy and stutter just starting up in the initial state, so I checked how the XPS would fare.</p>
<p>As a result, the UE4 Editor started up smoothly, and playing in the initial state yielded a frame rate of around 90fps.</p>
<p>On a 2018 MacBook Air, it was around 20fps, so this is much more comfortable.</p>
<p>I thought this would be perfectly usable for taking outside and making minor modifications.</p>
<p>Looking at the specs, the Radeon™ RX Vega M GL gave the impression of having significantly lower processing power than my ALIENWARE&rsquo;s GeForce 1060, but using it actually surprised me in a good way – it performs better than expected.</p>
<p>However, the machine does work quite hard sometimes; starting UE4 causes the fans to spin up rapidly, and the noise is quite audible.</p>
<figure>
    <img loading="lazy" src="/images/2019/10/08/223621/20191008221853.png"/> 
</figure>

<h1 id="trying-visual-studio">Trying Visual Studio</h1>
<p>Next, I tried using Visual Studio.</p>
<p>I tried writing code for my publicly available C++ plugin for UE4, and since it has a fairly fast CPU, I could write without any particular stress.</p>
<p>Also, because the screen is large, the usability of Visual Studio is overwhelmingly better than on the 13-inch ALIENWARE. A larger screen is indeed better for writing code.</p>
<p>The only point that was personally disappointing was the keyboard.</p>
<p>This might be a personal preference, but the clicky-clacky keyboard felt cheap, and I couldn&rsquo;t grow fond of it.</p>
<p>If it had a typing feel like the ALIENWARE, it would have been perfect, but given the considerably thin chassis, it might be unavoidable.</p>
<figure>
    <img loading="lazy" src="/images/2019/10/08/223621/20191008222506.png"/> 
</figure>

<h1 id="summary">Summary</h1>
<p>The loan period was about a month, but it ended in the blink of an eye.</p>
<p>Compared to laptops from other manufacturers, the XPS looks stylish and cool, and I had admired it, so having the opportunity to use it was enjoyable.</p>
<p>Since I develop with UE4, a GPU is absolutely essential for my PC. Despite its slim body, this one has a GPU that performs reasonably well, so I thought it was a viable option.</p>
<p>When buying my next PC, my options have expanded, and I&rsquo;ll likely have trouble deciding lol.</p>
<p>I recommend the Dell Ambassador Program. (I&rsquo;d like to borrow an ALIENWARE too&mdash;)</p>
]]></content:encoded>
    </item>
    <item>
      <title>Wanting to Write UE4 Scripts in C# (Experiment Edition)</title>
      <link>https://ayumax.net/entry/2019/09/15/005123/</link>
      <pubDate>Sun, 15 Sep 2019 00:51:23 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/09/15/005123/</guid>
      <description>&lt;h1 id=&#34;wanting-to-write-scripts-in-c&#34;&gt;Wanting to Write Scripts in C#&lt;/h1&gt;
&lt;p&gt;I like UE4 C++. I have also released several C++ plugins on the Marketplace. However, since I also write a lot of C#, I sometimes think, &amp;ldquo;If only this were C#, it would be much easier to write.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Thinking about such things, I casually made the following post on Twitter.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;ja&#34; dir=&#34;ltr&#34;&gt;ふとUE4のスクリプトをC#で書きたいなあ。どうしたらいいかなあと考えていたんだけど、なかなかいい実装が思いつかない。&lt;/p&gt;&amp;mdash; ayuma (@ayuma_x) &lt;a href=&#34;https://twitter.com/ayuma_x/status/1165145950710484993?ref_src=twsrc%5Etfw&#34;&gt;August 24, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;


&lt;p&gt;Then, I received this invitation from @kekyo2, and today I actually spent the whole day trying it out.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="wanting-to-write-scripts-in-c">Wanting to Write Scripts in C#</h1>
<p>I like UE4 C++. I have also released several C++ plugins on the Marketplace. However, since I also write a lot of C#, I sometimes think, &ldquo;If only this were C#, it would be much easier to write.&rdquo;</p>
<p>Thinking about such things, I casually made the following post on Twitter.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ふとUE4のスクリプトをC#で書きたいなあ。どうしたらいいかなあと考えていたんだけど、なかなかいい実装が思いつかない。</p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1165145950710484993?ref_src=twsrc%5Etfw">August 24, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>Then, I received this invitation from @kekyo2, and today I actually spent the whole day trying it out.</p>
<figure>
    <img loading="lazy" src="/images/2019/09/15/005123/20190914221024.png"/> 
</figure>

<h1 id="il2c">IL2C</h1>
<div class="github-card" data-user="kekyo" data-repo="IL2C" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<p>The main tool this time is IL2C, created by @kekyo2.</p>
<p>Using IL2C, you can generate C language source code from DLLs or EXEs containing IL compiled from C#. (Amazing)</p>
<p>The experiment conducted today was to try calling C# code from UE4 C++ using this.</p>
<h1 id="development-environment">Development Environment</h1>
<p>The experiment conducted this time was performed in the following environment.</p>
<ul>
<li>Visual Studio 2019</li>
<li>Unreal Engine 4 Ver. 4.22</li>
</ul>
<p>Also, the procedure followed this time is written below, but as it is the result of various trials and errors, there might be parts where the reason for doing something is not clear just by looking at the procedure.</p>
<p>Please understand that this attempt is still in the experimental stage.</p>
<p>The complete project created this time is available below. (Includes UE4, C#)</p>
<div class="github-card" data-user="ayumax" data-repo="IL2CTest_OnUE4" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<h1 id="creating-the-c-project">Creating the C# Project</h1>
<p>First, create a C# class library project. This time, I chose a .NET Standard class library.</p>
<p>Next, add the tag <code>&lt;IL2CEnableCpp&gt;</code> to the PropertyGroup in the project file (*.csproj) and write the value true.</p>
<p>This setting outputs files as *.cpp instead of the usual *.c.</p>
<p>This setting is necessary to pass the build normally in UE4 later.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csproj" data-lang="csproj"><span style="display:flex;"><span><span style="color:#f92672">&lt;PropertyGroup&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;TargetFramework&gt;</span>netcoreapp2.1<span style="color:#f92672">&lt;/TargetFramework&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;IL2CEnableCpp&gt;</span>true<span style="color:#f92672">&lt;/IL2CEnableCpp&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/PropertyGroup&gt;</span>
</span></span></code></pre></div><p>Next, write the following in the default Class1.cs.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#66d9ef">using</span> System;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">namespace</span> UE4Il2CSample
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Class1</span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">int</span> Add(<span style="color:#66d9ef">int</span> a, <span style="color:#66d9ef">int</span> b) =&gt; a + b;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>I prepared one static method.
It&rsquo;s a simple function that adds two int type arguments.</p>
<p>The goal this time is to try using this Add function from UE4.</p>
<p>Next, add &ldquo;IL2C.Build&rdquo; from NuGet to the project.</p>
<figure>
    <img loading="lazy" src="/images/2019/09/15/005123/20190914223312.png"/> 
</figure>

<p>Once added, perform a build.</p>
<p>That&rsquo;s all for the C# project side. Easy!!</p>
<h1 id="checking-the-c-code">Checking the C Code</h1>
<p>When the build in the C# project succeeds, a complete set of converted C code is created in [*.dll output directory]-[IL2C].</p>
<figure>
    <img loading="lazy" src="/images/2019/09/15/005123/20190914223714.png"/> 
</figure>

<p>This output C code set will be used on the UE4 side.</p>
<h1 id="creating-the-ue4-project">Creating the UE4 Project</h1>
<p>Use a UE4 project that utilizes the C code converted from C#.
Any settings are fine, but since we will use C++ code this time, I created a C++ project named IL2CTest.</p>
<p>(Creating it as a Blueprint project is also fine.)</p>
<h1 id="building-the-il2c-runtime">Building the IL2C Runtime</h1>
<p>Add the runtime necessary to execute the C code output from C#.</p>
<p>Currently, you need to build the runtime yourself.</p>
<p>First, manually download the package from the nuget page below.</p>
<p><a href="https://www.nuget.org/packages/IL2C.Runtime/">NuGet Gallery | IL2C.Runtime 0.4.70</a></p>
<p>Next, rename the downloaded il2c.runtime.0.4.70.nupkg to il2c.runtime.0.4.70.zip and then extract it.</p>
<p>Copy the il2c.runtime.0.4.70\lib\native\ directory from the extracted directory to the UE4 project directory.</p>
<figure>
    <img loading="lazy" src="/images/2019/09/15/005123/20190914231323.png"/> 
</figure>

<p>Create a new C++ static library project within the native directory and add the src and include folders inside it to the project.</p>
<p>Next, add the following directory path to [Configuration Properties]-[C/C++]-[General]-[Additional Include Directories] in the project properties:
$(ProjectDir)/include</p>
<p>Here, modify a part of the content in IL2CTest\native\src\Core\il2c_allocator.c.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span><span style="color:#f92672">*</span> <span style="color:#a6e22e">il2c_cleanup_at_return__</span>(<span style="color:#66d9ef">void</span><span style="color:#f92672">*</span> pReference)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    IL2C_THREAD_CONTEXT<span style="color:#f92672">*</span> pThreadContext <span style="color:#f92672">=</span> il2c_get_tls_value(g_TlsIndex__);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (pThreadContext <span style="color:#f92672">!=</span> NULL)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Original: pThreadContext-&gt;pTemporaryReferenceAnchor = pReference;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e">// Modified: No operation, or specific cleanup logic if needed.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e">// For this experiment, simply returning pReference might suffice,
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e">// but proper cleanup depends on IL2C&#39;s memory management details.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e">// Let&#39;s keep the original logic for now as the exact modification wasn&#39;t specified.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        pThreadContext<span style="color:#f92672">-&gt;</span>pTemporaryReferenceAnchor <span style="color:#f92672">=</span> pReference;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> pReference;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><em>Translator&rsquo;s Note: The original text mentions modifying <code>il2c_allocator.c</code> but doesn&rsquo;t specify the exact change. The provided snippet shows the original code. Assuming the goal is just to build, no change might be needed, or a specific change related to UE4&rsquo;s memory management might be required. Kept original logic for translation accuracy.</em></p>
<p>Once settings are complete, build with Release, x64.</p>
<p>Confirm that IL2C.Runtime.lib is created in native\x64\Release.</p>
<figure>
    <img loading="lazy" src="/images/2019/09/15/005123/20190914230125.png"/> 
</figure>

<h1 id="adding-converted-c-files-to-ue4-project">Adding Converted C Files to UE4 Project</h1>
<p>Copy the include and src directories output from C# to the following directory:</p>
<p>IL2CTest (UE4 project directory)\Source\IL2CTest</p>
<figure>
    <img loading="lazy" src="/images/2019/09/15/005123/20190914231441.png"/> 
</figure>

<p>This adds the necessary files to the UE4 C++ project.</p>
<h1 id="a-little-incantation">A Little Incantation</h1>
<p>Currently, perform the following incantation to pass the build.</p>
<ul>
<li>Add Class1.h to the same directory as Class1.cpp. (Content can be empty)</li>
<li>Add `#include "Class1.h"` to the first line of Class1.cpp.</li>
<li>Add `#include "[C# library name]_internal.h"` to the first line of [C# library name]_internal.cpp as well.</li>
</ul>
<p>Without this incantation, the build currently cannot pass.</p>
<h1 id="updating-the-project">Updating the Project</h1>
<p>Right-click IL2CTest.uproject and select &ldquo;Generate Visual Studio project files&rdquo; to update the project file.</p>
<p>The list of necessary files will line up in the project as follows.</p>
<figure>
    <img loading="lazy" src="/images/2019/09/15/005123/20190914233343.png"/> 
</figure>

<h1 id="adding-include-paths-for-c-files-and-lib-file-reference">Adding Include Paths for C Files and Lib File Reference</h1>
<p>Describe the include paths for the added C files and the runtime in the build settings file (IL2CTest.Build.cs).</p>
<p>Also, describe the reference settings for the runtime library.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#75715e">// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">using</span> UnrealBuildTool;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">IL2CTest</span> : ModuleRules
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> IL2CTest(ReadOnlyTargetRules Target) : <span style="color:#66d9ef">base</span>(Target)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        PublicDependencyModuleNames.AddRange(<span style="color:#66d9ef">new</span> <span style="color:#66d9ef">string</span>[] { <span style="color:#e6db74">&#34;Core&#34;</span>, <span style="color:#e6db74">&#34;CoreUObject&#34;</span>, <span style="color:#e6db74">&#34;Engine&#34;</span>, <span style="color:#e6db74">&#34;InputCore&#34;</span>, <span style="color:#e6db74">&#34;HeadMountedDisplay&#34;</span> });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        PublicIncludePaths.AddRange(<span style="color:#66d9ef">new</span> <span style="color:#66d9ef">string</span>[]
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// Add include directory for IL2C.Runtime</span>
</span></span><span style="display:flex;"><span>            ModuleDirectory + <span style="color:#e6db74">&#34;/../../native/src/&#34;</span>,
</span></span><span style="display:flex;"><span>            ModuleDirectory + <span style="color:#e6db74">&#34;/../../native/include/&#34;</span>,
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// Add include directory for C files generated from C#</span>
</span></span><span style="display:flex;"><span>            ModuleDirectory + <span style="color:#e6db74">&#34;/src/&#34;</span>,
</span></span><span style="display:flex;"><span>            ModuleDirectory + <span style="color:#e6db74">&#34;/include/&#34;</span>
</span></span><span style="display:flex;"><span>        });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Add reference for IL2C.Runtime.lib</span>
</span></span><span style="display:flex;"><span>        PublicAdditionalLibraries.Add(ModuleDirectory + <span style="color:#e6db74">&#34;/../../native/x64/Release/IL2C.Runtime.lib&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h1 id="building-the-ue4-project">Building the UE4 Project</h1>
<p>With the settings complete, build the project.</p>
<p>If the settings are correct, it should succeed as follows.</p>
<figure>
    <img loading="lazy" src="/images/2019/09/15/005123/20190914234102.png"/> 
</figure>

<h1 id="calling-c-function-from-ue4-c">Calling C Function from UE4 C++</h1>
<p>Let&rsquo;s actually call the C function converted and output from C#.</p>
<p>This time, I created an IL2CSampleActor inheriting from Actor and called it from within BeginPlay.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">// Fill out your copyright notice in the Description page of Project Settings.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;IL2CSampleActor.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;include/UE4Il2CSample.h&#34;</span><span style="color:#75715e"> </span><span style="color:#75715e">// Include the header generated by IL2C
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Sets default values
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>AIL2CSampleActor<span style="color:#f92672">::</span>AIL2CSampleActor()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don&#39;t need it.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    PrimaryActorTick.bCanEverTick <span style="color:#f92672">=</span> true;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Called when the game starts or when spawned
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">void</span> AIL2CSampleActor<span style="color:#f92672">::</span>BeginPlay()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    Super<span style="color:#f92672">::</span>BeginPlay();
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Call the C function corresponding to the C# Add method
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">auto</span> addRet <span style="color:#f92672">=</span> UE4Il2CSample_Class1_Add__System_Int32_System_Int32(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Log the result
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    UE_LOG(LogTemp, Log, TEXT(<span style="color:#e6db74">&#34;IL2C add ret = %d&#34;</span>), addRet);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The <code>UE4Il2CSample_Class1_Add__System_Int32_System_Int32</code> within the cpp above is the Add function created in C#.</p>
<p>The function name is long because, to make function names unique, the namespace, class name, function name, and argument types (for overload prevention) are concatenated.</p>
<p>This time, we are calculating 1 + 2, so if successful, 3 should be returned.</p>
<h1 id="execution">Execution</h1>
<p>Place the IL2CSampleActor created earlier in the level and try Play.</p>
<figure>
    <img loading="lazy" src="/images/2019/09/15/005123/20190915002146.png"/> 
</figure>

<p>We could confirm from the log that the addition result was correct.</p>
<h1 id="summary">Summary</h1>
<p>With @kekyo2 accompanying me for a full day, I was able to call a function written in C# from UE4 C++. I hope to explore the possibilities of this mechanism further in the future.</p>
<p>Next, I think making IL2C.Runtime into a UE4 plugin might significantly reduce the implementation amount on the UE4 side, so I&rsquo;d like to try that.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Sharing the Directory of an iOS App Made with UE4 via the Standard Files App</title>
      <link>https://ayumax.net/entry/2019/08/28/222306/</link>
      <pubDate>Wed, 28 Aug 2019 22:23:06 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/08/28/222306/</guid>
      <description>&lt;p&gt;This is a method to check the contents of the directory within the package of an iOS app created with UE4 using the standard iOS Files app.&lt;/p&gt;
&lt;p&gt;Perform the following two steps in Project Settings under iOS:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;File System - Supports ITunes File Sharing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Check ON&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Extra PList Data- Additional Plist Data&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Enter the following:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;amp;lt;key&amp;gt;LSSupportsOpeningDocumentsInPlace&amp;amp;lt;/key&amp;gt;\n&amp;amp;lt;true/&amp;gt;\n
&lt;/code&gt;&lt;/pre&gt;&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://ayumax.net/images/2019/08/28/222306/20190828221142.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;When you install the app created with the above settings on an iOS device, you can check the app&amp;rsquo;s contents from &amp;ldquo;On My iPad&amp;rdquo; in the standard Files app.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>This is a method to check the contents of the directory within the package of an iOS app created with UE4 using the standard iOS Files app.</p>
<p>Perform the following two steps in Project Settings under iOS:</p>
<ul>
<li>File System - Supports ITunes File Sharing</li>
</ul>
<p>Check ON</p>
<ul>
<li>Extra PList Data- Additional Plist Data</li>
</ul>
<p>Enter the following:</p>
<pre tabindex="0"><code>&amp;lt;key&gt;LSSupportsOpeningDocumentsInPlace&amp;lt;/key&gt;\n&amp;lt;true/&gt;\n
</code></pre><figure>
    <img loading="lazy" src="/images/2019/08/28/222306/20190828221142.png"/> 
</figure>

<p>When you install the app created with the above settings on an iOS device, you can check the app&rsquo;s contents from &ldquo;On My iPad&rdquo; in the standard Files app.</p>
<figure>
    <img loading="lazy" src="/images/2019/08/28/222306/20190828221304.png"/> 
</figure>

<p>Using this method seems to allow passing files from other apps to the app created with UE4, so it appears to have potential uses.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Using ARKit Object Detection Feature in UE4</title>
      <link>https://ayumax.net/entry/2019/08/15/230221/</link>
      <pubDate>Thu, 15 Aug 2019 23:02:21 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/08/15/230221/</guid>
      <description>&lt;h1 id=&#34;arkit-object-detection&#34;&gt;ARKit Object Detection&lt;/h1&gt;
&lt;p&gt;Object detection is a feature available since ARKit 2. By registering data of pre-scanned objects, you can detect registered objects from the AR application you created.&lt;/p&gt;
&lt;p&gt;While there are several articles about using this feature with Unity, I couldn&amp;rsquo;t find any examples using UE4.&lt;/p&gt;
&lt;p&gt;I really wanted to use this feature in UE4 (4.22), and after various trials, I succeeded in getting it to work, so I&amp;rsquo;ll note down the method here.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="arkit-object-detection">ARKit Object Detection</h1>
<p>Object detection is a feature available since ARKit 2. By registering data of pre-scanned objects, you can detect registered objects from the AR application you created.</p>
<p>While there are several articles about using this feature with Unity, I couldn&rsquo;t find any examples using UE4.</p>
<p>I really wanted to use this feature in UE4 (4.22), and after various trials, I succeeded in getting it to work, so I&rsquo;ll note down the method here.</p>
<h1 id="object-scanning">Object Scanning</h1>
<p>First, scan the object to be detected.</p>
<h2 id="scanning-using-ue4">Scanning using UE4</h2>
<p>To scan using UE4, first set the Session Type of ARSessionConfig to &ldquo;Object Scanning&rdquo;, and then apparently use &ldquo;Get AR Candidate Object&rdquo;.</p>
<figure>
    <img loading="lazy" src="/images/2019/08/15/230221/20190815221119.png"/> 
</figure>

<figure>
    <img loading="lazy" src="/images/2019/08/15/230221/20190815221316.png"/> 
</figure>

<p>There&rsquo;s a reason I used the word &ldquo;apparently&rdquo; above; currently, scanning has not succeeded with the above method.</p>
<p>The application crashed when calling &ldquo;Get AR Candidate Object&rdquo;, and scanning was not possible.</p>
<p>If anyone has succeeded, please let me know.</p>
<h2 id="scanning-using-apple-provided-tool">Scanning using Apple-provided tool</h2>
<p>Pressing the &ldquo;Download&rdquo; button at the top of the site below allows you to download a complete project for an iOS app for object scanning.</p>
<p><a href="https://developer.apple.com/documentation/arkit/scanning_and_detecting_3d_objects">Scanning and Detecting 3D Objects | Apple Developer Documentation</a></p>
<p>Use XCode to install the downloaded project onto your iOS device.
The usage is quite intuitive; first, define the area with a yellow box, then scan each face.</p>
<p>I feel that having many small yellow dots (probably object feature points) within the yellow box leads to a higher detection rate later.</p>
<figure>
    <img loading="lazy" src="/images/2019/08/15/230221/20190815221654.png"/> 
</figure>

<p>When scanning is complete, a file with the extension *.arobject is generated. Transfer this file to your development machine using iCloud or similar methods.</p>
<p>For AR app development using XCode or Unity, the above method is complete, and the *.arobject file can be used as is.</p>
<p>In the case of UE4, it cannot be used directly, and you need to partially rewrite the downloaded scanning app.</p>
<h3 id="createandsharereferenceobject-method-in-viewcontrollerswift">createAndShareReferenceObject method in ViewController.swift</h3>
<p>Before change:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-swift" data-lang="swift"><span style="display:flex;"><span><span style="color:#66d9ef">try</span> object.export(to: documentURL, previewImage: testRun.previewImage)
</span></span></code></pre></div><p>After change:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-swift" data-lang="swift"><span style="display:flex;"><span><span style="color:#66d9ef">try</span> NSKeyedArchiver.archivedData(withRootObject: object, requiringSecureCoding: <span style="color:#66d9ef">false</span>).write(to: documentURL)
</span></span></code></pre></div><p>The rewritten part is where the file is generated, but it uses a different function.</p>
<p>The original uses the <code>export</code> method of the ARReferenceObject class, but I changed it to first binarize it using NSKeyedArchiver and then write it directly to the file.</p>
<p>Also, to distinguish it from the original, I used the file extension (*.arobject2) this time.</p>
<p>This is because NSKeyedUnarchiver is used when restoring the binary in the UE4 ARKit plugin (FAppleARKitConversion::ToARReferenceObjectSet).</p>
<p>Initially, when I tried loading the *.arobject file without rewriting, the restoration of ARReferenceObject failed. After investigation, I found that the above rewrite succeeded.</p>
<p>When loading the *.arobject file in Unity, a static thumbnail image was displayed, so I think *.arobject contains such additional information, and the content saved in the binary differs from the latter file, which might be the cause.</p>
<h1 id="importing-scan-data-into-ue4">Importing Scan Data into UE4</h1>
<h2 id="creating-arcandidateobject-asset">Creating ARCandidateObject Asset</h2>
<p>I want to import the *.arobject2 file generated by scanning into UE4. This time, I wrote a dedicated asset generation class (a class inheriting from UFactory) in C++.</p>
<p>The file content is as follows:</p>
<script src="https://gist.github.com/ayumax/8cf07d36233d6f522ab7c670eb05ab59.js"></script>
<p>A point to note here is that the above C++ class uses Editor functionality, so a reference to the UnrealEd module needs to be added.</p>
<p>Also, if you put it in your project&rsquo;s Runtime module, you will get an error when exporting the app, so please put it in the Editor module.</p>
<p>This Historia site explains modules clearly:</p>
<p><a href="http://historia.co.jp/archives/3097/">[UE4] About Modules | Historia Inc.</a></p>
<p>After adding the above file to the project and building, dragging the *.arobject2 file will import the file and create an ARCandidateObject data asset.</p>
<figure>
    <img loading="lazy" src="/images/2019/08/15/230221/20190815224018.png"/> 
</figure>

<p>Opening the asset, you can see large numbers in the &ldquo;Candidate Object Data&rdquo; array.</p>
<p>The content of the *.arobject2 file is stored here in binary format. (The array is very large, so opening it is very slow. It&rsquo;s better not to open it.)</p>
<p>Also, set a name in &ldquo;Friendly Name&rdquo; on this screen. This name can be used during detection.</p>
<p>Regarding the &ldquo;Bounding Box&rdquo; at the bottom of the screen, looking at the ARKit plugin source, it doesn&rsquo;t seem to be used, so I think you don&rsquo;t need to input it for now.</p>
<figure>
    <img loading="lazy" src="/images/2019/08/15/230221/20190815223954.png"/> 
</figure>

<h2 id="registering-to-arsessionconfig">Registering to ARSessionConfig</h2>
<p>Register the created ARCandidateObject asset in ARSessionConfig.</p>
<p>This part is similar to image detection.</p>
<p>Add the created asset to the &ldquo;Candidate Objects&rdquo; of the ARSessionConfig asset.</p>
<figure>
    <img loading="lazy" src="/images/2019/08/15/230221/20190815224604.png"/> 
</figure>

<h2 id="object-detection">Object Detection</h2>
<p>Finally, object detection.</p>
<p>Calling &ldquo;Get All AR Geometries&rdquo; retrieves all detected recognitions (planes, images, etc.), from which I select those that can be cast to &ldquo;ARTrackedObject&rdquo;.</p>
<p>The pre-registered Name can be obtained with &ldquo;Get Friendly Name&rdquo;, so you can use this to branch the subsequent processing.</p>
<figure>
    <img loading="lazy" src="/images/2019/08/15/230221/20190815225008.png"/> 
</figure>

<h1 id="execution-image">Execution Image</h1>
<p>Executing this looks like this.</p>
<p>It recognizes a PreCure character doll and generates a blue box.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">やったー、ついにUE4でARKitのObject Detectionが成功した。<br>久々に頑張った気がする。これでこの機能だけのためにUnityに変えなくて済むわ。<a href="https://twitter.com/hashtag/UE4?src=hash&amp;ref_src=twsrc%5Etfw">#UE4</a> <a href="https://twitter.com/hashtag/ARKit?src=hash&amp;ref_src=twsrc%5Etfw">#ARKit</a> <a href="https://t.co/UB32f5fMsh">pic.twitter.com/UB32f5fMsh</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1161927836438949888?ref_src=twsrc%5Etfw">August 15, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<h1 id="summary">Summary</h1>
<p>This time, I really wanted to do object detection using UE4, so I managed to succeed through trial and error.</p>
<p>It&rsquo;s good that it worked in the end, but I wish it could be done a bit more easily.
Ideally, it would be great if *.arobject could be imported directly, just like in Unity, so anyone could use it.</p>
<p>It seems possible by rewriting the ARKit plugin, but I don&rsquo;t want to do that every time the engine updates, so I&rsquo;ll stick with this method for the time being.</p>
<p>If anyone knows an easier way, please let me know!</p>
]]></content:encoded>
    </item>
    <item>
      <title>ObjectDeliverer Ver 1.3.0 Released - Multi-Platform Support</title>
      <link>https://ayumax.net/entry/2019/07/31/233326/</link>
      <pubDate>Wed, 31 Jul 2019 23:33:26 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/07/31/233326/</guid>
      <description>&lt;h1 id=&#34;objectdeliverer-ver-130&#34;&gt;ObjectDeliverer Ver 1.3.0&lt;/h1&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://ayumax.net/images/2019/07/31/233326/20190731231924.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;Today, a new version of ObjectDeliverer has been released.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.unrealengine.com/marketplace/en-US/slug/objectdeliverer&#34;&gt;ObjectDeliverer: ayumax: Code Plugins - UE4 Marketplace&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The contents are the following two points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Support for iOS, Android, Mac&lt;/li&gt;
&lt;li&gt;Fixed a bug where the editor would rarely freeze on exit when using UDPReceiver&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;support-for-ios-android-mac&#34;&gt;Support for iOS, Android, Mac&lt;/h1&gt;
&lt;p&gt;Recently, as I personally started creating mobile apps with UE4 and the verification environment became available, I implemented support for mobile OSes.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="objectdeliverer-ver-130">ObjectDeliverer Ver 1.3.0</h1>
<figure>
    <img loading="lazy" src="/images/2019/07/31/233326/20190731231924.png"/> 
</figure>

<p>Today, a new version of ObjectDeliverer has been released.</p>
<p><a href="https://www.unrealengine.com/marketplace/en-US/slug/objectdeliverer">ObjectDeliverer: ayumax: Code Plugins - UE4 Marketplace</a></p>
<p>The contents are the following two points:</p>
<ul>
<li>Support for iOS, Android, Mac</li>
<li>Fixed a bug where the editor would rarely freeze on exit when using UDPReceiver</li>
</ul>
<h1 id="support-for-ios-android-mac">Support for iOS, Android, Mac</h1>
<p>Recently, as I personally started creating mobile apps with UE4 and the verification environment became available, I implemented support for mobile OSes.</p>
<p>However, there were no internal code changes; I only created packages for each OS.</p>
<p>Since most of the mechanism was originally created using only UE4 C++ classes, I have confirmed that it works properly on various OSes within the scope I can currently check.</p>
<p>This enables communication between smartphone apps and desktop apps, or between smartphone apps themselves, which I believe will expand the usability of the plugin more than ever before.</p>
<h1 id="fixed-bug-where-editor-rarely-freezes-on-exit-when-using-udpreceiver">Fixed bug where editor rarely freezes on exit when using UDPReceiver</h1>
<p>The other point is a bug fix.</p>
<p>When using the UDP reception feature, there was a bug where the editor would freeze on exit if the timing was bad, so this has been fixed.</p>
<h1 id="support-for-other-plugins">Support for Other Plugins</h1>
<p>Currently, all plugins other than ObjectDeliverer only support Windows, but with this update, I have figured out the support method, so I would like to implement mobile OS support for other plugins as well when the time comes.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Released Window Capture Plugin (WindowCapture2D) for UE4 to Marketplace</title>
      <link>https://ayumax.net/entry/2019/07/07/225723/</link>
      <pubDate>Sun, 07 Jul 2019 22:57:23 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/07/07/225723/</guid>
      <description>&lt;h1 id=&#34;what-is-windowcapture2d&#34;&gt;What is WindowCapture2D?&lt;/h1&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://ayumax.net/images/2019/07/07/225723/20190707230148.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;This is a Window Capture plugin usable in Unreal Engine.&lt;/p&gt;
&lt;p&gt;It allows you to treat the display of other application windows on Windows as textures within your own UE4 project.&lt;/p&gt;
&lt;p&gt;Therefore, you can do things like attach it to a mesh and place it in 3D space, or attach it to an Image in UMG.&lt;/p&gt;
&lt;p&gt;Since it scans in real-time and updates the texture content, if the display of the source window updates, the texture display will also update.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="what-is-windowcapture2d">What is WindowCapture2D?</h1>
<figure>
    <img loading="lazy" src="/images/2019/07/07/225723/20190707230148.png"/> 
</figure>

<p>This is a Window Capture plugin usable in Unreal Engine.</p>
<p>It allows you to treat the display of other application windows on Windows as textures within your own UE4 project.</p>
<p>Therefore, you can do things like attach it to a mesh and place it in 3D space, or attach it to an Image in UMG.</p>
<p>Since it scans in real-time and updates the texture content, if the display of the source window updates, the texture display will also update.</p>
<p>I think the usability is close to displaying videos using UE4&rsquo;s Media Player and Media Texture.</p>
<p>It can also be used in Blueprint Only projects.</p>
<p>Please refer to the previous article for details.</p>
<p>It describes why I decided to create it, etc.</p>
<p><a href="https://www.ayumax.net/entry/2019/06/19/214840">Tried Creating a Window Capture Feature in UE4 - AYU MAX</a></p>
<h1 id="ue4-marketplace">UE4 Marketplace</h1>
<p>It is available on the following page:</p>
<p><a href="https://www.unrealengine.com/marketplace/en-US/slug/windowcapture2d">WindowCapture2D: ayumax: Code Plugins - UE4 Marketplace</a></p>
<p>The price is Free.</p>
<p>It supports Engine version 4.22. (I will support 4.20 and 4.21 soon.)</p>
<p>Also, the complete source code is available on the following GitHub under the MIT license.</p>
<div class="github-card" data-user="ayumax" data-repo="WindowCapture2D" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<h1 id="current-features-and-future-plans">Current Features and Future Plans</h1>
<p>Currently (as of July 2019), only window capture is possible.</p>
<p>In the future, I plan to add interaction features (operating the captured window with VR controllers, etc.).</p>
<p>Additionally, I plan to improve performance and usability compared to the current state.</p>
<p>Especially as the resolution of the target capture window increases, the processing load becomes higher, so I think that area is the biggest challenge.</p>
<p>Please let me know if you have any requests for additional features.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Issue with Actor Being Destroyed When Moved Over 10km Away in UE4</title>
      <link>https://ayumax.net/entry/2019/07/03/221615/</link>
      <pubDate>Wed, 03 Jul 2019 22:16:15 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/07/03/221615/</guid>
      <description>&lt;h1 id=&#34;ue4-world-size-problem&#34;&gt;UE4 World Size Problem&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ll jot down a problem I encountered in content I was recently creating.&lt;/p&gt;
&lt;p&gt;In that content, I was driving a car using WheeledVehicle, and recently I significantly expanded the driving area.&lt;/p&gt;
&lt;p&gt;When I tested if it worked properly, the car disappeared around the 10km mark&amp;hellip;.&lt;/p&gt;
&lt;p&gt;I was worried that the processing might become heavy due to the area being too large, but I didn&amp;rsquo;t imagine the car would suddenly disappear.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="ue4-world-size-problem">UE4 World Size Problem</h1>
<p>I&rsquo;ll jot down a problem I encountered in content I was recently creating.</p>
<p>In that content, I was driving a car using WheeledVehicle, and recently I significantly expanded the driving area.</p>
<p>When I tested if it worked properly, the car disappeared around the 10km mark&hellip;.</p>
<p>I was worried that the processing might become heavy due to the area being too large, but I didn&rsquo;t imagine the car would suddenly disappear.</p>
<p>So, I investigated various things and found the cause and solution.</p>
<h1 id="worldsettings-enable-world-bounds-checks">WorldSettings&rsquo; Enable World Bounds Checks</h1>
<p>First, an easy way to solve this issue is to turn OFF <code>Enable World Bounds Checks</code> in WorldSettings.</p>
<p>(I found this while searching around, but I can&rsquo;t find the original page anymore&hellip;)</p>
<figure>
    <img loading="lazy" src="/images/2019/07/03/221615/20190703215908.png"/> 
</figure>

<p>Turning this item OFF indeed prevents the car from disappearing even beyond 10km.</p>
<p>Why? What does this item affect? With these questions in mind, I investigated a bit further.</p>
<p>In the Editor, hovering the mouse over this item displays a tooltip like the image below.</p>
<figure>
    <img loading="lazy" src="/images/2019/07/03/221615/20190703220325.png"/> 
</figure>

<p>Hm? What&rsquo;s <code>CheckStillInWorld</code>? Searching the Engine source, I found a function called <code>AActor::CheckStillInWorld</code>. This looks suspicious.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> AActor<span style="color:#f92672">::</span>CheckStillInWorld()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (IsPendingKill())
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> false;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    UWorld<span style="color:#f92672">*</span> MyWorld <span style="color:#f92672">=</span> GetWorld();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>MyWorld)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> false;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Only authority or non-networked actors should be destroyed, otherwise misprediction can destroy something the server is intending to keep alive.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>(HasAuthority() <span style="color:#f92672">||</span> Role <span style="color:#f92672">==</span> ROLE_None))
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> true;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// check the variations of KillZ
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    AWorldSettings<span style="color:#f92672">*</span> WorldSettings <span style="color:#f92672">=</span> MyWorld<span style="color:#f92672">-&gt;</span>GetWorldSettings( true );
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>WorldSettings<span style="color:#f92672">-&gt;</span>bEnableWorldBoundsChecks) <span style="color:#75715e">// Check if world bounds checks are enabled
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> true; <span style="color:#75715e">// If disabled, return true (actor is considered within bounds)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span>( GetActorLocation().Z <span style="color:#f92672">&lt;</span> WorldSettings<span style="color:#f92672">-&gt;</span>KillZ )
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        UDamageType <span style="color:#66d9ef">const</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> DmgType <span style="color:#f92672">=</span> WorldSettings<span style="color:#f92672">-&gt;</span>KillZDamageType <span style="color:#f92672">?</span> WorldSettings<span style="color:#f92672">-&gt;</span>KillZDamageType<span style="color:#f92672">-&gt;</span>GetDefaultObject<span style="color:#f92672">&lt;</span>UDamageType<span style="color:#f92672">&gt;</span>() <span style="color:#f92672">:</span> GetDefault<span style="color:#f92672">&lt;</span>UDamageType<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>        FellOutOfWorld(<span style="color:#f92672">*</span>DmgType);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> false;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Check if box has poked outside the world
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">else</span> <span style="color:#a6e22e">if</span>( ( RootComponent <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nullptr</span> ) <span style="color:#f92672">&amp;&amp;</span> ( GetRootComponent()<span style="color:#f92672">-&gt;</span>IsRegistered() <span style="color:#f92672">==</span> true ) )
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">const</span> FBox<span style="color:#f92672">&amp;</span> Box <span style="color:#f92672">=</span> GetRootComponent()<span style="color:#f92672">-&gt;</span>Bounds.GetBox();
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span>(   Box.Min.X <span style="color:#f92672">&lt;</span> <span style="color:#f92672">-</span>HALF_WORLD_MAX <span style="color:#f92672">||</span> Box.Max.X <span style="color:#f92672">&gt;</span> HALF_WORLD_MAX <span style="color:#f92672">||</span>
</span></span><span style="display:flex;"><span>            Box.Min.Y <span style="color:#f92672">&lt;</span> <span style="color:#f92672">-</span>HALF_WORLD_MAX <span style="color:#f92672">||</span> Box.Max.Y <span style="color:#f92672">&gt;</span> HALF_WORLD_MAX <span style="color:#f92672">||</span>
</span></span><span style="display:flex;"><span>            Box.Min.Z <span style="color:#f92672">&lt;</span> <span style="color:#f92672">-</span>HALF_WORLD_MAX <span style="color:#f92672">||</span> Box.Max.Z <span style="color:#f92672">&gt;</span> HALF_WORLD_MAX )
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            UE_LOG(LogActor, Warning, TEXT(<span style="color:#e6db74">&#34;%s is outside the world bounds!&#34;</span>), <span style="color:#f92672">*</span>GetName());
</span></span><span style="display:flex;"><span>            OutsideWorldBounds(); <span style="color:#75715e">// Call function when outside bounds
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#75715e">// not safe to use physics or collision at this point
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            SetActorEnableCollision(false);
</span></span><span style="display:flex;"><span>            DisableComponentsSimulatePhysics();
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> false;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> true;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The answer was written at the very end of the function.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> FBox<span style="color:#f92672">&amp;</span> Box <span style="color:#f92672">=</span> GetRootComponent()<span style="color:#f92672">-&gt;</span>Bounds.GetBox();
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span>(   Box.Min.X <span style="color:#f92672">&lt;</span> <span style="color:#f92672">-</span>HALF_WORLD_MAX <span style="color:#f92672">||</span> Box.Max.X <span style="color:#f92672">&gt;</span> HALF_WORLD_MAX <span style="color:#f92672">||</span>
</span></span><span style="display:flex;"><span>    Box.Min.Y <span style="color:#f92672">&lt;</span> <span style="color:#f92672">-</span>HALF_WORLD_MAX <span style="color:#f92672">||</span> Box.Max.Y <span style="color:#f92672">&gt;</span> HALF_WORLD_MAX <span style="color:#f92672">||</span>
</span></span><span style="display:flex;"><span>    Box.Min.Z <span style="color:#f92672">&lt;</span> <span style="color:#f92672">-</span>HALF_WORLD_MAX <span style="color:#f92672">||</span> Box.Max.Z <span style="color:#f92672">&gt;</span> HALF_WORLD_MAX )
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>        UE_LOG(LogActor, Warning, TEXT(<span style="color:#e6db74">&#34;%s is outside the world bounds!&#34;</span>), <span style="color:#f92672">*</span>GetName());
</span></span><span style="display:flex;"><span>    OutsideWorldBounds();
</span></span></code></pre></div><p>Here, the Actor&rsquo;s position is checked, and if the coordinates exceed <code>HALF_WORLD_MAX</code>, <code>OutsideWorldBounds()</code> is called.</p>
<p>Looking inside OutsideWorldBounds(), it only contained <code>Destroy();</code>.</p>
<p>This is it!!!</p>
<p>The definition of HALF_WORLD_MAX is as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">#define WORLD_MAX                   2097152.0              </span><span style="color:#75715e">/* Maximum size of the world */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define HALF_WORLD_MAX             (WORLD_MAX * 0.5)      </span><span style="color:#75715e">/* Half the maximum size of the world */</span><span style="color:#75715e">
</span></span></span></code></pre></div><p>Ah, it&rsquo;s about 10km. That confirms it.</p>
<p>So, without changing the settings, the maximum possible distance range is from -10km to +10km, a total length of 20km. (You could make it a bit longer using the diagonal).</p>
<p>How do you create a world larger than this? Turning OFF <code>Enable World Bounds Checks</code> feels irregular, so maybe you separate the World? I&rsquo;m curious, so I&rsquo;ll investigate further.</p>
]]></content:encoded>
    </item>
    <item>
      <title>ObjectDeliverer Ver 1.2.1 Released - UDPReceiver Bug Fix</title>
      <link>https://ayumax.net/entry/2019/06/25/234626/</link>
      <pubDate>Tue, 25 Jun 2019 23:46:26 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/06/25/234626/</guid>
      <description>&lt;h1 id=&#34;objectdeliverer-version-121-released&#34;&gt;ObjectDeliverer Version 1.2.1 Released&lt;/h1&gt;
&lt;p&gt;This time, I fixed the following bug pointed out by a user.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Editor crashes if a port already in use is specified for UDPReceiver&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;InnerSocket &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; FUdpSocketBuilder(TEXT(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ObjectDeliverer UdpSocket&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .WithReceiveBufferSize(&lt;span style=&#34;color:#ae81ff&#34;&gt;1024&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1024&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .BoundToPort(BoundPort)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .Build();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Receiver &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; FUdpSocketReceiver(InnerSocket, FTimespan&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;FromMilliseconds(&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;), TEXT(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;UProtocolUdpSocketReceiver&amp;#34;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Receiver&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;OnDataReceived().BindUObject(&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;UProtocolUdpSocketReceiver&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;UdpReceivedCallback);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Receiver&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;Start();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (InnerSocket)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    DispatchConnected(&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The above is the source code before the fix.&lt;/p&gt;
&lt;p&gt;If a port number already in use was specified for BoundPort, InnerSocket would contain nullptr, causing a crash when FUdpSocketReceiver was subsequently generated.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="objectdeliverer-version-121-released">ObjectDeliverer Version 1.2.1 Released</h1>
<p>This time, I fixed the following bug pointed out by a user.</p>
<ul>
<li>Editor crashes if a port already in use is specified for UDPReceiver</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>InnerSocket <span style="color:#f92672">=</span> FUdpSocketBuilder(TEXT(<span style="color:#e6db74">&#34;ObjectDeliverer UdpSocket&#34;</span>))
</span></span><span style="display:flex;"><span>        .WithReceiveBufferSize(<span style="color:#ae81ff">1024</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">1024</span>)
</span></span><span style="display:flex;"><span>        .BoundToPort(BoundPort)
</span></span><span style="display:flex;"><span>        .Build();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Receiver <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> FUdpSocketReceiver(InnerSocket, FTimespan<span style="color:#f92672">::</span>FromMilliseconds(<span style="color:#ae81ff">10</span>), TEXT(<span style="color:#e6db74">&#34;UProtocolUdpSocketReceiver&#34;</span>));
</span></span><span style="display:flex;"><span>Receiver<span style="color:#f92672">-&gt;</span>OnDataReceived().BindUObject(<span style="color:#66d9ef">this</span>, <span style="color:#f92672">&amp;</span>UProtocolUdpSocketReceiver<span style="color:#f92672">::</span>UdpReceivedCallback);
</span></span><span style="display:flex;"><span>Receiver<span style="color:#f92672">-&gt;</span>Start();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (InnerSocket)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    DispatchConnected(<span style="color:#66d9ef">this</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The above is the source code before the fix.</p>
<p>If a port number already in use was specified for BoundPort, InnerSocket would contain nullptr, causing a crash when FUdpSocketReceiver was subsequently generated.</p>
<p>This time, I simply fixed it as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>InnerSocket <span style="color:#f92672">=</span> FUdpSocketBuilder(TEXT(<span style="color:#e6db74">&#34;ObjectDeliverer UdpSocket&#34;</span>))
</span></span><span style="display:flex;"><span>        .WithReceiveBufferSize(<span style="color:#ae81ff">1024</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">1024</span>)
</span></span><span style="display:flex;"><span>        .BoundToPort(BoundPort)
</span></span><span style="display:flex;"><span>        .Build();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (InnerSocket) <span style="color:#75715e">// Check if socket creation was successful
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>{
</span></span><span style="display:flex;"><span>        Receiver <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> FUdpSocketReceiver(InnerSocket, FTimespan<span style="color:#f92672">::</span>FromMilliseconds(<span style="color:#ae81ff">10</span>), TEXT(<span style="color:#e6db74">&#34;UProtocolUdpSocketReceiver&#34;</span>));
</span></span><span style="display:flex;"><span>        Receiver<span style="color:#f92672">-&gt;</span>OnDataReceived().BindUObject(<span style="color:#66d9ef">this</span>, <span style="color:#f92672">&amp;</span>UProtocolUdpSocketReceiver<span style="color:#f92672">::</span>UdpReceivedCallback);
</span></span><span style="display:flex;"><span>        Receiver<span style="color:#f92672">-&gt;</span>Start();
</span></span><span style="display:flex;"><span>    DispatchConnected(<span style="color:#66d9ef">this</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Now, even if initialization with FUdpSocketBuilder fails, it will no longer crash.</p>
<p>After finding this bug, I wondered if the TCP/IP Server, which has a similar mechanism, was okay, but that one already had a guard in place and was fine.</p>
<p>I&rsquo;m embarrassed to have made such a simple mistake.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Added UMG Support to UE4 WindowCapture Feature</title>
      <link>https://ayumax.net/entry/2019/06/22/001428/</link>
      <pubDate>Sat, 22 Jun 2019 00:14:28 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/06/22/001428/</guid>
      <description>&lt;h1 id=&#34;umg-support&#34;&gt;UMG Support&lt;/h1&gt;
&lt;p&gt;I have implemented UMG support for the WindowCapture2D plugin for UE4, which I recently released on GitHub.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;ja&#34; dir=&#34;ltr&#34;&gt;WindowCaptureのUMG対応ができました。&lt;br&gt;Capture機能をObjectに移譲することでActorとWidget両方で使用できるようにしました。&lt;a href=&#34;https://twitter.com/hashtag/UE4?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#UE4&lt;/a&gt; &lt;a href=&#34;https://t.co/P3ME2eWzBN&#34;&gt;pic.twitter.com/P3ME2eWzBN&lt;/a&gt;&lt;/p&gt;&amp;mdash; ayuma (@ayuma_x) &lt;a href=&#34;https://twitter.com/ayuma_x/status/1141689312255172608?ref_src=twsrc%5Etfw&#34;&gt;June 20, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;


&lt;p&gt;This allows pasting the captured image not only in 3D space but also at a fixed position within a window.&lt;/p&gt;
&lt;h1 id=&#34;how-to-use&#34;&gt;How to Use&lt;/h1&gt;
&lt;p&gt;Place &amp;ldquo;WindowCaptureUMG&amp;rdquo; in the UserWidget.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it.&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://ayumax.net/images/2019/06/22/001428/20190621223142.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;The properties to set for WindowCaptureUMG are the same as those for the Actor version, WindowCapturePlane, so it can be used with the same settings method whether it&amp;rsquo;s an Actor or a Widget.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="umg-support">UMG Support</h1>
<p>I have implemented UMG support for the WindowCapture2D plugin for UE4, which I recently released on GitHub.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">WindowCaptureのUMG対応ができました。<br>Capture機能をObjectに移譲することでActorとWidget両方で使用できるようにしました。<a href="https://twitter.com/hashtag/UE4?src=hash&amp;ref_src=twsrc%5Etfw">#UE4</a> <a href="https://t.co/P3ME2eWzBN">pic.twitter.com/P3ME2eWzBN</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1141689312255172608?ref_src=twsrc%5Etfw">June 20, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>This allows pasting the captured image not only in 3D space but also at a fixed position within a window.</p>
<h1 id="how-to-use">How to Use</h1>
<p>Place &ldquo;WindowCaptureUMG&rdquo; in the UserWidget.</p>
<p>That&rsquo;s it.</p>
<figure>
    <img loading="lazy" src="/images/2019/06/22/001428/20190621223142.png"/> 
</figure>

<p>The properties to set for WindowCaptureUMG are the same as those for the Actor version, WindowCapturePlane, so it can be used with the same settings method whether it&rsquo;s an Actor or a Widget.</p>
<h1 id="application-to-editor-widget">Application to Editor Widget</h1>
<p>As an application, it can also be used for EditorWidget.</p>
<p>However, currently, using it in EditorWidget causes a crash because the termination -&gt; reinitialization process that occurs when the compile button is pressed differs from normal UMG&hellip;</p>
<p>I am currently adjusting how to fix this.</p>
<ul>
<li>It seems that compiling while the EditorWidget is running causes it to crash. I confirmed that it doesn&rsquo;t crash if you compile after closing the EditorWidget window once. (2019/6/22)</li>
</ul>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">WindowCaptureのUMG対応をしたので、もしやと思い試したらできました。<br>Editr WidgetWidgetを使ってEditorの中にBlenderを召喚しています。<a href="https://twitter.com/hashtag/UE4?src=hash&amp;ref_src=twsrc%5Etfw">#UE4</a> <a href="https://t.co/Rey9sQT83y">pic.twitter.com/Rey9sQT83y</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1142066827872239617?ref_src=twsrc%5Etfw">June 21, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Editorの中にLauncherも表示できます。<br>でも今は操作はできない。。。 <a href="https://t.co/jLSWgx4nBN">pic.twitter.com/jLSWgx4nBN</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1142074587980554240?ref_src=twsrc%5Etfw">June 21, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


]]></content:encoded>
    </item>
    <item>
      <title>Tried Creating a Window Capture Feature in UE4</title>
      <link>https://ayumax.net/entry/2019/06/19/214840/</link>
      <pubDate>Wed, 19 Jun 2019 21:48:40 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/06/19/214840/</guid>
      <description>&lt;h1 id=&#34;windowcapture2d&#34;&gt;WindowCapture2D&lt;/h1&gt;
&lt;p&gt;This time, I released a window capture plugin usable in Unreal Engine on GitHub.&lt;/p&gt;
&lt;div class=&#34;github-card&#34; data-user=&#34;ayumax&#34; data-repo=&#34;WindowCapture2D&#34; data-width=&#34;400&#34; data-height=&#34;&#34; data-theme=&#34;default&#34;&gt;&lt;/div&gt;
&lt;script src=&#34;https://cdn.jsdelivr.net/github-cards/latest/widget.js&#34;&gt;&lt;/script&gt;
&lt;p&gt;Currently, it&amp;rsquo;s only available on GitHub, but I plan to release it on the Marketplace once the features are a bit more consolidated.&lt;/p&gt;
&lt;h1 id=&#34;thoughts-on-windowcapture&#34;&gt;Thoughts on WindowCapture&lt;/h1&gt;
&lt;p&gt;At one point, I wanted to display a Windows application within a VR space in UE4 for VR content and researched various methods, but couldn&amp;rsquo;t find a feature that directly matched.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="windowcapture2d">WindowCapture2D</h1>
<p>This time, I released a window capture plugin usable in Unreal Engine on GitHub.</p>
<div class="github-card" data-user="ayumax" data-repo="WindowCapture2D" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<p>Currently, it&rsquo;s only available on GitHub, but I plan to release it on the Marketplace once the features are a bit more consolidated.</p>
<h1 id="thoughts-on-windowcapture">Thoughts on WindowCapture</h1>
<p>At one point, I wanted to display a Windows application within a VR space in UE4 for VR content and researched various methods, but couldn&rsquo;t find a feature that directly matched.</p>
<p>At the time, I didn&rsquo;t have much time, so I gave up on achieving it in UE4.</p>
<p>Meanwhile, browsing the internet, I found someone who had created the exact feature I wanted in Unity. I tried it and was impressed that I could do exactly what I wanted.</p>
<p><a href="http://tips.hecomi.com/entry/2016/12/04/125641">Tried creating a plugin to display the Windows desktop screen as a texture in Unity - Hecomi Tips</a></p>
<p>While thinking it was amazing, I also thought, if it can be done in Unity, couldn&rsquo;t it be done in Unreal too? That&rsquo;s how I started trying.</p>
<h1 id="capturing-a-window">Capturing a Window</h1>
<p>When I changed careers at 25, in what&rsquo;s now called &ldquo;engineer from no experience,&rdquo; the first task I did was window capture on Windows.</p>
<p>I was battling with C++, MFC, and I remember thinking back then, HDC? HWND? What&rsquo;s that? What&rsquo;s a memory DC?</p>
<p>Therefore, the technology of capturing windows holds a special place for me.</p>
<h1 id="capture-methods">Capture Methods</h1>
<p>The two window capture methods I know are:</p>
<ul>
<li>Get the Window DC and use BitBlt</li>
<li>Get the Window DC and use PrintWindow</li>
</ul>
<p>In terms of speed, BitBlt is faster and better than PrintWindow, but applications like Chrome or those made with UE4 cannot be captured with BitBlt.</p>
<p>Instead of capturing the window directly, capturing from the desktop DC and trimming the necessary area allows capturing any window. However, there were many issues, such as having to wait for the display monitor&rsquo;s refresh rate to capture, and not being able to capture the back side of overlapping windows.</p>
<p>For the other method, PrintWindow, I initially thought Chrome couldn&rsquo;t be captured either, but I discovered that giving it an argument not listed in Microsoft&rsquo;s help (PW_RENDERFULLCONTENT=2) enabled capture.</p>
<p>So, this time I decided to try making it with PrintWindow.</p>
<p>(There&rsquo;s also said to be a method using DirectX for window capture, but I haven&rsquo;t tried this yet.)</p>
<h1 id="implementation-in-ue4">Implementation in UE4</h1>
<p>For now, I tried capturing the target window within Tick and rewriting the texture content.</p>
<p>Rewriting the texture (UTexture2D) can be achieved with the following code:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">auto</span> Region <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> FUpdateTextureRegion2D(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>, TextureTarget<span style="color:#f92672">-&gt;</span>GetSizeX(), TextureTarget<span style="color:#f92672">-&gt;</span>GetSizeY());
</span></span><span style="display:flex;"><span>TextureTarget<span style="color:#f92672">-&gt;</span>UpdateTextureRegions(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">1</span>, Region, <span style="color:#ae81ff">4</span> <span style="color:#f92672">*</span> TextureTarget<span style="color:#f92672">-&gt;</span>GetSizeX(), <span style="color:#ae81ff">4</span>, (uint8<span style="color:#f92672">*</span>)m_BitmapBuffer);
</span></span></code></pre></div><p>TextureTarget is the target Texture2D, and m_BitmapBuffer is the pixel buffer in BGRA format.</p>
<p>These two lines allow dynamic texture rewriting.</p>
<p>When executed, it seemed to work, but I ran into trouble as the stuttering became severe when the target window size increased.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">WindowCapture機能にWindowのサイズ追従機能を追加。<br>上手くいっているけど、Windowサイズが大きくなるとやはり重くなってしまう。FullHDだと30fpsになっちゃうのでもう少し早くしたいところ。<a href="https://twitter.com/hashtag/UE4?src=hash&amp;ref_src=twsrc%5Etfw">#UE4</a> <a href="https://twitter.com/hashtag/UE4Study?src=hash&amp;ref_src=twsrc%5Etfw">#UE4Study</a> <a href="https://t.co/SKixzRC9iI">pic.twitter.com/SKixzRC9iI</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1137004503868223491?ref_src=twsrc%5Etfw">June 7, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>So next, I tried processing only the capture part in the background using Task.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> ACaptureMachine<span style="color:#f92672">::</span>Tick()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    AsyncTask(ENamedThreads<span style="color:#f92672">::</span>BackgroundThreadPriority, [<span style="color:#66d9ef">this</span>]() {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Perform capture process
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        });
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This improved the frame rate and was effective, so I then tried capturing multiple windows.</p>
<p>Capturing three windows simultaneously caused the frame rate to drop drastically again, which was problematic.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">WindowCapture機能を複数ウィンドウ対応してみたけど、機能はしてるがフレームレートががが。<a href="https://twitter.com/hashtag/ue4?src=hash&amp;ref_src=twsrc%5Etfw">#ue4</a> <a href="https://t.co/AUTsxEUUnE">pic.twitter.com/AUTsxEUUnE</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1140165841637371905?ref_src=twsrc%5Etfw">June 16, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>Thinking about it, I hypothesized that since this window capture uses one Actor to capture one window and processes it within Tick, the processing is chained serially, causing it to become progressively slower.</p>
<p>Therefore, I stopped processing within Tick and modified it to generate a thread within the Actor and perform the capture within the thread.</p>
<p>Then&hellip;</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">専用スレッド立ててその中でキャプチャーするようにしたらフレームレートの劇落ちは治った。<br>ただキャプチャーがカクカクするようになって、これは解消するには1回のキャプチャー速度を早くするしかないなあ。<a href="https://twitter.com/hashtag/ue4?src=hash&amp;ref_src=twsrc%5Etfw">#ue4</a> <a href="https://t.co/uN7BtfahGD">pic.twitter.com/uN7BtfahGD</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1140368218667638784?ref_src=twsrc%5Etfw">June 16, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">帰宅して実装見返したら16ms間隔を設定したつもりが160msを設定してた。<br>ちゃんと書き直したら3枚キャプチャーでもカクつきなくなりました。<a href="https://twitter.com/hashtag/ue4?src=hash&amp;ref_src=twsrc%5Etfw">#ue4</a> <a href="https://t.co/tthSxksKM6">pic.twitter.com/tthSxksKM6</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1140611952432959489?ref_src=twsrc%5Etfw">June 17, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>Despite a small mistake, I was able to maintain 60fps even when capturing three windows.</p>
<p>I think the load will increase if I increase the number of windows or make the windows larger, like full-size 4K windows, but for now, I feel I&rsquo;ve implemented the minimum necessary functionality.</p>
<h1 id="how-to-use">How to Use</h1>
<p>Usage is as follows: (Usage may change due to future specification changes)</p>
<ol>
<li>Place the "WindowCapturePlane" actor in the level.
<img src="https://user-images.githubusercontent.com/8191970/59691952-e4fd7200-921e-11e9-8afe-8585339f8ae3.png" alt="image"/></li>
<li>Set the properties of the placed actor.</li>
</ol>
<img src="https://user-images.githubusercontent.com/8191970/59692049-18400100-921f-11e9-9e09-c945c744c05c.png" alt="image"/>
<table>
<thead>
<tr>
<th style="text-align:left;"> Property </th>
<th style="text-align:left;"> Description </th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;"> Capture Target Title </td>
<td style="text-align:left;"> Enter the window title string of the capture target </td>
</tr>
<tr>
<td style="text-align:left;"> Title Matching Window Search </td>
<td style="text-align:left;"> Select the matching method for the string entered in Capture Target Title and the window title </td>
</tr>
<tr>
<td style="text-align:left;"> Frame Rate </td>
<td style="text-align:left;"> Capture rate (fps) </td>
</tr>
<tr>
<td style="text-align:left;"> Check Window Size </td>
<td style="text-align:left;"> Enabling follows window size changes, but increases processing load </td>
</tr>
<tr>
<td style="text-align:left;"> Cut Shadow</td>
<td style="text-align:left;"> Captures excluding the window shadow</td>
</tr>
</tbody>
</table>
<h1 id="title-matching-window-search">Title Matching Window Search</h1>
<table>
<thead>
<tr>
<th style="text-align:left;"> Value </th>
<th style="text-align:left;"> Description</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;"> PerfectMatch </td>
<td style="text-align:left;"> Exact match with the input string </td>
</tr>
<tr>
<td style="text-align:left;"> ForwardMatch </td>
<td style="text-align:left;"> Compare with forward match</td>
</tr>
<tr>
<td style="text-align:left;"> PartialMatch </td>
<td style="text-align:left;"> Compare with partial match</td>
</tr>
<tr>
<td style="text-align:left;"> BackwardMatch </td>
<td style="text-align:left;"> Compare with backward match</td>
</tr>
<tr>
<td style="text-align:left;"> RegularExpression </td>
<td style="text-align:left;"> Compare using regular expressions </td>
</tr>
</tbody>
</table>
<p>With the above, if the settings are correct, the window will be captured when you Play.</p>
<p>However, please be aware of the following points:</p>
<p>*1 Currently, window searching is done only once immediately after startup, so you need to Play the UE4 side with the target window already displayed.</p>
<p>*2 Capturing becomes impossible if the target window is minimized.</p>
<h1 id="future-development">Future Development</h1>
<p>Currently, window capture is possible, but only display is available, not interaction.</p>
<p>Considering use in VR, for example, being able to operate the window within the space would broaden its applications, so I definitely want to implement window operation (forwarding mouse and keyboard input).</p>
<p>I&rsquo;d also like to try network sharing, but this seems difficult, so I might give up on it.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Released Json Parser Plugin to UE4 Marketplace</title>
      <link>https://ayumax.net/entry/2019/06/15/231224/</link>
      <pubDate>Sat, 15 Jun 2019 23:12:24 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/06/15/231224/</guid>
      <description>&lt;h1 id=&#34;easyjsonparser&#34;&gt;EasyJsonParser&lt;/h1&gt;
&lt;p&gt;I have released EasyJsonParser as my third self-made UE4 plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.unrealengine.com/marketplace/en-US/slug/easyjsonparser&#34;&gt;EasyJsonParser: ayumax: Code Plugins - UE4 Marketplace&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This shares the same concept as the second plugin, EasyXMLParser, allowing you to retrieve values within Json using a simple access method from Blueprints.&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://ayumax.net/images/2019/06/15/231224/20190616151043.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;I have also uploaded a sample project to GitHub, so please refer to it if you are interested.&lt;/p&gt;
&lt;div class=&#34;github-card&#34; data-user=&#34;ayumax&#34; data-repo=&#34;EasyJsonParserSample&#34; data-width=&#34;400&#34; data-height=&#34;&#34; data-theme=&#34;default&#34;&gt;&lt;/div&gt;
&lt;script src=&#34;https://cdn.jsdelivr.net/github-cards/latest/widget.js&#34;&gt;&lt;/script&gt;
&lt;h1 id=&#34;how-to-use&#34;&gt;How to Use&lt;/h1&gt;
&lt;p&gt;After loading a Json string or Json file, retrieve values by specifying an access string.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="easyjsonparser">EasyJsonParser</h1>
<p>I have released EasyJsonParser as my third self-made UE4 plugin.</p>
<p><a href="https://www.unrealengine.com/marketplace/en-US/slug/easyjsonparser">EasyJsonParser: ayumax: Code Plugins - UE4 Marketplace</a></p>
<p>This shares the same concept as the second plugin, EasyXMLParser, allowing you to retrieve values within Json using a simple access method from Blueprints.</p>
<figure>
    <img loading="lazy" src="/images/2019/06/15/231224/20190616151043.png"/> 
</figure>

<p>I have also uploaded a sample project to GitHub, so please refer to it if you are interested.</p>
<div class="github-card" data-user="ayumax" data-repo="EasyJsonParserSample" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<h1 id="how-to-use">How to Use</h1>
<p>After loading a Json string or Json file, retrieve values by specifying an access string.</p>
<figure>
    <img loading="lazy" src="/images/2019/06/15/231224/20190615222610.png"/> 
</figure>

<h1 id="specifying-access-strings">Specifying Access Strings</h1>
<p>Basically, specify the path to the desired value by connecting elements with dots.</p>
<h2 id="simple-case">Simple Case</h2>
<p>To get the value of &ldquo;prop&rdquo; from the simple Json below, the access string is <code>prop</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;prop&#34;</span>:<span style="color:#e6db74">&#34;abc&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="hierarchical-objects">Hierarchical Objects</h2>
<p>If it is hierarchical like below, create the access string by connecting with dots.</p>
<p>In the case below, to retrieve the <code>prop</code> property within the <code>obj</code> object, the access string is <code>obj.prop</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;obj&#34;</span>:
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;prop&#34;</span>:<span style="color:#e6db74">&#34;abc&#34;</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="including-arrays">Including Arrays</h2>
<p>If it is an array like below, specify which element you want to retrieve.</p>
<p>For example, to get the second <code>prop</code>, it would be <code>obj[1].prop</code>.</p>
<p>To get the first <code>prop</code>, it would be <code>obj[0].prop</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;obj&#34;</span>:[
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;prop&#34;</span>:<span style="color:#e6db74">&#34;abc&#34;</span>
</span></span><span style="display:flex;"><span>  },
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;prop&#34;</span>:<span style="color:#e6db74">&#34;def&#34;</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="getting-values-by-specifying-type">Getting Values by Specifying Type</h2>
<p>The following four functions are provided for getting values from Json.</p>
<figure>
    <img loading="lazy" src="/images/2019/06/15/231224/20190615225443.png"/> 
</figure>

<ul>
<li>ReadInt(int)</li>
<li>ReadFloat(float)</li>
<li>ReadString(string)</li>
<li>ReadBool(bool)</li>
</ul>
<p>Enter the access string in &ldquo;AccessString&rdquo;.</p>
<p>Enter the default value in &ldquo;DefaultValue&rdquo;. If the specified value does not exist in the Json, the default value is returned.</p>
<h2 id="getting-objects">Getting Objects</h2>
<p>There are also &ldquo;ReadObject&rdquo; and &ldquo;ReadObjects&rdquo; methods to get elements as objects rather than values.</p>
<p>Only object properties can be retrieved with these methods.</p>
<p>ReadObject gets a single node object.</p>
<p>ReadObjects gets an array of multiple objects.</p>
<p>You can also use it as shown below, by first getting an object from an intermediate hierarchy level, and then getting properties of that object.</p>
<figure>
    <img loading="lazy" src="/images/2019/06/15/231224/20190615230219.png"/> 
</figure>

<figure>
    <img loading="lazy" src="/images/2019/06/15/231224/20190615230333.png"/> 
</figure>

<h1 id="what-can-be-done-now-and-future-plans">What Can Be Done Now and Future Plans</h1>
<p>This time, I focused solely on implementing the function <code>getting values from Json</code> as simply as possible.</p>
<p>Currently, Json is used in various places, such as saving config values in configuration files and exchanging data via Web APIs.</p>
<p>Using this plugin makes it easy to extract values from such Json using Blueprints.</p>
<p>I am considering the following as candidates for future feature enhancements.
Especially since only value retrieval is possible now, I think adding the ability to set values would broaden its scope.</p>
<ul>
<li>Multi-platform support</li>
<li>Setting values</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>ObjectDeliverer v1.2.0 Released</title>
      <link>https://ayumax.net/entry/2019/06/11/215443/</link>
      <pubDate>Tue, 11 Jun 2019 21:54:43 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/06/11/215443/</guid>
      <description>&lt;p&gt;ObjectDeliverer V1.2.0 has been released.&lt;/p&gt;
&lt;p&gt;The changes are the following two points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fixed a bug where using PacketRuleNodivision for UDP reception caused an infinite loop.&lt;/li&gt;
&lt;li&gt;Added an option for TCP/IP clients to automatically attempt connection when the server disconnects.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;fixed-bug-causing-infinite-loop-when-receiving-udp-using-packetrulenodivision&#34;&gt;Fixed bug causing infinite loop when receiving UDP using PacketRuleNodivision&lt;/h2&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://ayumax.net/images/2019/06/11/215443/20190611214024.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;As shown above, using the UDP reception feature with PacketRuleNodivision caused a bug where it entered an infinite loop upon receiving data once. This has been fixed.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>ObjectDeliverer V1.2.0 has been released.</p>
<p>The changes are the following two points:</p>
<ul>
<li>Fixed a bug where using PacketRuleNodivision for UDP reception caused an infinite loop.</li>
<li>Added an option for TCP/IP clients to automatically attempt connection when the server disconnects.</li>
</ul>
<h2 id="fixed-bug-causing-infinite-loop-when-receiving-udp-using-packetrulenodivision">Fixed bug causing infinite loop when receiving UDP using PacketRuleNodivision</h2>
<figure>
    <img loading="lazy" src="/images/2019/06/11/215443/20190611214024.png"/> 
</figure>

<p>As shown above, using the UDP reception feature with PacketRuleNodivision caused a bug where it entered an infinite loop upon receiving data once. This has been fixed.</p>
<p>Since PacketRuleNodivision is likely used most often for UDP reception, I sincerely apologize for this critical bug.</p>
<h2 id="added-option-for-tcpip-client-to-automatically-attempt-connection-when-server-disconnects">Added option for TCP/IP client to automatically attempt connection when server disconnects</h2>
<figure>
    <img loading="lazy" src="/images/2019/06/11/215443/20190611214849.png"/> 
</figure>

<p>A feature was previously implemented where, when using a TCP/IP client with the Retry flag ON, it would automatically repeat Connect attempts until the server started.</p>
<p>However, this feature was designed not to work if the server terminated after a connection was established.</p>
<p>Therefore, a new AutoConnectAfterDisconnect flag has been created.</p>
<p>Turning this flag ON will cause it to automatically repeat Connect attempts if the connection to an already connected server is lost.</p>
<p>Thus, using it together with the conventional Retry flag will make it repeat Connect attempts whenever it is not connected to the server.</p>
<p>This is convenient for cases where you want to maintain a connection at all times.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Submitted XML Parser Plugin to UE4 Marketplace</title>
      <link>https://ayumax.net/entry/2019/06/10/235811/</link>
      <pubDate>Mon, 10 Jun 2019 23:58:11 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/06/10/235811/</guid>
      <description>&lt;h1 id=&#34;easyxmlparser&#34;&gt;EasyXMLParser&lt;/h1&gt;
&lt;p&gt;Today, I submitted a plugin named EasyXMLParser to the Unreal Engine Marketplace.&lt;/p&gt;
&lt;p&gt;This is my second work, following the previously released ObjectDeliverer.&lt;/p&gt;
&lt;p&gt;Last time I listed it for free, but this time I have set a price.
I focused on ease of use when creating it, so please consider it if you like.&lt;/p&gt;
&lt;p&gt;A sample using this plugin is available on GitHub.&lt;/p&gt;
&lt;div class=&#34;github-card&#34; data-user=&#34;ayumax&#34; data-repo=&#34;EasyXMLParserSample&#34; data-width=&#34;400&#34; data-height=&#34;&#34; data-theme=&#34;default&#34;&gt;&lt;/div&gt;
&lt;script src=&#34;https://cdn.jsdelivr.net/github-cards/latest/widget.js&#34;&gt;&lt;/script&gt;
&lt;h1 id=&#34;feature-introduction&#34;&gt;Feature Introduction&lt;/h1&gt;
&lt;p&gt;Introducing the features of EasyXMLParser.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="easyxmlparser">EasyXMLParser</h1>
<p>Today, I submitted a plugin named EasyXMLParser to the Unreal Engine Marketplace.</p>
<p>This is my second work, following the previously released ObjectDeliverer.</p>
<p>Last time I listed it for free, but this time I have set a price.
I focused on ease of use when creating it, so please consider it if you like.</p>
<p>A sample using this plugin is available on GitHub.</p>
<div class="github-card" data-user="ayumax" data-repo="EasyXMLParserSample" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<h1 id="feature-introduction">Feature Introduction</h1>
<p>Introducing the features of EasyXMLParser.</p>
<h2 id="getting-text">Getting Text</h2>
<p>To get a text node, create an access string for the value you want to retrieve.</p>
<p>The access string is created by connecting tag names with dots.</p>
<p>If there are multiple nodes with the same tag name, you can specify an index number starting from 0 (e.g., [2] -&gt; 3rd).</p>
<p>If no index is specified, the first element is retrieved.</p>
<img src="https://user-images.githubusercontent.com/8191970/57173329-f35b1e80-6e68-11e9-9cd7-a3910fb9159e.png" alt="GALLERY 4"/>
<p>The access string for getting attributes is specified with (at mark + attribute name).</p>
<img src="https://user-images.githubusercontent.com/8191970/57173330-f8b86900-6e68-11e9-9e52-4974c4dd3718.png" alt="GALLERY5"/>
<h2 id="getting-values-by-specifying-type">Getting Values by Specifying Type</h2>
<p>The following four functions are provided for getting values from XML.</p>
<ul>
<li>ReadInt(int)</li>
<li>ReadFloat(float)</li>
<li>ReadString(string)</li>
<li>ReadBool(bool)</li>
</ul>
<p>Enter the access string in &ldquo;AccessString&rdquo;.</p>
<p>Enter the default value in &ldquo;DefaultValue&rdquo;. If the specified value does not exist in the XML, the default value is returned.</p>
<img src="https://user-images.githubusercontent.com/8191970/57173340-29000780-6e69-11e9-8d55-5a473a631732.png" alt="GALLERY 1"/>
<h2 id="getting-objects">Getting Objects</h2>
<p>There are also &ldquo;ReadElement&rdquo; and &ldquo;ReadElements&rdquo; methods to get nodes as objects rather than values.</p>
<p>ReadElement gets a single node.</p>
<p>ReadElements gets an array of multiple nodes.</p>
<img src="https://user-images.githubusercontent.com/8191970/57173342-34533300-6e69-11e9-86af-d9bda9dafc5b.png" alt="GALLERY 2"/>
<h2 id="xml-parsing-method">XML Parsing Method</h2>
<p>There are two ways to load XML: &ldquo;LoadFromFile&rdquo; for loading XML files, and &ldquo;LoadFromString&rdquo; for loading XML strings.</p>
<p>There is also an asynchronous version that performs parsing in the background.</p>
<img src="https://user-images.githubusercontent.com/8191970/57173344-3cab6e00-6e69-11e9-805c-b55093fd139e.png" alt="GALLERY 3"/>
<h1 id="after-xml">After XML</h1>
<p>Personally, I occasionally have the opportunity to parse XML, so I decided to make it into a plugin this time.</p>
<p>However, I feel that JSON is used more often than XML nowadays.</p>
<p>Therefore, I plan to release a JSON parser as the next plugin.</p>
<p>It is designed with the same usability as this EasyXMLParser and is currently under review by the Marketplace.</p>
]]></content:encoded>
    </item>
    <item>
      <title>ObjectDeliverer Shared Memory Sample</title>
      <link>https://ayumax.net/entry/2019/06/06/231244/</link>
      <pubDate>Thu, 06 Jun 2019 23:12:44 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/06/06/231244/</guid>
      <description>&lt;h1 id=&#34;shared-memory-sample&#34;&gt;Shared Memory Sample&lt;/h1&gt;
&lt;p&gt;I had previously prepared ObjectDeliverer samples on GitHub, but for shared memory, only the reading side was implemented, and the process wasn&amp;rsquo;t complete. So, I newly implemented the writing side as well.&lt;/p&gt;
&lt;p&gt;Here, I will briefly introduce the contents of the sample.&lt;/p&gt;
&lt;h1 id=&#34;overview&#34;&gt;Overview&lt;/h1&gt;
&lt;p&gt;In this sample, an image captured by SceneCapture2D is extracted from a TextureRenderTarget, and then displayed on another material via shared memory.&lt;/p&gt;
&lt;img src=&#34;https://user-images.githubusercontent.com/8191970/59034465-159bee00-88a6-11e9-9abb-615eb1d88239.gif&#34; alt=&#34;203fc2438cc4488ddf9567ad67496f63&#34;/&gt;
&lt;ol&gt;
&lt;li&gt;First, please open the SharedMemory level.
&lt;img src=&#34;https://user-images.githubusercontent.com/8191970/59034702-9529bd00-88a6-11e9-9a74-55b9036a1c83.png&#34; alt=&#34;sharedmemory1&#34;/&gt;&lt;/li&gt;
&lt;li&gt;All implementation is within the Box Actor blueprint.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;reading-side-implementation&#34;&gt;Reading Side Implementation&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Prepare a texture and material to hold the pixel buffer read from shared memory.
&lt;img src=&#34;https://user-images.githubusercontent.com/8191970/59035081-711aab80-88a7-11e9-96de-12a6e1b76c9c.jpg&#34; alt=&#34;sharedmemory2&#34;/&gt;&lt;/li&gt;
&lt;li&gt;Generate an instance of ObjectDeliverer for reading shared memory and start the process.
&lt;img src=&#34;https://user-images.githubusercontent.com/8191970/59035271-e1293180-88a7-11e9-859e-488205a7080b.jpg&#34; alt=&#34;sharedmemory3&#34;/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The shared memory buffer size is set to the image buffer size (800x450x4 bytes).&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="shared-memory-sample">Shared Memory Sample</h1>
<p>I had previously prepared ObjectDeliverer samples on GitHub, but for shared memory, only the reading side was implemented, and the process wasn&rsquo;t complete. So, I newly implemented the writing side as well.</p>
<p>Here, I will briefly introduce the contents of the sample.</p>
<h1 id="overview">Overview</h1>
<p>In this sample, an image captured by SceneCapture2D is extracted from a TextureRenderTarget, and then displayed on another material via shared memory.</p>
<img src="https://user-images.githubusercontent.com/8191970/59034465-159bee00-88a6-11e9-9abb-615eb1d88239.gif" alt="203fc2438cc4488ddf9567ad67496f63"/>
<ol>
<li>First, please open the SharedMemory level.
<img src="https://user-images.githubusercontent.com/8191970/59034702-9529bd00-88a6-11e9-9a74-55b9036a1c83.png" alt="sharedmemory1"/></li>
<li>All implementation is within the Box Actor blueprint.</li>
</ol>
<h2 id="reading-side-implementation">Reading Side Implementation</h2>
<ol>
<li>Prepare a texture and material to hold the pixel buffer read from shared memory.
<img src="https://user-images.githubusercontent.com/8191970/59035081-711aab80-88a7-11e9-96de-12a6e1b76c9c.jpg" alt="sharedmemory2"/></li>
<li>Generate an instance of ObjectDeliverer for reading shared memory and start the process.
<img src="https://user-images.githubusercontent.com/8191970/59035271-e1293180-88a7-11e9-859e-488205a7080b.jpg" alt="sharedmemory3"/></li>
</ol>
<p>The shared memory buffer size is set to the image buffer size (800x450x4 bytes).</p>
<ol>
<li>Update the texture content in the ReceiveData event (an event that occurs when the content of the shared memory changes).
<img src="https://user-images.githubusercontent.com/8191970/59035611-9a880700-88a8-11e9-93d3-b5891920d0b3.jpg" alt="sharedmemory4"/></li>
</ol>
<h2 id="writing-side-implementation">Writing Side Implementation</h2>
<ol>
<li>Prepare a buffer to hold the pixel buffer obtained from TextureRenderTarget.</li>
<li>Generate an instance of ObjectDeliverer for writing to shared memory and start the process.
<img src="https://user-images.githubusercontent.com/8191970/59035271-e1293180-88a7-11e9-859e-488205a7080b.jpg" alt="sharedmemory3"/></li>
</ol>
<p>The shared memory buffer size is set to the image buffer size (800x450x4 bytes).</p>
<img src="https://user-images.githubusercontent.com/8191970/59036537-73cad000-88aa-11e9-9051-d8df6d94cb15.jpg" alt="sharedmemory4"/>
<ol>
<li>During the Tick event, extract the pixel buffer from TextureRenderTarget and write it to shared memory.
<img src="https://user-images.githubusercontent.com/8191970/59036949-387cd100-88ab-11e9-87e7-c827c135705c.jpg" alt="sharedmemory4"/></li>
</ol>
<h1 id="use-cases">Use Cases</h1>
<p>In this example, it&rsquo;s completed within a single process, so it doesn&rsquo;t have much meaning. However, for instance, by preparing two UE4 projects, one responsible for writing to shared memory and the other for reading from shared memory, video transfer can be achieved.</p>
<p>Unlike TCP/IP or UDP, shared memory cannot transfer data over a network, but because of that, it can transfer large amounts of data at high speed, making it suitable for inter-process communication of heavy data like video.</p>
<p>Please try it out if you are interested.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Created a Dynamic Mesh Generation Feature by Drawing with Editor Utility Widget</title>
      <link>https://ayumax.net/entry/2019/05/30/234740/</link>
      <pubDate>Thu, 30 May 2019 23:47:40 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/05/30/234740/</guid>
      <description>&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://ayumax.net/images/2019/05/30/234740/20190530234709.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h1 id=&#34;editor-utility-widget&#34;&gt;Editor Utility Widget&lt;/h1&gt;
&lt;p&gt;This time, I tried out the Editor Utility Widget feature, which became available from UE4.22.
Using Editor Utility Widget, you can easily create editor extensions with UMG and Blueprints.&lt;/p&gt;
&lt;p&gt;For a basic explanation of Editor Utility Widget, I referred to Okazu-san&amp;rsquo;s article.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://qiita.com/EGJ-Kaz_Okada/items/9f530db3b53d0fde3f20&#34;&gt;[UE4] About Editor Utility Widget, which allows easy creation of tools and editor extensions that run in the editor using UMG - Qiita&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&#34;what-i-made&#34;&gt;What I Made&lt;/h1&gt;
&lt;p&gt;I created a feature where you draw a single continuous line by dragging the mouse on the Editor Utility Widget, and then generate a spline mesh along the drawn line.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530234709.png"/> 
</figure>

<h1 id="editor-utility-widget">Editor Utility Widget</h1>
<p>This time, I tried out the Editor Utility Widget feature, which became available from UE4.22.
Using Editor Utility Widget, you can easily create editor extensions with UMG and Blueprints.</p>
<p>For a basic explanation of Editor Utility Widget, I referred to Okazu-san&rsquo;s article.</p>
<p><a href="https://qiita.com/EGJ-Kaz_Okada/items/9f530db3b53d0fde3f20">[UE4] About Editor Utility Widget, which allows easy creation of tools and editor extensions that run in the editor using UMG - Qiita</a></p>
<h1 id="what-i-made">What I Made</h1>
<p>I created a feature where you draw a single continuous line by dragging the mouse on the Editor Utility Widget, and then generate a spline mesh along the drawn line.</p>
<p>The resulting spline mesh can be converted into a static mesh by pressing a button.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Editor Scriptingでお絵かきして作ったSplineMeshComponentをそのままスクリプトでStaticMesh化するのに成功した。<a href="https://twitter.com/hashtag/UE4?src=hash&amp;ref_src=twsrc%5Etfw">#UE4</a> <a href="https://twitter.com/hashtag/ue4study?src=hash&amp;ref_src=twsrc%5Etfw">#ue4study</a> <a href="https://t.co/sCfMMPdC1J">pic.twitter.com/sCfMMPdC1J</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1134083916317380613?ref_src=twsrc%5Etfw">May 30, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<h1 id="enabling-the-editor-scripting-utilities-plugin">Enabling the Editor Scripting Utilities Plugin</h1>
<p>Enabling this plugin allows operations like manipulating assets from the Editor Utility Widget.
<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530234123.png"/> 
</figure>
</p>
<h1 id="drawing-lines-on-the-widget">Drawing Lines on the Widget</h1>
<p>I implemented the line drawing part within a single UserWidget.</p>
<p>First, prepare an array of coordinates (Vector2D) for drawing lines in the variables.
<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530230810.png"/> 
</figure>
</p>
<p>Next, empty the coordinate array every time on MouseDown.
<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530230738.png"/> 
</figure>
</p>
<p>In MouseMove, add the mouse coordinates to the coordinate array.</p>
<p>However, processing every MouseMove event results in too many points, so points are stored only if they are more than 5 pixels away from the previously stored point.</p>
<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530230956.png"/> 
</figure>

<p>Then, call DrawLines in OnPaint to draw the line.
<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530231131.png"/> 
</figure>
</p>
<p>In MouseUp, fire an event indicating that the line drawing is finished.</p>
<p>The Editor Utility Widget monitors this event and proceeds with mesh generation afterwards.</p>
<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530231259.png"/> 
</figure>

<h1 id="editor-utility-widget-implementation">Editor Utility Widget Implementation</h1>
<p>Next, create the Editor Utility Widget.</p>
<p>Also place the UserWidget created earlier.</p>
<figure>
     <img loading="lazy" src="/images/2019/05/30/234740/20190530231520.png"/> 
 </figure>

<p>To display a list of Actors with mesh generation functionality in the ComboBox, get the list of Actors and add them when the ComboBox opens.</p>
<p>Also, set the current Actor when the ComboBox selection changes.</p>
<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530231727.png"/> 
</figure>

<p>Monitor the line drawing finished event of the UserWidget created earlier and pass the array of coordinates along the line to the current Actor.
<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530231813.png"/> 
</figure>
</p>
<h1 id="spline-mesh-generation">Spline Mesh Generation</h1>
<p>Let&rsquo;s create the Actor that generates the spline mesh.</p>
<p>Add two SplineComponents and one SceneComponent to be the parent of the SplineMeshComponents.
Two SplineComponents are used lavishly for point correction.</p>
<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530232107.png"/> 
</figure>

<p>Create the function called when the UserWidget&rsquo;s line drawing finishes.</p>
<p>First, destroy all previously generated SplineMeshComponents and clear the points of the SplineComponent.
<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530232243.png"/> 
</figure>
</p>
<p>Next, add the passed array of points directly to the SplineComponent&rsquo;s points.
1 pixel is set as 10cm.</p>
<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530232409.png"/> 
</figure>

<p>Next, extract points at equal intervals along the line of the first SplineComponent and add them to the second SplineComponent.</p>
<p>The reason for creating the second SplineComponent here is that creating points at equal intervals results in a cleaner SplineMesh later.</p>
<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530232549.png"/> 
</figure>

<p>Finally, create SplineMeshComponents using the point positions and Tangents of the second SplineComponent.</p>
<p>This creates a mesh along the line drawn on the UserWidget.
<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530232744.png"/> 
</figure>
</p>
<h1 id="converting-spline-mesh-to-static-mesh">Converting Spline Mesh to Static Mesh</h1>
<p>To convert an Actor containing SplineMeshComponents to a StaticMesh, I usually use the MergeActor feature, so I looked for a way to call this from the Editor Utility Widget.</p>
<p>I found the node below, but its input is StaticMeshActor, so the type doesn&rsquo;t match.</p>
<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530232947.png"/> 
</figure>

<p>So, wondering if there was a way, I peeked into the C++ implementation of this node.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> UEditorLevelLibrary<span style="color:#f92672">::</span>MergeStaticMeshActors(<span style="color:#66d9ef">const</span> TArray<span style="color:#f92672">&lt;</span>AStaticMeshActor<span style="color:#f92672">*&gt;&amp;</span> ActorsToMerge, <span style="color:#66d9ef">const</span> FEditorScriptingMergeStaticMeshActorsOptions<span style="color:#f92672">&amp;</span> MergeOptions, AStaticMeshActor<span style="color:#f92672">*&amp;</span> OutMergedActor)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    TGuardValue<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">bool</span><span style="color:#f92672">&gt;</span> UnattendedScriptGuard(GIsRunningUnattendedScript, true);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    OutMergedActor <span style="color:#f92672">=</span> <span style="color:#66d9ef">nullptr</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>EditorScriptingUtils<span style="color:#f92672">::</span>CheckIfInEditorAndPIE())
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> false;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    FString FailureReason;
</span></span><span style="display:flex;"><span>    FString PackageName <span style="color:#f92672">=</span> EditorScriptingUtils<span style="color:#f92672">::</span>ConvertAnyPathToLongPackagePath(MergeOptions.BasePackageName, FailureReason);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (PackageName.IsEmpty())
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        UE_LOG(LogEditorScripting, Error, TEXT(<span style="color:#e6db74">&#34;MergeStaticMeshActors. Failed to convert the BasePackageName. %s&#34;</span>), <span style="color:#f92672">*</span>FailureReason);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> false;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    TArray<span style="color:#f92672">&lt;</span>AStaticMeshActor<span style="color:#f92672">*&gt;</span> AllActors;
</span></span><span style="display:flex;"><span>    TArray<span style="color:#f92672">&lt;</span>UPrimitiveComponent<span style="color:#f92672">*&gt;</span> AllComponents;
</span></span><span style="display:flex;"><span>    FVector PivotLocation;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>InternalEditorLevelLibrary<span style="color:#f92672">::</span>FindValidActorAndComponents(ActorsToMerge, AllActors, AllComponents, PivotLocation, FailureReason))
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        UE_LOG(LogEditorScripting, Error, TEXT(<span style="color:#e6db74">&#34;MergeStaticMeshActors failed. %s&#34;</span>), <span style="color:#f92672">*</span>FailureReason);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> false;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// See MeshMergingTool.cpp
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">//
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">const</span> IMeshMergeUtilities<span style="color:#f92672">&amp;</span> MeshUtilities <span style="color:#f92672">=</span> FModuleManager<span style="color:#f92672">::</span>Get().LoadModuleChecked<span style="color:#f92672">&lt;</span>IMeshMergeModule<span style="color:#f92672">&gt;</span>(<span style="color:#e6db74">&#34;MeshMergeUtilities&#34;</span>).GetUtilities();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    FVector MergedActorLocation;
</span></span><span style="display:flex;"><span>    TArray<span style="color:#f92672">&lt;</span>UObject<span style="color:#f92672">*&gt;</span> CreatedAssets;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">float</span> ScreenAreaSize <span style="color:#f92672">=</span> TNumericLimits<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">float</span><span style="color:#f92672">&gt;::</span>Max();
</span></span><span style="display:flex;"><span>    MeshUtilities.MergeComponentsToStaticMesh(AllComponents, AllActors[<span style="color:#ae81ff">0</span>]<span style="color:#f92672">-&gt;</span>GetWorld(), MergeOptions.MeshMergingSettings, <span style="color:#66d9ef">nullptr</span>, <span style="color:#66d9ef">nullptr</span>, PackageName, CreatedAssets, MergedActorLocation, ScreenAreaSize, true);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    UStaticMesh<span style="color:#f92672">*</span> MergedMesh <span style="color:#f92672">=</span> <span style="color:#66d9ef">nullptr</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>CreatedAssets.FindItemByClass(<span style="color:#f92672">&amp;</span>MergedMesh))
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        UE_LOG(LogEditorScripting, Error, TEXT(<span style="color:#e6db74">&#34;MergeStaticMeshActors failed. No mesh was created.&#34;</span>));
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> false;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    FAssetRegistryModule<span style="color:#f92672">&amp;</span> AssetRegistry <span style="color:#f92672">=</span> FModuleManager<span style="color:#f92672">::</span>Get().LoadModuleChecked<span style="color:#f92672">&lt;</span>FAssetRegistryModule<span style="color:#f92672">&gt;</span>(<span style="color:#e6db74">&#34;AssetRegistry&#34;</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (UObject<span style="color:#f92672">*</span> Obj : CreatedAssets)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        AssetRegistry.AssetCreated(Obj);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//Also notify the content browser that the new assets exists
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>IsRunningCommandlet())
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        FContentBrowserModule<span style="color:#f92672">&amp;</span> ContentBrowserModule <span style="color:#f92672">=</span> FModuleManager<span style="color:#f92672">::</span>Get().LoadModuleChecked<span style="color:#f92672">&lt;</span>FContentBrowserModule<span style="color:#f92672">&gt;</span>(<span style="color:#e6db74">&#34;ContentBrowser&#34;</span>);
</span></span><span style="display:flex;"><span>        ContentBrowserModule.Get().SyncBrowserToAssets(CreatedAssets, true);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Place new mesh in the world
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">if</span> (MergeOptions.bSpawnMergedActor)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        FActorSpawnParameters Params;
</span></span><span style="display:flex;"><span>        Params.OverrideLevel <span style="color:#f92672">=</span> AllActors[<span style="color:#ae81ff">0</span>]<span style="color:#f92672">-&gt;</span>GetLevel();
</span></span><span style="display:flex;"><span>        OutMergedActor <span style="color:#f92672">=</span> AllActors[<span style="color:#ae81ff">0</span>]<span style="color:#f92672">-&gt;</span>GetWorld()<span style="color:#f92672">-&gt;</span>SpawnActor<span style="color:#f92672">&lt;</span>AStaticMeshActor<span style="color:#f92672">&gt;</span>(MergedActorLocation, FRotator<span style="color:#f92672">::</span>ZeroRotator, Params);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>OutMergedActor)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            UE_LOG(LogEditorScripting, Error, TEXT(<span style="color:#e6db74">&#34;MergeStaticMeshActors failed. Internal error while creating the merged actor.&#34;</span>));
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> false;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        OutMergedActor<span style="color:#f92672">-&gt;</span>GetStaticMeshComponent()<span style="color:#f92672">-&gt;</span>SetStaticMesh(MergedMesh);
</span></span><span style="display:flex;"><span>        OutMergedActor<span style="color:#f92672">-&gt;</span>SetActorLabel(MergeOptions.NewActorLabel);
</span></span><span style="display:flex;"><span>        AllActors[<span style="color:#ae81ff">0</span>]<span style="color:#f92672">-&gt;</span>GetWorld()<span style="color:#f92672">-&gt;</span>UpdateCullDistanceVolumes(OutMergedActor, OutMergedActor<span style="color:#f92672">-&gt;</span>GetStaticMeshComponent());
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Remove source actors
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">if</span> (MergeOptions.bDestroySourceActors)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        UWorld<span style="color:#f92672">*</span> World <span style="color:#f92672">=</span> AllActors[<span style="color:#ae81ff">0</span>]<span style="color:#f92672">-&gt;</span>GetWorld();
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> (AActor<span style="color:#f92672">*</span> Actor : AllActors)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            GEditor<span style="color:#f92672">-&gt;</span>Layers<span style="color:#f92672">-&gt;</span>DisassociateActorFromLayers(Actor);
</span></span><span style="display:flex;"><span>            World<span style="color:#f92672">-&gt;</span>EditorDestroyActor(Actor, true);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//Select newly created actor
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    GEditor<span style="color:#f92672">-&gt;</span>SelectNone(false, true, false);
</span></span><span style="display:flex;"><span>    GEditor<span style="color:#f92672">-&gt;</span>SelectActor(OutMergedActor, true, false);
</span></span><span style="display:flex;"><span>    GEditor<span style="color:#f92672">-&gt;</span>NoteSelectionChange();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> true;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>It turns out that it extracts an array of UPrimitiveComponents from the array of StaticMeshActors passed as arguments and then merges them.</p>
<p>So, referencing this source, I created a function modified to take an Actor as an argument and merge the MeshComponents within the Actor.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> UEditorUtilExtention<span style="color:#f92672">::</span>MergeStaticMeshComponents(<span style="color:#66d9ef">const</span> AActor<span style="color:#f92672">*</span> Actor, <span style="color:#66d9ef">const</span> FString<span style="color:#f92672">&amp;</span> PackageName, <span style="color:#66d9ef">const</span> FMeshMergingSettings<span style="color:#f92672">&amp;</span> MergeOptions)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> IMeshMergeUtilities<span style="color:#f92672">&amp;</span> MeshUtilities <span style="color:#f92672">=</span> FModuleManager<span style="color:#f92672">::</span>Get().LoadModuleChecked<span style="color:#f92672">&lt;</span>IMeshMergeModule<span style="color:#f92672">&gt;</span>(<span style="color:#e6db74">&#34;MeshMergeUtilities&#34;</span>).GetUtilities();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    TInlineComponentArray<span style="color:#f92672">&lt;</span>UStaticMeshComponent<span style="color:#f92672">*&gt;</span> ComponentArray;
</span></span><span style="display:flex;"><span>    Actor<span style="color:#f92672">-&gt;</span>GetComponents<span style="color:#f92672">&lt;</span>UStaticMeshComponent<span style="color:#f92672">&gt;</span>(ComponentArray);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    TArray<span style="color:#f92672">&lt;</span>UPrimitiveComponent<span style="color:#f92672">*&gt;</span> allComponents;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">bool</span> bActorIsValid <span style="color:#f92672">=</span> false;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (UStaticMeshComponent<span style="color:#f92672">*</span> MeshCmp : ComponentArray)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (MeshCmp<span style="color:#f92672">-&gt;</span>GetStaticMesh() <span style="color:#f92672">&amp;&amp;</span> MeshCmp<span style="color:#f92672">-&gt;</span>GetStaticMesh()<span style="color:#f92672">-&gt;</span>RenderData.IsValid())
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            allComponents.Add(MeshCmp);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (allComponents.Num() <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>) <span style="color:#75715e">// Added check for empty components
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    {
</span></span><span style="display:flex;"><span>        UE_LOG(LogTemp, Warning, TEXT(<span style="color:#e6db74">&#34;MergeStaticMeshComponents failed. No valid StaticMeshComponents found in the actor.&#34;</span>));
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> false;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    FVector MergedActorLocation;
</span></span><span style="display:flex;"><span>    TArray<span style="color:#f92672">&lt;</span>UObject<span style="color:#f92672">*&gt;</span> CreatedAssets;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">float</span> ScreenAreaSize <span style="color:#f92672">=</span> TNumericLimits<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">float</span><span style="color:#f92672">&gt;::</span>Max();
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Use the first component&#39;s world
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    MeshUtilities.MergeComponentsToStaticMesh(allComponents, allComponents[<span style="color:#ae81ff">0</span>]<span style="color:#f92672">-&gt;</span>GetOwner()<span style="color:#f92672">-&gt;</span>GetWorld(), MergeOptions, <span style="color:#66d9ef">nullptr</span>, <span style="color:#66d9ef">nullptr</span>, PackageName, CreatedAssets, MergedActorLocation, ScreenAreaSize, true);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    UStaticMesh<span style="color:#f92672">*</span> MergedMesh <span style="color:#f92672">=</span> <span style="color:#66d9ef">nullptr</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>CreatedAssets.FindItemByClass(<span style="color:#f92672">&amp;</span>MergedMesh))
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        UE_LOG(LogTemp, Error, TEXT(<span style="color:#e6db74">&#34;MergeStaticMeshComponents failed. No mesh was created.&#34;</span>));
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> false;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    FAssetRegistryModule<span style="color:#f92672">&amp;</span> AssetRegistry <span style="color:#f92672">=</span> FModuleManager<span style="color:#f92672">::</span>Get().LoadModuleChecked<span style="color:#f92672">&lt;</span>FAssetRegistryModule<span style="color:#f92672">&gt;</span>(<span style="color:#e6db74">&#34;AssetRegistry&#34;</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (UObject<span style="color:#f92672">*</span> Obj : CreatedAssets)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        AssetRegistry.AssetCreated(Obj);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//Also notify the content browser that the new assets exists
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>IsRunningCommandlet())
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        FContentBrowserModule<span style="color:#f92672">&amp;</span> ContentBrowserModule <span style="color:#f92672">=</span> FModuleManager<span style="color:#f92672">::</span>Get().LoadModuleChecked<span style="color:#f92672">&lt;</span>FContentBrowserModule<span style="color:#f92672">&gt;</span>(<span style="color:#e6db74">&#34;ContentBrowser&#34;</span>);
</span></span><span style="display:flex;"><span>        ContentBrowserModule.Get().SyncBrowserToAssets(CreatedAssets, true);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> true;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>It extracts an array of UPrimitiveComponents from the Actor passed as an argument, and the subsequent merge process uses the logic from the original source as is.</p>
<p>Calling the completed function from the Editor Utility Widget properly merged the SplineMesh into a StaticMesh.
<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530233704.png"/> 
</figure>
</p>
<p>However, why are the materials also copied??</p>
<p>When manually using Merge Actor, it merges while referencing the original materials, which is the preferred behavior, but I couldn&rsquo;t figure out how to do that.
<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530233817.png"/> 
</figure>
</p>
<p>It has properly become a static mesh.
<figure>
    <img loading="lazy" src="/images/2019/05/30/234740/20190530233948.png"/> 
</figure>
</p>
<h1 id="summary">Summary</h1>
<p>This was my first time using Editor Utility Widget, and it was a lot of fun.</p>
<p>Since you can create editor extensions using familiar UMG and Blueprints, I think anyone can easily automate daily tasks.</p>
<p>I manually converted an Actor containing a large number of SplineMeshComponents to StaticMesh a while ago, so if I had known about this feature then, how much easier it would have been&hellip;</p>
<p>Automation not only makes tasks easier but also prevents careless mistakes from manual work, so I think it&rsquo;s useful in terms of quality as well.</p>
<p>I decided to actively use it more and more for tasks I want to automate in the future.</p>
]]></content:encoded>
    </item>
    <item>
      <title>MarketplaceURL when Submitting a UE4 Plugin to the Marketplace</title>
      <link>https://ayumax.net/entry/2019/05/26/235702/</link>
      <pubDate>Sun, 26 May 2019 23:57:02 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/05/26/235702/</guid>
      <description>&lt;p&gt;I recently submitted my second code plugin to the Marketplace, and while writing various properties into the uplugin file, I submitted it with the &amp;ldquo;MarketplaceURL&amp;rdquo; left blank.&lt;/p&gt;
&lt;p&gt;I had assumed this URL wouldn&amp;rsquo;t be decided until it was actually published on the Marketplace, so both last time and this time, I followed the flow below for submitting the code plugin:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Submit with MarketplaceURL blank.&lt;/li&gt;
&lt;li&gt;Receive an email from the reviewer saying, &#34;Write this URL in the uplugin and resubmit.&#34;&lt;/li&gt;
&lt;li&gt;Modify the uplugin, package again -&gt; upload.&lt;/li&gt;
&lt;li&gt;Resubmit.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I felt this flow was somewhat redundant and troublesome, but I did it this way both times, and if left alone, I intended to do it this way the third time too.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I recently submitted my second code plugin to the Marketplace, and while writing various properties into the uplugin file, I submitted it with the &ldquo;MarketplaceURL&rdquo; left blank.</p>
<p>I had assumed this URL wouldn&rsquo;t be decided until it was actually published on the Marketplace, so both last time and this time, I followed the flow below for submitting the code plugin:</p>
<ol>
<li>Submit with MarketplaceURL blank.</li>
<li>Receive an email from the reviewer saying, "Write this URL in the uplugin and resubmit."</li>
<li>Modify the uplugin, package again -> upload.</li>
<li>Resubmit.</li>
</ol>
<p>I felt this flow was somewhat redundant and troublesome, but I did it this way both times, and if left alone, I intended to do it this way the third time too.</p>
<p>However, today, when I happened to open the web page for the plugin awaiting review, I noticed that the end of the URL was the value to be written for the MarketplaceURL in the uplugin.</p>
<figure>
    <img loading="lazy" src="/images/2019/05/26/235702/20190527215202.png"/> 
</figure>

<p>Oh, right, that makes sense.</p>
<p>There&rsquo;s no way the flow should be this troublesome.</p>
<p>Perhaps it was written somewhere properly, and I might have overlooked it.</p>
<p>Until now, I left this URL blank, so resubmission was always necessary. But from next time, I aim to complete the review in one go.</p>
<p>*Update 2019/06/15: I actually submitted using this method and passed the review without any modifications.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Trying out .NET Core 3.0 WPF (Made a Node-Based Calculator)</title>
      <link>https://ayumax.net/entry/2019/05/13/190518/</link>
      <pubDate>Mon, 13 May 2019 19:05:18 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/05/13/190518/</guid>
      <description>&lt;h1 id=&#34;tried-it-out&#34;&gt;Tried It Out&lt;/h1&gt;
&lt;p&gt;With the combination of Visual Studio 2019 + .NET Core 3.0, WPF is usable, so I created a new project and tried it out.&lt;/p&gt;
&lt;p&gt;For now, I&amp;rsquo;ll try writing as if I&amp;rsquo;m using the traditional WPF, forgetting that I&amp;rsquo;m using .NET Core, and see how it feels.&lt;/p&gt;
&lt;p&gt;Usage methods are introduced by various people, but you can use it by installing Visual Studio 2019 and .NET Core 3.0, and then checking ON &amp;ldquo;Use preview .NET Core SDK&amp;rdquo; in Visual Studio options.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="tried-it-out">Tried It Out</h1>
<p>With the combination of Visual Studio 2019 + .NET Core 3.0, WPF is usable, so I created a new project and tried it out.</p>
<p>For now, I&rsquo;ll try writing as if I&rsquo;m using the traditional WPF, forgetting that I&rsquo;m using .NET Core, and see how it feels.</p>
<p>Usage methods are introduced by various people, but you can use it by installing Visual Studio 2019 and .NET Core 3.0, and then checking ON &ldquo;Use preview .NET Core SDK&rdquo; in Visual Studio options.</p>
<p>I think this check will become unnecessary once .NET Core 3.0 becomes the official version.</p>
<figure>
    <img loading="lazy" src="/images/2019/05/13/190518/20190512064056.png"/> 
</figure>

<h1 id="c-80-nullable-reference-types">C# 8.0 Nullable Reference Types</h1>
<p>At the same time, I also tried the nullable reference types introduced in C# 8.0.</p>
<p>This time, since I&rsquo;m trying it out by creating a new project, I&rsquo;ve enabled nullable reference types for the entire project by describing it in the .csproj as follows.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;propertygroup&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;outputtype&gt;</span>WinExe<span style="color:#f92672">&lt;/outputtype&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;targetframework&gt;</span>netcoreapp3.0<span style="color:#f92672">&lt;/targetframework&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;usewpf&gt;</span>true<span style="color:#f92672">&lt;/usewpf&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;langversion&gt;</span>8.0<span style="color:#f92672">&lt;/langversion&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;nullablecontextoptions&gt;</span>enable<span style="color:#f92672">&lt;/nullablecontextoptions&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/propertygroup&gt;</span>
</span></span></code></pre></div><p>With this setting, you can no longer put null in the traditional way of writing reference types.
Also, it will now issue a warning when accessing a variable that might be null.</p>
<h1 id="what-i-made">What I Made</h1>
<p>Since I&rsquo;m creating a new project, I decided to set a theme.<br/>
Because I often see node-based creation environments in tools like <a href="https://www.unrealengine.com/en-US/what-is-unreal-engine-4">Unreal Engine (UE4)</a>, which I use at work, and <a href="https://www.sidefx.com/products/houdini/">Houdini</a>, which I&rsquo;ve been paying attention to recently, I chose &ldquo;Node-Based UI&rdquo; as the theme.</p>
<figure>
    <img loading="lazy" src="/images/2019/05/13/190518/20190513175842.png"/> 
</figure>

<p>Just connecting nodes isn&rsquo;t interesting, so I&rsquo;ve included calculator functionality.</p>
<p>What I&rsquo;ve made, as of writing this article, looks like this:</p>
<p>Currently, you can connect nodes to perform addition and subtraction.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ノードベース計算機を結構バージョンアップ。<br>・ノード間の線は3次ベジェ曲線に<br>・ノードのプロパティはポップアップで変更<br>・入力ピン数の動的変更<a href="https://twitter.com/hashtag/wpf?src=hash&amp;ref_src=twsrc%5Etfw">#wpf</a> <a href="https://twitter.com/hashtag/dotnetcore?src=hash&amp;ref_src=twsrc%5Etfw">#dotnetcore</a> <a href="https://t.co/2RFaWWyjXf">pic.twitter.com/2RFaWWyjXf</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1127130209390477312?ref_src=twsrc%5Etfw">May 11, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>The complete project is available on GitHub.</p>
<div class="github-card" data-user="ayumax" data-repo="NodeCalculator" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<ul>
<li>Note: This node-based calculator is still under development, so it is frequently modified.</li>
</ul>
<h1 id="references-from-nuget">References from NuGet</h1>
<p>This time, I&rsquo;ve added references to the following four from NuGet:</p>
<ul>
<li>Extended.Wpf.Toolkit</li>
<li>gong-wpf-dragdrop</li>
<li>Microsoft.Xaml.Behaviors.Wpf</li>
<li>ReactiveProperty</li>
</ul>
<figure>
    <img loading="lazy" src="/images/2019/05/13/190518/20190513062057.png"/> 
</figure>

<p>Among these, <code>Extended.Wpf.Toolkit</code> and <code>Microsoft.Xaml.Behaviors.Wpf</code> don&rsquo;t seem to support .NET Core 3.0 yet, resulting in the following warnings:</p>
<pre tabindex="0"><code>NU1701: Package &#39;Extended.Wpf.Toolkit 3.5.0&#39; was restored using &#39;.NETFramework,Version=v4.6.1&#39; instead of the project target framework &#39;.NETCoreApp,Version=v3.0&#39;. This package may not be fully compatible with your project.
NU1701: Package &#39;Microsoft.Xaml.Behaviors.Wpf 1.0.1&#39; was restored using &#39;.NETFramework,Version=v4.6.1&#39; instead of the project target framework &#39;.NETCoreApp,Version=v3.0&#39;. This package may not be fully compatible with your project.
</code></pre><p>For now, there are no issues with the functionality I&rsquo;m using, and since .NET Core 3.0 is still a preview version, I&rsquo;ve decided not to worry about it.</p>
<p>If these warnings persist even after .NET Core 3.0 becomes the official version, actions such as handling it myself and building might be necessary.</p>
<h1 id="a-little-introduction-to-the-structure">A Little Introduction to the Structure</h1>
<p>I will focus on introducing the functionality for adding new nodes among what I created this time. (I thought about writing about drawing lines and performing calculations too, but since it&rsquo;s actively under development, there&rsquo;s a high possibility of future changes.)</p>
<h2 id="node-placement">Node Placement</h2>
<p>The XAML for the View where nodes are placed is as follows.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;itemscontrol</span> <span style="color:#a6e22e">itemsource=</span><span style="color:#e6db74">&#34;{Binding Nodes}&#34;</span> 
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">background=</span><span style="color:#e6db74">&#34;Transparent&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">dd:DragDrop.IsDropTarget=</span><span style="color:#e6db74">&#34;True&#34;</span> 
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">dd:DragDrop.DropHandler=</span><span style="color:#e6db74">&#34;{Binding}&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;itemscontrol.itemspanel&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&lt;itemspaneltemplate&gt;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&lt;canvas</span> <span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&lt;/itemspaneltemplate&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/itemscontrol.itemspanel&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;itemscontrol.itemtemplate&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&lt;datatemplate&gt;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&lt;node:NodeContainer</span> <span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&lt;/datatemplate&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/itemscontrol.itemtemplate&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;itemscontrol.itemcontainerstyle&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&lt;style</span> <span style="color:#a6e22e">targettype=</span><span style="color:#e6db74">&#34;ContentPresenter&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&lt;setter</span> <span style="color:#a6e22e">property=</span><span style="color:#e6db74">&#34;Canvas.Top&#34;</span> <span style="color:#a6e22e">value=</span><span style="color:#e6db74">&#34;{Binding PositionY.Value}&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&lt;setter</span> <span style="color:#a6e22e">property=</span><span style="color:#e6db74">&#34;Canvas.Left&#34;</span> <span style="color:#a6e22e">value=</span><span style="color:#e6db74">&#34;{Binding PositionX.Value}&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&lt;/style&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/itemscontrol.itemcontainerstyle&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/itemscontrol&gt;</span>
</span></span></code></pre></div><p>By specifying Canvas for ItemsPanel, placement using absolute coordinates is enabled.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;itemscontrol.itemspanel&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;itemspaneltemplate&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&lt;canvas</span> <span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/itemspaneltemplate&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/itemscontrol.itemspanel&gt;</span>
</span></span></code></pre></div><p>Node position setting is handled by binding Canvas.Top and Left to the properties of the node&rsquo;s ViewModel in ItemContainerStyle.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;itemscontrol.itemcontainerstyle&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;style</span> <span style="color:#a6e22e">targettype=</span><span style="color:#e6db74">&#34;ContentPresenter&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&lt;setter</span> <span style="color:#a6e22e">property=</span><span style="color:#e6db74">&#34;Canvas.Top&#34;</span> <span style="color:#a6e22e">value=</span><span style="color:#e6db74">&#34;{Binding PositionY.Value}&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&lt;setter</span> <span style="color:#a6e22e">property=</span><span style="color:#e6db74">&#34;Canvas.Left&#34;</span> <span style="color:#a6e22e">value=</span><span style="color:#e6db74">&#34;{Binding PositionX.Value}&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/style&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/itemscontrol.itemcontainerstyle&gt;</span>
</span></span></code></pre></div><p>Also, since node generation via drag-and-drop is incorporated into this ItemsControl, <code>dd:DragDrop.IsDropTarget</code> and <code>dd:DragDrop.DropHandler</code> are specified.</p>
<p>This is a feature of <code>gong-wpf-dragdrop</code> added via NuGet; writing it this way allows you to write the drop handling logic in the ViewModel bound to the ItemsControl.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;itemscontrol</span> <span style="color:#a6e22e">itemsource=</span><span style="color:#e6db74">&#34;{Binding Nodes}&#34;</span> 
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">background=</span><span style="color:#e6db74">&#34;Transparent&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">dd:DragDrop.IsDropTarget=</span><span style="color:#e6db74">&#34;True&#34;</span> 
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">dd:DragDrop.DropHandler=</span><span style="color:#e6db74">&#34;{Binding}&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&gt;</span>
</span></span></code></pre></div><h2 id="new-node-generation">New Node Generation</h2>
<p>The following source code is the process when dropping onto the View where nodes are placed.</p>
<p><code>dropInfo.Data</code> contains the DataContext (bound ViewModel) of the dropped View, so the process changes depending on its type.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> Drop(IDropInfo dropInfo)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">switch</span> (dropInfo.Data)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> NodeViewModel node:
</span></span><span style="display:flex;"><span>            {
</span></span><span style="display:flex;"><span>                nowDragItem = <span style="color:#66d9ef">null</span>;
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> NodeConnectionViewModel connection:
</span></span><span style="display:flex;"><span>            {
</span></span><span style="display:flex;"><span>                connection.LineToX.Value = <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>                connection.LineToY.Value = <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>                connection.Visible.Value = Visibility.Hidden;
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> ToolBoxItemViewModel item:
</span></span><span style="display:flex;"><span>            {
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">var</span> newItem = Activator.CreateInstance(item.NodeModelType) <span style="color:#66d9ef">as</span> NodeBase;
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">if</span> (newItem != <span style="color:#66d9ef">null</span>)
</span></span><span style="display:flex;"><span>                {
</span></span><span style="display:flex;"><span>                    newItem.PositionX = dropInfo.DropPosition.X;
</span></span><span style="display:flex;"><span>                    newItem.PositionY = dropInfo.DropPosition.Y;
</span></span><span style="display:flex;"><span>                    mainModel.Nodes.Add(newItem);
</span></span><span style="display:flex;"><span>                }                
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">default</span>:
</span></span><span style="display:flex;"><span>            nowDragItem = <span style="color:#66d9ef">null</span>;
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The Drop process when creating a new node is the part that handles <code>ToolBoxItemViewModel</code>.</p>
<p>The dropped ViewModel has a property called NodeModelType of type Type, and based on this, an instance of the node is generated.</p>
<p>The generated node is given coordinates based on the drop position and added to the model&rsquo;s <code>Nodes</code> array.</p>
<p>This addition to the array propagates from Model -&gt; ViewModel -&gt; View, and the new node is displayed in the ItemsControl explained earlier.</p>
<p>Also, where <code>Activator.CreateInstance</code> is used, I initially skipped the null check out of laziness, but since the nullable reference types feature was ON, a warning appeared.</p>
<p>Adding the null check made the warning disappear, apparently because the compiler performs flow analysis. Amazing!</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#66d9ef">case</span> ToolBoxItemViewModel item:
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> newItem = Activator.CreateInstance(item.NodeModelType) <span style="color:#66d9ef">as</span> NodeBase;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (newItem != <span style="color:#66d9ef">null</span>) <span style="color:#75715e">// Null check added</span>
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            newItem.PositionX = dropInfo.DropPosition.X;
</span></span><span style="display:flex;"><span>            newItem.PositionY = dropInfo.DropPosition.Y;
</span></span><span style="display:flex;"><span>            mainModel.Nodes.Add(newItem);
</span></span><span style="display:flex;"><span>        }                    
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">break</span>;
</span></span></code></pre></div><h1 id="summary">Summary</h1>
<p>While writing this article, I intended to summarize any points like &ldquo;you should be careful about this when using WPF with .NET Core,&rdquo; but&hellip; there weren&rsquo;t any in particular.</p>
<p>You can use it just like when using the previous .NET Framework version of WPF.</p>
<p>It was said that the inability to use the XAML designer in the .NET Core version was a disadvantage, but it seems it became usable in VS2019 Preview 3 (haven&rsquo;t tried it yet), so I think this will also cease to be an issue eventually.</p>
<p>Also, regarding nullable reference types, I initially thought the warnings might be intrusive, but that wasn&rsquo;t the case. Instead, I felt it was a helpful feature because it points out places where I might have overlooked potential null access.</p>
<p>Introducing it into existing projects might result in a flood of warnings and be difficult, but I think enabling it for newly created projects enhances code safety.</p>
<p>I believe .NET Core will become mainstream for future C# development, but I felt that developing desktop applications using WPF is also perfectly fine.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Note on Updating Content Submitted to the UE4 Marketplace</title>
      <link>https://ayumax.net/entry/2019/05/08/232600/</link>
      <pubDate>Wed, 08 May 2019 23:26:00 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/05/08/232600/</guid>
      <description>&lt;p&gt;I got a bit confused when updating my plugin, so I&amp;rsquo;m making a note of it.&lt;/p&gt;
&lt;p&gt;Code plugins written in C++ will likely undergo several version updates, and here&amp;rsquo;s a point to note during that process.&lt;/p&gt;
&lt;p&gt;When updating content for an already listed Engine version, the Project File Link on the screen below needs to be a different link URL than the previous one.&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://ayumax.net/images/2019/05/08/232600/20190508231942.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;It seems that if this URL is the same as the previous one, notification that the content has changed will not be sent.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I got a bit confused when updating my plugin, so I&rsquo;m making a note of it.</p>
<p>Code plugins written in C++ will likely undergo several version updates, and here&rsquo;s a point to note during that process.</p>
<p>When updating content for an already listed Engine version, the Project File Link on the screen below needs to be a different link URL than the previous one.</p>
<figure>
    <img loading="lazy" src="/images/2019/05/08/232600/20190508231942.png"/> 
</figure>

<p>It seems that if this URL is the same as the previous one, notification that the content has changed will not be sent.</p>
<p>I use Microsoft OneDrive, and overwriting a cloud file results in the same shared link URL as before. Therefore, I issued a different URL by first unsharing the file and then sharing it again.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Regarding Multi-Platform Support for Plugins Submitted to the UE4 Marketplace</title>
      <link>https://ayumax.net/entry/2019/05/05/183952/</link>
      <pubDate>Sun, 05 May 2019 18:39:52 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/05/05/183952/</guid>
      <description>&lt;h1 id=&#34;multi-platform-support-for-ue4-plugins&#34;&gt;Multi-Platform Support for UE4 Plugins&lt;/h1&gt;
&lt;p&gt;The plugin I currently have listed on the Marketplace, ObjectDeliverer, only supports Windows.&lt;/p&gt;
&lt;p&gt;Recently, I received several requests from users asking for support for other platforms, so I decided to reluctantly look into it.&lt;/p&gt;
&lt;p&gt;I found many articles about multi-platform support for the final game package, but I had trouble finding much information specifically about plugin packaging.&lt;/p&gt;
&lt;p&gt;However, since most of it is the same as game packaging methods, by piecing together various bits of information, I managed to get to a point where it seems likely to work.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="multi-platform-support-for-ue4-plugins">Multi-Platform Support for UE4 Plugins</h1>
<p>The plugin I currently have listed on the Marketplace, ObjectDeliverer, only supports Windows.</p>
<p>Recently, I received several requests from users asking for support for other platforms, so I decided to reluctantly look into it.</p>
<p>I found many articles about multi-platform support for the final game package, but I had trouble finding much information specifically about plugin packaging.</p>
<p>However, since most of it is the same as game packaging methods, by piecing together various bits of information, I managed to get to a point where it seems likely to work.</p>
<p>The following information assumes a Windows development environment.</p>
<ul>
<li>As I will write at the end, only iOS is not working correctly.</li>
</ul>
<h1 id="environment-preparation">Environment Preparation</h1>
<p>First, from the Engine installation options, check the platforms you want to output to and install the necessary features.</p>
<figure>
    <img loading="lazy" src="/images/2019/05/05/183952/20190505174905.png"/> 
</figure>

<p>Next, install additionally required software.</p>
<h2 id="android">Android</h2>
<p>Install the tools necessary for the Android development environment all at once using the following installer:</p>
<p>[UE4 Install Directory]\Engine\Extras\AndroidWorks\Win64\CodeWorksforAndroid-1R7u1-windows.exe</p>
<p>Details about this information can be confirmed from the link below.</p>
<p><a href="http://api.unrealengine.com/JPN/Platforms/Android/GettingStarted/1/">Unreal Engine | 1. Settings Required for Android Game Development</a></p>
<h2 id="linux">Linux</h2>
<p>For Linux, the official website has links to installers for the necessary software (toolchain), so download and install from there.</p>
<p>The toolchain differs for each Engine version, so installation is required for each Engine version you want to package for.</p>
<figure>
    <img loading="lazy" src="/images/2019/05/05/183952/20190505180159.png"/> 
</figure>

<p>Links to the installers are available on the site below.</p>
<p>(The Japanese page only goes up to Engine version 4.19, so I am providing the link to the English page.)</p>
<p><a href="https://docs.unrealengine.com/en-US/Platforms/Linux/GettingStarted">Cross-Compiling for Linux</a></p>
<h2 id="ios">iOS</h2>
<p>Since iOS cannot be built on a Windows machine, the method seems to be preparing a Mac machine on the same network and building by remotely logging in from Windows.</p>
<p>Therefore, remote login settings need to be configured.</p>
<p>For normal game packaging, it seems the settings are completed by entering the Mac machine name and login username in [ProjectSettings]-[Platforms]-[iOS]-[Build]-[Remote Build Options].</p>
<p>You can also create and register SSH Keys here.</p>
<p>However, this information is not used for plugin packaging, and it won&rsquo;t remotely access the Mac.</p>
<p>After trying various things, adding the following description to [UE4 Install Directory]\Engine\Config\IOS\IOSEngine.ini made it attempt remote connection.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-txt" data-lang="txt"><span style="display:flex;"><span>[/Script/IOSRuntimeSettings.IOSRuntimeSettings]
</span></span><span style="display:flex;"><span>RemoteServerName=Mac_Machine_Name
</span></span><span style="display:flex;"><span>RSyncUsername=Login_Username
</span></span></code></pre></div><h1 id="plugin-packaging">Plugin Packaging</h1>
<p>For the basic method of plugin packaging, please refer to the previous article.</p>
<p><a href="https://www.ayumax.net/entry/2019/02/07/235700">Creating a Package for a Custom UE4 Plugin for the Marketplace - AYU MAX</a></p>
<p>Also, if creating via Editor operations instead of commands, it seems you can also Package from the Plugins window. (Learned this recently)
<figure>
    <img loading="lazy" src="/images/2019/05/05/183952/20190505181419.png"/> 
</figure>
</p>
<p>To create output for the targeted platform at this time, it is necessary to write the platform name in WhitelistPlatforms in the *.uplugin file.
(It seems you can also specify via command line arguments instead of using WhitelistPlatforms)</p>
<p>Writing as follows apparently outputs for Windows (64bit, 32bit), Mac, Linux, iOS, Android, HTML5, so let&rsquo;s try running the packaging command with this setting.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span><span style="color:#e6db74">&#34;WhitelistPlatforms&#34;</span><span style="color:#960050;background-color:#1e0010">:</span> [
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;Win64&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;Win32&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;Mac&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;Linux&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;IOS&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;Android&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;HTML5&#34;</span>
</span></span><span style="display:flex;"><span>]
</span></span></code></pre></div><h1 id="packaging-results">Packaging Results</h1>
<p>I judged whether packaging was successful by looking at the command results and the contents within the plugin output directory&rsquo;s \Intermediate\Build.</p>
<p>The results were as follows:</p>
<table>
<thead>
<tr>
<th style="text-align:left;">Platform</th>
<th style="text-align:left;">Result</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;">Win64</td>
<td style="text-align:left;">〇 (Success)</td>
</tr>
<tr>
<td style="text-align:left;">Win32</td>
<td style="text-align:left;">〇 (Success)</td>
</tr>
<tr>
<td style="text-align:left;">Mac</td>
<td style="text-align:left;">× (Failure)</td>
</tr>
<tr>
<td style="text-align:left;">Linux</td>
<td style="text-align:left;">〇 (Success)</td>
</tr>
<tr>
<td style="text-align:left;">iOS</td>
<td style="text-align:left;">× (Failure)</td>
</tr>
<tr>
<td style="text-align:left;">Android</td>
<td style="text-align:left;">〇 (Success)</td>
</tr>
<tr>
<td style="text-align:left;">HTML5</td>
<td style="text-align:left;">〇 (Success)</td>
</tr>
</tbody>
</table>
<p>As a result, generation succeeded for all except Mac and iOS.</p>
<p>Looking into it, it seems Mac currently cannot be built from Windows, and the only way for Mac is to install UE4 on a Mac and build from there.</p>
<p>iOS actually failed with an error during the command execution, and it didn&rsquo;t work.</p>
<p>From the error message content, I think it&rsquo;s related to provisioning, but I haven&rsquo;t found a proper solution yet.</p>
<p>The official method is probably the procedure described in <a href="http://api.unrealengine.com/JPN/Platforms/iOS/QuickStart/3/index.html">Unreal Engine | 3. iOS Provisioning - Generating Signing Certificates</a>, but this procedure cannot be realized without completing iOS Developer registration, so I am looking for alternative methods.</p>
<p>I understand it&rsquo;s absolutely necessary for game builds, but personally, I wonder if it&rsquo;s also needed for plugin builds.</p>
<p>If I can&rsquo;t find a method, I will obediently pay the tribute to Apple and try building with the official method.</p>
<p>If anyone knows a way to package plugins without paying the tribute, please let me know.</p>
<h1 id="summary">Summary</h1>
<p>Although only iOS didn&rsquo;t work, I was able to package the UE4 plugin for multi-platform support.</p>
<p>However, I am thinking of supporting only Windows for my plugin for the time being.</p>
<p>If there is a problem with the plugin released on the Marketplace, I think I can manage it with my knowledge for Windows, but I don&rsquo;t have much experience with other platforms, so I currently lack the confidence to support them properly.</p>
<p>Releasing with the restriction of not supporting anything other than Windows might be an option, but I will think about it a little longer.</p>
]]></content:encoded>
    </item>
    <item>
      <title>ObjectDeliverer Ver1.1.0 Released</title>
      <link>https://ayumax.net/entry/2019/05/03/213240/</link>
      <pubDate>Fri, 03 May 2019 21:32:40 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/05/03/213240/</guid>
      <description>&lt;p&gt;I have updated the version of the code plugin listed (for free) on the Unreal Engine Marketplace.&lt;/p&gt;
&lt;p&gt;The latest plugin can already be downloaded from the Marketplace.&lt;/p&gt;
&lt;p&gt;Please see the following article for what ObjectDeliverer is.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.ayumax.net/entry/2019/01/28/000355&#34;&gt;Easy Inter-Process Communication in UE4 with ObjectDeliverer - AYU MAX&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&#34;update-details&#34;&gt;Update Details&lt;/h1&gt;
&lt;p&gt;The updates this time are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Minor bug fixes&lt;/li&gt;
&lt;li&gt;Functionality to specify the destination when using a TCP/IP server&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;bug-fixes&#34;&gt;Bug Fixes&lt;/h2&gt;
&lt;p&gt;Fixed a bug where a null access crash occurred if PacketRule was not passed during the ObjectDelivererManager&amp;rsquo;s Start method.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I have updated the version of the code plugin listed (for free) on the Unreal Engine Marketplace.</p>
<p>The latest plugin can already be downloaded from the Marketplace.</p>
<p>Please see the following article for what ObjectDeliverer is.</p>
<p><a href="https://www.ayumax.net/entry/2019/01/28/000355">Easy Inter-Process Communication in UE4 with ObjectDeliverer - AYU MAX</a></p>
<h1 id="update-details">Update Details</h1>
<p>The updates this time are:</p>
<ul>
<li>Minor bug fixes</li>
<li>Functionality to specify the destination when using a TCP/IP server</li>
</ul>
<h2 id="bug-fixes">Bug Fixes</h2>
<p>Fixed a bug where a null access crash occurred if PacketRule was not passed during the ObjectDelivererManager&rsquo;s Start method.</p>
<p>Additionally, processing efficiency improvements (removal of unnecessary value copying) have been made.</p>
<h2 id="functionality-to-specify-destination-when-using-tcpip-server">Functionality to Specify Destination When Using TCP/IP Server</h2>
<p>This feature was implemented in response to a request comment on the Marketplace content page.</p>
<p>With the existing Send method, when you are the server and multiple clients are connected, data would reach all clients. The SendTo method has been added to allow sending only to the intended client.</p>
<p>Incidentally, if the SendTo method is used when utilizing protocols other than TCP/IP server, it behaves the same as the Send method.</p>
<h3 id="sendto-sample">SendTo Sample</h3>
<p>The destination passed to SendTo comes as a parameter in Connected events or ReceiveData events.</p>
<p>Therefore, by appropriately storing this value, sending to the targeted TCP/IP client is possible.</p>
<p>The following Blueprint uses the parameter from ReceiveData directly for SendTo.</p>
<p>With this description, it&rsquo;s possible to implement a response transmission only to the client that sent the data when data is received.</p>
<figure>
    <img loading="lazy" src="/images/2019/05/03/213240/20190503212742.png"/> 
</figure>

<p>Please try it out if you are interested.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Experienced the Varjo VR-1</title>
      <link>https://ayumax.net/entry/2019/04/23/223654/</link>
      <pubDate>Tue, 23 Apr 2019 22:36:54 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/04/23/223654/</guid>
      <description>&lt;p&gt;I had the chance to experience the Varjo VR-1 at ELSA&amp;rsquo;s booth during the Unreal Fest held in Kyoto the other day, so here are my impressions.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;ja&#34; dir=&#34;ltr&#34;&gt;&lt;a href=&#34;https://twitter.com/hashtag/Varjo?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#Varjo&lt;/a&gt; の体験もできた。凄い興味あったのでよかった。&lt;br&gt;確かに視野の中心はめちゃくちゃ綺麗で文字の滲みもまったくなかった。&lt;br&gt;ディスプレイの切れ目は分かるっちゃ分かる。&lt;br&gt;控えめに言って欲しい。&lt;a href=&#34;https://twitter.com/hashtag/ue4fest?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#ue4fest&lt;/a&gt; &lt;a href=&#34;https://t.co/RuPpZAJ6JQ&#34;&gt;pic.twitter.com/RuPpZAJ6JQ&lt;/a&gt;&lt;/p&gt;&amp;mdash; ayuma (@ayuma_x) &lt;a href=&#34;https://twitter.com/ayuma_x/status/1119413185658806272?ref_src=twsrc%5Etfw&#34;&gt;April 20, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;


&lt;h1 id=&#34;varjo-vr-1&#34;&gt;Varjo VR-1&lt;/h1&gt;
&lt;p&gt;Varjo is a VR startup from Finland.
The VR-1 is a PC-connected VR headset released in February 2019.&lt;/p&gt;
&lt;h1 id=&#34;features-of-the-vr-1&#34;&gt;Features of the VR-1&lt;/h1&gt;
&lt;p&gt;The most significant feature of the VR-1 is its novel structure, which renders a narrow area in the center of the field of view with a high-resolution display and the surrounding peripheral vision with a low-resolution display.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I had the chance to experience the Varjo VR-1 at ELSA&rsquo;s booth during the Unreal Fest held in Kyoto the other day, so here are my impressions.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/Varjo?src=hash&amp;ref_src=twsrc%5Etfw">#Varjo</a> の体験もできた。凄い興味あったのでよかった。<br>確かに視野の中心はめちゃくちゃ綺麗で文字の滲みもまったくなかった。<br>ディスプレイの切れ目は分かるっちゃ分かる。<br>控えめに言って欲しい。<a href="https://twitter.com/hashtag/ue4fest?src=hash&amp;ref_src=twsrc%5Etfw">#ue4fest</a> <a href="https://t.co/RuPpZAJ6JQ">pic.twitter.com/RuPpZAJ6JQ</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1119413185658806272?ref_src=twsrc%5Etfw">April 20, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<h1 id="varjo-vr-1">Varjo VR-1</h1>
<p>Varjo is a VR startup from Finland.
The VR-1 is a PC-connected VR headset released in February 2019.</p>
<h1 id="features-of-the-vr-1">Features of the VR-1</h1>
<p>The most significant feature of the VR-1 is its novel structure, which renders a narrow area in the center of the field of view with a high-resolution display and the surrounding peripheral vision with a low-resolution display.</p>
<p>The mechanical aspect of rendering with two displays of different resolutions is intriguing.</p>
<p>Considering how the human eye actually sees – clearly in the center but blurry in the periphery – this structure might be quite effective.</p>
<p>Furthermore, even though it&rsquo;s called &ldquo;low-resolution,&rdquo; its resolution is apparently the same as the VIVE Pro, so we can expect it to be clearer than previous VR headsets in every aspect.</p>
<p>It&rsquo;s also great that it supports SteamVR, meaning content previously made for VIVE or VIVE Pro will run as is!</p>
<h1 id="impressions-from-actual-experience">Impressions from Actual Experience</h1>
<p>Before the demo, I received a brief explanation. I was told that IPD adjustment is automatic, and if lines appear when wearing it, I should fine-tune the headset myself so that the lines connect horizontally.</p>
<p>The subsequent content was a demo where I could experience being inside a car interior, and it was truly beautiful.</p>
<p>Small text was clearly visible, and it was just stunningly clear!!</p>
<p>However, the boundary between the high-resolution and low-resolution displays was quite distinct, which was unfortunate.</p>
<p>Also, the feature I had seen online beforehand – &ldquo;eye-tracking follows the direction of gaze, and the high-resolution display moves accordingly&rdquo; – seemed not to be implemented.</p>
<p>Nevertheless, overall, it was clearer than any VR I had seen before, and I really want one.</p>
<p>I&rsquo;m currently creating content using a VIVE Pro at work, so I can&rsquo;t help but think how much clearer it would look with this device.</p>
<p>I asked the person explaining if there were plans for sales in Japan. They said nothing is decided yet, but adjustments are underway, so I want to remain hopeful.</p>
<p>However, the overseas selling price is apparently $6000, so it&rsquo;s expected to be quite expensive in Japan as well.</p>
<p>Also, the GPU used for the demo was a Quadro RTX 8000, so it seems a considerable GPU spec will be required&hellip;</p>
<figure>
    <img loading="lazy" src="/images/2019/04/23/223654/IMG_20190420_101648.jpg"/> 
</figure>

<figure>
    <img loading="lazy" src="/images/2019/04/23/223654/IMG_20190420_101656.jpg"/> 
</figure>

]]></content:encoded>
    </item>
    <item>
      <title>Attended Unreal Fest 2019</title>
      <link>https://ayumax.net/entry/2019/04/22/220709/</link>
      <pubDate>Mon, 22 Apr 2019 22:07:09 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/04/22/220709/</guid>
      <description>&lt;h1 id=&#34;unreal-fest-west-2019&#34;&gt;UNREAL FEST WEST 2019&lt;/h1&gt;
&lt;p&gt;This is a large-scale official study event hosted by Epic Games Japan. It has been held annually in the Kanto and Kansai regions since 2014, when Unreal Engine 4 was made publicly available.
*From the &lt;a href=&#34;http://unrealengine.jp/unrealfest/&#34;&gt;official website&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&#34;before-attending&#34;&gt;Before Attending&lt;/h1&gt;
&lt;p&gt;I had applied for 2018 as well, but another commitment came up on the day, so I couldn&amp;rsquo;t go. This was my first time attending.&lt;/p&gt;
&lt;p&gt;Being a large-scale study event, I wondered how many people would come, but seeing the final expected attendance number was over 600 people made me realize it truly was large-scale.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="unreal-fest-west-2019">UNREAL FEST WEST 2019</h1>
<p>This is a large-scale official study event hosted by Epic Games Japan. It has been held annually in the Kanto and Kansai regions since 2014, when Unreal Engine 4 was made publicly available.
*From the <a href="http://unrealengine.jp/unrealfest/">official website</a></p>
<h1 id="before-attending">Before Attending</h1>
<p>I had applied for 2018 as well, but another commitment came up on the day, so I couldn&rsquo;t go. This was my first time attending.</p>
<p>Being a large-scale study event, I wondered how many people would come, but seeing the final expected attendance number was over 600 people made me realize it truly was large-scale.</p>
<p>When deciding whether to bring my laptop, I hesitated because it&rsquo;s heavy and wouldn&rsquo;t last the whole day without power, so I decided against it.</p>
<p>However, the venue was a hall-like place at Kyoto Computer Gakuin, and there were tables and power outlets at the seats, so it seemed usable even if I had brought it.</p>
<p>In the end, during the lectures, I only used Twitter and took notes, so the laptop wasn&rsquo;t necessary.</p>
<h1 id="from-arrival-to-start">From Arrival to Start</h1>
<p>I had read on the official website beforehand that there would be an after-party following the fest, and thinking it sounded interesting, I definitely wanted to attend.</p>
<p>To participate, it was necessary to buy a ticket on the day.</p>
<p>Seeing information that the tickets were limited in number, I thought it best to arrive early and got there around 9:30 AM, 30 minutes before registration started at 10:00 AM.</p>
<p>When I arrived, there was already a queue of about 20 to 30 people.
After that, the line kept growing longer, indicating its popularity.</p>
<p>At 10:00 AM, registration began, and I entered.
At the reception, I showed the screen of the Peatix app on my smartphone to complete registration.
I received a tote bag as a visitor gift.
Despite being a free gift, this bag is well-made and cool.</p>
<figure>
    <img loading="lazy" src="/images/2019/04/22/220709/IMG_20190420_231821.jpg"/> 
</figure>

<p>After completing registration, I went to the merchandise corner next door.</p>
<p>I saw the pink band, which was the ticket for the after-party, so it seemed I made it in time.</p>
<p>Paid 5000 yen and successfully got it.</p>
<blockquote>
<p>#ue4fest pic.twitter.com/s7sEBeWAq3
— ayuma (@ayuma_x) April 20, 2019<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p></blockquote>
<p>However, I saw the words &ldquo;Limited to 25&rdquo; at the sales counter, and thought, &ldquo;Eh, 600 people are coming, but there are only 25? It&rsquo;s really rare. If I had come a little later, it would definitely have been sold out&hellip;&rdquo;</p>
<p>Also, I personally wanted to buy stickers or T-shirts, but this time only the after-party tickets were sold, which was a bit disappointing.</p>
<p>I wanted to put a UE4 sticker on my laptop&hellip;</p>
<p>There were also company exhibits around the reception area, and I found something extremely interesting among them, so I went to see it right after completing registration.
I will write a separate article about this.</p>
<p>After looking around the other exhibits a bit, I went to the venue and waited for the start.</p>
<h1 id="1-unreal-engine-roadmap">1) Unreal Engine Roadmap</h1>
<p>The first talk was by Axel from Epic.
I heard many interesting stories about the latest features of UE4.</p>
<p>It started in French, which was a bit surprising. After that, the explanation was in fluent Japanese and easy to understand.</p>
<p>Below are the contents that caught my interest.</p>
<h2 id="epic-online-services">Epic Online Services</h2>
<p><a href="https://dev.epicgames.com/ja/services?lang=ja">Epic Online Services | Services</a></p>
<p>They will release an SDK that provides online service functionality.</p>
<p>Of course for UE4, but I was surprised that they would also release it for Unity!</p>
<p>Since there&rsquo;s also a C API, it seems possible to support various platforms if you try.</p>
<p>I was moved by the words, &ldquo;It&rsquo;s free. There are no hidden catches.&rdquo;</p>
<h2 id="quixel-movie">Quixel Movie</h2>
<iframe width="480" height="270" src="https://www.youtube.com/embed/9fC20NWhx4s?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=9fC20NWhx4s">www.youtube.com</a></cite>
<p>I was shown an incredibly beautiful movie made using UE4.
It truly looked like live-action, and I couldn&rsquo;t hide my surprise that it was real-time rendering.</p>
<h2 id="live-coding">Live Coding</h2>
<p>A feature included since 4.22, it allows C++ changes to be reflected faster than the previous hot reload.
Personally, I thought the script reflection time was an area where UE4 lagged behind Unity, so this is a very welcome feature.</p>
<p>Now I can use C++ with less stress from waiting times!!!</p>
<h2 id="ray-tracing">Ray Tracing</h2>
<iframe width="480" height="270" src="https://www.youtube.com/embed/3wUVLYKPB6g?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=3wUVLYKPB6g">www.youtube.com</a></cite>
<p>There was also an explanation and demo of the current highlight, real-time ray tracing.
The mirror reflections really change when enabled.
With the latest drivers, it seems usable even on GTX 1060 and above, which is great for trying it out.</p>
<p>Researching later, I found out the movie above was made with a single 2080 Ti, which made me feel its awesomeness even more.</p>
<h2 id="unreal-insights">Unreal Insights</h2>
<p>Information announced for the first time at this Unreal Fest.
A high-performance tracing framework that is said to make performance and crash analysis easier.
Even now, load confirmation etc. can be done with various commands, but I&rsquo;m looking forward to seeing how things change when this is introduced.</p>
<h2 id="chaos">Chaos</h2>
<iframe width="480" height="270" src="https://www.youtube.com/embed/u3ktiewcLpo?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=u3ktiewcLpo">www.youtube.com</a></cite>
<p>A new physics destruction system apparently testable in the next version, 4.23.
Watching the footage of buildings being destroyed, the reality was incredible, as if real objects were being destroyed.
Making a game using this seems like it would be exhilarating!!</p>
<h1 id="2-what-i-learned-from-listing-a-shrine-asset-on-the-ue4-marketplace">2) What I Learned from Listing a Shrine Asset on the UE4 Marketplace</h1>
<p><a href="https://www.unrealengine.com/marketplace/ja/slug/shinto-shrine">Shinto Shrine：Motonak：Environments - UE4 Marketplace</a></p>
<p>A lecture by background artist Mr. Nakamura.</p>
<p>Since the content was non-public, I won&rsquo;t write details, but I heard interesting stories about the Marketplace.</p>
<p>I also listed one item recently and was thinking of listing another next, so it was very helpful.</p>
<h1 id="3-hearing-from-the-students-who-became-number-one-in-japan-how-to-conquer-the-japan-game-awards">3) Hearing from the Students Who Became Number One in Japan: How to Conquer the Japan Game Awards</h1>
<p>A panel discussion with the team members who won the Grand Prize in the &ldquo;Japan Game Awards 2018 Amateur Division&rdquo;.</p>
<p>It was the first time I saw footage of the game, but even at a glance, the quality was very high, and I actually wanted to try playing it.</p>
<p>Listening to their stories, it strongly felt like they won the Grand Prize not by chance, but by aiming for it. Although they are students, I felt a strong sense of professionalism.</p>
<p>Stories that left an impression included:
&ldquo;There are reasons for everything, including the game&rsquo;s concept, and we can explain them properly.&rdquo;
&ldquo;Since the game&rsquo;s concept is mirrors, we bought real mirrors and studied them.&rdquo;
etc.</p>
<p>Indeed, having reasons for the development concept prevents the plan from wavering midway, and I felt that&rsquo;s the same in work.
(Lately, my own activities have been quite plan-wavering&hellip;)</p>
<p>It was content I could relate to in many ways.</p>
<h1 id="4-utilization-in-non-game-fields-in-2019">4) Utilization in Non-Game Fields in 2019</h1>
<p>I heard about three patterns of UE4 utilization examples outside of games.</p>
<p>In the introduction video of Reality, a video compositing tool? using UE4, I was shown incredibly accurate keying down to the level of individual hairs, and felt it was an amazing technology.</p>
<p>Also, UE4 is apparently now used for filming movies etc., and sometimes prototypes are made with UE4 to check the visuals before actual shooting.</p>
<p>The third one, Unreal Studio, was a familiar topic as I use it myself.
By smoothly importing from CAD tools into UE4, UE4 is also used in the manufacturing industry.</p>
<h1 id="5-utilizing-console-assets-ue4-utilization-case-study-for-the-mobile-game-winning-eleven-2019">5) Utilizing Console Assets? UE4 Utilization Case Study for the Mobile Game &ldquo;Winning Eleven 2019&rdquo;</h1>
<p>A story about replacing the game engine of Winning Eleven with UE4.</p>
<p>Not just replacing it, but a story of successfully replacing the engine under circumstances with no time margin and no turning back.</p>
<p>Although spoken calmly, thinking about it carefully, I felt this might have been an incredibly dangerous story.</p>
<p>The people involved at the time must have been extremely tired&hellip;</p>
<p>Also, I thought I might want to try using the CRI File System mentioned in the talk.
The term &ldquo;dual file system&rdquo; using it sounded cool.</p>
<h1 id="6-cloud-expression-in-ace-combat-7-using-ue4-x-truesky">6) Cloud Expression in &ldquo;Ace Combat 7&rdquo; Using UE4 x TrueSky</h1>
<p>A story about expressing realistic skies in Ace Combat 7 using UE4 and TrueSky.</p>
<p>Thinking it was a game development talk, it started with &ldquo;What are clouds?&rdquo; and began like a physics lesson.</p>
<p>Using middleware called TrueSky allows creating realistic clouds, but to do so, it seems necessary to understand phenomena like why clouds form, what their components are, etc.</p>
<blockquote>
<p><a href="https://t.co/pJCuZJQeUj">https://t.co/pJCuZJQeUj</a> #ue4fest
— ayuma (@ayuma_x) April 20, 2019<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p></blockquote>
<p>Apparently, as you master it, you start feeling things like &ldquo;Today&rsquo;s atmospheric color is deep&rdquo; or &ldquo;Today&rsquo;s sky Mie scattering is strong&rdquo; when looking at the actual sky.</p>
<p>It truly felt like professionals of the sky and clouds.</p>
<p>Also interesting was the story of various工夫 (ingenuity/contrivances) made to maintain 60fps in the PS4 VR version.</p>
<p>To make it lighter, they apparently even modified TrueSky itself, making me feel the programmers are strong.</p>
<p>Listening to the talk made me want to play Ace Combat!!</p>
<h1 id="7-automatic-background-generation-using-procedural-techniques-1000-japanese-rooms">7) Automatic Background Generation Using Procedural Techniques: &ldquo;1,000 Japanese Rooms&rdquo;</h1>
<iframe width="480" height="270" src="https://www.youtube.com/embed/FotLJdyCE98?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=FotLJdyCE98">www.youtube.com</a></cite>
<p>A story about creating a mechanism for automatic generation of Japanese rooms using &ldquo;Houdini,&rdquo; which I often hear about recently.</p>
<p>Not just automatic generation, but the quality was also amazing, to the level where comparing it with photos of real rooms, it was hard to tell which was real.</p>
<blockquote>
<p>Artistic nodes!! #UE4fest
— ayuma (@ayuma_x) April 20, 2019<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p></blockquote>
<p>Received the power word &ldquo;artistic nodes,&rdquo; causing laughter!</p>
<p>However, reflecting on the Blueprints I&rsquo;ve written in the past, I thought, &ldquo;I have quite a few artistic nodes too&hellip;&rdquo;</p>
<p>What strongly impressed me was the mechanism for connecting the kotatsu cord to the outlet, avoiding obstacles.</p>
<p>I felt it was genuinely amazing because trying to create this by programming it myself would require quite a bit of head-scratching.</p>
<h1 id="after-party-social-gathering">After Party (Social Gathering)</h1>
<p>After the fest ended, there was a social gathering for ticket holders and related personnel.</p>
<p>Although I didn&rsquo;t know anyone, I was able to talk and exchange business cards with several people and had a fun time.</p>
<p>In the rock-paper-scissors game, I lost just before winning and couldn&rsquo;t get a prize&hellip; I really wanted that thing with the UE4 shortcuts written on it.</p>
<p>But I was happy to be able to talk to Nan-san, the creator of Nanana, which I recently fell in love with at first sight on the Marketplace and purchased.
<a href="https://www.unrealengine.com/marketplace/ja/slug/iron-fist-girl">Iron Fist Girl：Indie-usGames：Characters - UE4 Marketplace</a></p>
<p>This asset is really Cool!</p>
<h1 id="next-is-yokohama">Next is Yokohama</h1>
<p>Although it was my first time participating in Unreal Fest, the large venue and the content, all of which were interesting, were truly stimulating.</p>
<p>I&rsquo;ve been using UE4 for work for several years and creating various things, so I want to maintain this motivation and continue creating good things.</p>
<p>Unreal Fest happens twice a year, and the next one seems to be in Yokohama, so if my schedule allows, I&rsquo;d like to go again.</p>
<p>Thank you to the related personnel for a wonderful fest.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Updating a Plugin Submitted to the UE4 Marketplace</title>
      <link>https://ayumax.net/entry/2019/04/06/144803/</link>
      <pubDate>Sat, 06 Apr 2019 14:48:03 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/04/06/144803/</guid>
      <description>&lt;h1 id=&#34;plugin-support-for-ue4-422&#34;&gt;Plugin Support for UE4 4.22&lt;/h1&gt;
&lt;p&gt;The official version of UE4 Ver 4.22 was released the other day.
So, I made my plugin (ObjectDeliverer) submitted to the Marketplace compatible with 4.22, and I will record the procedure here.&lt;/p&gt;
&lt;p&gt;Please refer to the previous article for the plugin being updated this time, ObjectDeliverer.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.ayumax.net/entry/2019/01/28/000355&#34;&gt;Easy Inter-Process Communication in UE4 with ObjectDeliverer - AYU MAX&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&#34;create-package-with-422&#34;&gt;Create Package with 4.22&lt;/h1&gt;
&lt;p&gt;First, create a package for the custom plugin using the 4.22 engine.
Please refer to the previous article for the method of creating a plugin package.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="plugin-support-for-ue4-422">Plugin Support for UE4 4.22</h1>
<p>The official version of UE4 Ver 4.22 was released the other day.
So, I made my plugin (ObjectDeliverer) submitted to the Marketplace compatible with 4.22, and I will record the procedure here.</p>
<p>Please refer to the previous article for the plugin being updated this time, ObjectDeliverer.</p>
<p><a href="https://www.ayumax.net/entry/2019/01/28/000355">Easy Inter-Process Communication in UE4 with ObjectDeliverer - AYU MAX</a></p>
<h1 id="create-package-with-422">Create Package with 4.22</h1>
<p>First, create a package for the custom plugin using the 4.22 engine.
Please refer to the previous article for the method of creating a plugin package.</p>
<p><a href="https://www.ayumax.net/entry/2019/02/07/235700">Creating a Package for a Custom UE4 Plugin for the Marketplace - AYU MAX</a></p>
<p>I thought the C++ rules probably hadn&rsquo;t changed from 4.21 to 4.22, so I expected it to build smoothly, but I got several C5038 errors.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">C5038のエラーが原因っぽい。メンバ変数の宣言順に初期化してないのが原因？？</p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1114389529534681089?ref_src=twsrc%5Etfw">April 6, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>However, I haven&rsquo;t been able to determine whether this is due to the UE4 version update or a Visual Studio update.</p>
<p>After fixing the errors and confirming there were no issues through testing, I created the package.</p>
<h1 id="work-in-marketplace-publisher-portal">Work in Marketplace Publisher Portal</h1>
<p>From here, update the Marketplace registration.
Go to the Marketplace Publisher Portal page and select the published plugin.</p>
<p>If you look closely, there&rsquo;s a warning saying, &ldquo;Your product is not compatible with the latest UE4.&rdquo;</p>
<figure>
    <img loading="lazy" src="/images/2019/04/06/144803/20190406143217.png"/> 
</figure>

<p>This time, the only change is adding the 4.22 compatible plugin, so scroll down the page to PRODUCT FILES.</p>
<p>Then, add an item for 4.22, set the URL of the 4.22 compatible plugin uploaded to the cloud, and configure the necessary items.</p>
<figure>
    <img loading="lazy" src="/images/2019/04/06/144803/20190406143930.png"/> 
</figure>

<p>Once the settings are complete, press the &ldquo;Submit&rdquo; button to finish the update procedure.</p>
<h1 id="confirmation-email">Confirmation Email</h1>
<p>After a while, an email titled &ldquo;Unreal Engine Marketplace: Pending File Update&rdquo; arrived from Epic, stating that the plugin update was received.
I think the Marketplace information will be updated after a while.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Released ObjectDeliverer to the UE4 Marketplace</title>
      <link>https://ayumax.net/entry/2019/02/20/215627/</link>
      <pubDate>Wed, 20 Feb 2019 21:56:27 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/02/20/215627/</guid>
      <description>&lt;h1 id=&#34;release-to-marketplace-complete&#34;&gt;Release to Marketplace Complete&lt;/h1&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://ayumax.net/images/2019/02/20/215627/20190220210655.png&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;I was able to achieve my recent goal of listing on the UE4 Marketplace.&lt;/p&gt;
&lt;p&gt;What I released is a Code Plugin called ObjectDeliverer.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s priced as Free, so anyone can use it.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.unrealengine.com/marketplace/objectdeliverer&#34;&gt;ObjectDeliverer by ayumax in Code Plugins - UE4 Marketplace&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s primarily a library for inter-process communication between UE4 applications and other applications.&lt;/p&gt;
&lt;p&gt;It might not be a perfect match for those using UE4 for game development, but I think it will resonate with those using it for other purposes and wanting to link with other applications.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="release-to-marketplace-complete">Release to Marketplace Complete</h1>
<figure>
    <img loading="lazy" src="/images/2019/02/20/215627/20190220210655.png"/> 
</figure>

<p>I was able to achieve my recent goal of listing on the UE4 Marketplace.</p>
<p>What I released is a Code Plugin called ObjectDeliverer.</p>
<p>It&rsquo;s priced as Free, so anyone can use it.</p>
<p><a href="https://www.unrealengine.com/marketplace/objectdeliverer">ObjectDeliverer by ayumax in Code Plugins - UE4 Marketplace</a></p>
<p>It&rsquo;s primarily a library for inter-process communication between UE4 applications and other applications.</p>
<p>It might not be a perfect match for those using UE4 for game development, but I think it will resonate with those using it for other purposes and wanting to link with other applications.</p>
<p>I myself am currently using it for content creation utilizing VR.</p>
<p>I have written separate articles about this library, so please take a look if you are interested.</p>
<p><a href="https://www.ayumax.net/entry/2019/01/28/000355">Easy Inter-Process Communication in UE4 with ObjectDeliverer - AYU MAX</a></p>
<h1 id="history-leading-up-to-release">History Leading Up to Release</h1>
<p>Just in case, I&rsquo;ll jot down how things went leading up to the release.</p>
<h3 id="201812">2018/12</h3>
<p>Thought of writing a communication library for UE4 and started working on it.
Decided to aim for a Marketplace release while I was at it.</p>
<h3 id="20191">2019/1</h3>
<p>Completed the first version of the library. Tested it by using it myself.
Fixed all the bugs found.</p>
<h3 id="201927">2019/2/7</h3>
<p>Learned that packaging is necessary for Marketplace submission, researched → implemented.</p>
<p><a href="https://www.ayumax.net/entry/2019/02/07/235700">Creating a Package for a Custom UE4 Plugin for the Marketplace - AYU MAX</a></p>
<h3 id="2019210">2019/2/10</h3>
<p>Registered as a seller on the Marketplace and registered the created package.
Completed everything while feeling anxious about whether the entries were correct.</p>
<p>The email after registration stated it would take 15 to 20 business days for the review to complete.</p>
<p><a href="https://www.ayumax.net/entry/2019/02/10/171408">Submitting to the UE4 Marketplace - AYU MAX</a></p>
<h3 id="2019216">2019/2/16</h3>
<p>Received an email saying it would be reviewed within 5 business days.</p>
<p>Was a bit surprised as I was prepared to wait for about a month.</p>
<h3 id="2019218">2019/2/18</h3>
<p>The review was finished, and some minor corrections were needed.</p>
<p>Specifically, I was pointed out to add a Copyright notice at the beginning of the C++ source files.</p>
<p>Also, I was asked to describe the MarketplaceURL in the *.uplugin file and re-register the file.</p>
<p>Implemented the corrections and re-registered on the same day.</p>
<h3 id="2019219">2019/2/19</h3>
<p>Received notification that it would proceed to the final review within 3 to 5 business days.</p>
<h3 id="2019219-1">2019/2/19</h3>
<p>Received an email just before the date changed, stating the status had become APPROVED.
It said I just needed to log into my product page myself and change the status to PUBLISHED.</p>
<p>Did it immediately, and the release was successfully completed.</p>
<p>Checked on the Epic Games Launcher, and it was indeed there!!</p>
<figure>
    <img loading="lazy" src="/images/2019/02/20/215627/20190220215342.png"/> 
</figure>

<h1 id="managed-to-release-by-trying-hard">Managed to Release by Trying Hard</h1>
<p>It had been years since I last released an iOS app to any store, so it was a lot of fun.</p>
<p>Above all, there&rsquo;s a sense of accomplishment.</p>
<p>The review, which I thought would take a long time, ended up taking only 10 days, so the wait was totally bearable, and more importantly, I was relieved it wasn&rsquo;t rejected.</p>
<p>Thank you to the Epic staff who reviewed it.</p>
<p>That said, releasing a library to the store can be considered the start, so I want to maintain it properly.</p>
<p>I still have 2 or 3 more ideas in my head, so it would be great if I could release again.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Slightly Modifying Static Meshes with Mesh Editing</title>
      <link>https://ayumax.net/entry/2019/02/15/225425/</link>
      <pubDate>Fri, 15 Feb 2019 22:54:25 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/02/15/225425/</guid>
      <description>&lt;h1 id=&#34;mesh-editing&#34;&gt;Mesh Editing&lt;/h1&gt;
&lt;p&gt;Since UE4 4.21, a feature has been added that allows slight editing of Static Meshes, which is quite convenient, so I&amp;rsquo;m making a note of it.&lt;/p&gt;
&lt;p&gt;The modeling features added in 4.20, introduced in this feature showcase, are more advanced, but the feature I&amp;rsquo;m writing about this time is likely a separate one.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://unrealengine.hatenablog.com/entry/2018/06/10/235233&#34;&gt;Trying out UE4&amp;rsquo;s New Polygon Modeling Feature (Mesh Editor) - Let&amp;rsquo;s Enjoy Unreal Engine&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&#34;usage-conditions&#34;&gt;Usage Conditions&lt;/h1&gt;
&lt;p&gt;A project with Unreal Studio configured in 4.21 is required.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="mesh-editing">Mesh Editing</h1>
<p>Since UE4 4.21, a feature has been added that allows slight editing of Static Meshes, which is quite convenient, so I&rsquo;m making a note of it.</p>
<p>The modeling features added in 4.20, introduced in this feature showcase, are more advanced, but the feature I&rsquo;m writing about this time is likely a separate one.</p>
<p><a href="http://unrealengine.hatenablog.com/entry/2018/06/10/235233">Trying out UE4&rsquo;s New Polygon Modeling Feature (Mesh Editor) - Let&rsquo;s Enjoy Unreal Engine</a></p>
<h1 id="usage-conditions">Usage Conditions</h1>
<p>A project with Unreal Studio configured in 4.21 is required.</p>
<p>If Unreal Studio is not configured or is disabled (*.uproject&rsquo;s &ldquo;Enterprise&rdquo;: false), it will not appear in the display.</p>
<h1 id="assigning-a-new-material-to-arbitrary-polygons-of-a-static-mesh">Assigning a New Material to Arbitrary Polygons of a Static Mesh</h1>
<p>Let&rsquo;s try assigning a material to the mesh&rsquo;s polygons using the Mesh Editing feature mentioned above.</p>
<p>I downloaded the mesh used this time from here.</p>
<p><a href="https://www.turbosquid.com/3d-models/free-c4d-model-retro-tv/815392">free c4d model retro tv</a></p>
<ul>
<li>Open the downloaded Static Mesh.</li>
</ul>
<figure>
    <img loading="lazy" src="/images/2019/02/15/225425/20190215212653.png"/> 
</figure>

<ul>
<li>Select the "Mesh Editing" tab at the top of the window.</li>
</ul>
<figure>
    <img loading="lazy" src="/images/2019/02/15/225425/20190215212727.png"/> 
</figure>

<ul>
<li>Press the "EditMode" button and select the polygons.
You can select multiple by holding Ctrl while selecting.</li>
</ul>
<figure>
    <img loading="lazy" src="/images/2019/02/15/225425/20190215213455.png"/> 
</figure>

<ul>
<li>Select the material you want to assign with the mouse in the Content Browser.</li>
</ul>
<figure>
    <img loading="lazy" src="/images/2019/02/15/225425/20190215213219.png"/> 
</figure>

<ul>
<li>Return to the Mesh Editing screen and press "Assign Material" at the top of the window. A Material Slot will be added, and the material selected just before will be assigned.</li>
</ul>
<figure>
    <img loading="lazy" src="/images/2019/02/15/225425/20190215213719.png"/> 
</figure>

<h1 id="other-features">Other Features</h1>
<p>You can delete selected polygons, flip UVs, etc.</p>
<p>It&rsquo;s convenient because you don&rsquo;t have to go through fbx export → editing in a modeling tool like Blender for minor changes.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Bought a Laptop Cooler: NOTEPAL X-SLIM II</title>
      <link>https://ayumax.net/entry/2019/02/11/221751/</link>
      <pubDate>Mon, 11 Feb 2019 22:17:51 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/02/11/221751/</guid>
      <description>&lt;h1 id=&#34;my-laptop-is-noisy&#34;&gt;My Laptop is Noisy&lt;/h1&gt;
&lt;p&gt;The Razer Blade laptop that arrived at my home late last year is a very welcome presence, as it allows me to use UE4 even at home.&lt;/p&gt;
&lt;p&gt;However, I had been troubled by the loudness of its fan for some time.&lt;/p&gt;
&lt;p&gt;At home, I use an Oculus Rift for VR development, and the fan noise when starting Oculus is intense.&lt;/p&gt;
&lt;p&gt;However, I can tolerate that because I understand the load is high. But even when doing nothing, the fan occasionally spins at high speed when a single external display is connected.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="my-laptop-is-noisy">My Laptop is Noisy</h1>
<p>The Razer Blade laptop that arrived at my home late last year is a very welcome presence, as it allows me to use UE4 even at home.</p>
<p>However, I had been troubled by the loudness of its fan for some time.</p>
<p>At home, I use an Oculus Rift for VR development, and the fan noise when starting Oculus is intense.</p>
<p>However, I can tolerate that because I understand the load is high. But even when doing nothing, the fan occasionally spins at high speed when a single external display is connected.</p>
<p>This is a bit stressful during quiet nights, and since the PC itself gets quite hot, I&rsquo;m also concerned about its durability.</p>
<p>So, I purchased this item.</p>
<h2 id="cooler-master-laptop-cooler-notepal-x-slim-ii">Cooler Master Laptop Cooler NOTEPAL X-SLIM II</h2>
<figure>
    <img loading="lazy" src="/images/2019/02/11/221751/IMG_20190209_184117.jpg"/> 
</figure>

<p>The price wasn&rsquo;t too high, and with a 20cm fan, I bought it hoping that the cooler itself would be relatively quiet.</p>
<p>This is how it looks with the Razer Blade on it.</p>
<figure>
    <img loading="lazy" src="/images/2019/02/11/221751/IMG_20190211_214013.jpg"/> 
</figure>

<p>It&rsquo;s powered via USB connection from the PC.</p>
<p>The power USB connector itself has a USB pass-through port, so the port used by the cooler isn&rsquo;t wasted.</p>
<p>After actually using it, perhaps because the fan is large, the noise from the cooler itself wasn&rsquo;t noticeable.</p>
<p>The sound of the air conditioner running in the room is louder.</p>
<p>As for the crucial effect on the laptop, it&rsquo;s not just my imagination; the fan noise has certainly become less noticeable.</p>
<p>Even with one external display connected, a situation where the fan would normally spin up occasionally, it now maintains a quiet state.</p>
<p>Also, perhaps thanks to the constant airflow from below, the area next to the touchpad, which usually gets hot, doesn&rsquo;t get hot anymore.</p>
<p>Naturally, the fan still spins up when launching UE4 or similar applications, but even then, I can feel it&rsquo;s quieter than before.</p>
<p>One point of caution is that there&rsquo;s no power switch, so it&rsquo;s better to connect the USB to a port that stops supplying power when the PC is turned off.</p>
<p>If you&rsquo;re troubled by laptop fan noise, consider giving it a try.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Submitting to the UE4 Marketplace</title>
      <link>https://ayumax.net/entry/2019/02/10/171408/</link>
      <pubDate>Sun, 10 Feb 2019 17:14:08 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/02/10/171408/</guid>
      <description>&lt;h1 id=&#34;want-to-submit-to-the-marketplace&#34;&gt;Want to Submit to the Marketplace&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ll write down the steps I took to submit &lt;a href=&#34;https://github.com/ayumax/ObjectDeliverer&#34;&gt;ObjectDeliverer&lt;/a&gt; to the Marketplace as a memo.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The input items on the registration page vary depending on what you select beforehand. Here, I will describe the items for submitting ObjectDeliverer.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;s&gt;* Currently awaiting review, so there&amp;rsquo;s a possibility of errors in the steps described here. If such things are found, I will correct them sequentially.&lt;/s&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Successfully listed on the Marketplace, so these steps seem to be OK. (2019/02/20)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr/&gt;
&lt;p&gt;The Marketplace is the UE4 store accessible from the Epic Games Launcher or the web.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="want-to-submit-to-the-marketplace">Want to Submit to the Marketplace</h1>
<p>I&rsquo;ll write down the steps I took to submit <a href="https://github.com/ayumax/ObjectDeliverer">ObjectDeliverer</a> to the Marketplace as a memo.</p>
<ul>
<li>The input items on the registration page vary depending on what you select beforehand. Here, I will describe the items for submitting ObjectDeliverer.</li>
</ul>
<p><s>* Currently awaiting review, so there&rsquo;s a possibility of errors in the steps described here. If such things are found, I will correct them sequentially.</s></p>
<ul>
<li>Successfully listed on the Marketplace, so these steps seem to be OK. (2019/02/20)</li>
</ul>
<hr/>
<p>The Marketplace is the UE4 store accessible from the Epic Games Launcher or the web.</p>
<p>Since UE4 is a game engine, the impression is that most available items are assets like 3D models, textures, materials, effects, and sounds, but libraries for creating program logic in C++ and Blueprint are also available.</p>
<figure>
    <img loading="lazy" src="/images/2019/02/10/171408/20190210152705.png"/> 
</figure>

<p>This time, I will summarize the procedure for publishing my own created Plugin here.</p>
<h1 id="seller-registration">Seller Registration</h1>
<p>First, register as a seller.</p>
<p>Clicking the &ldquo;Get Started!&rdquo; button on the site below transitions to the registration screen.</p>
<ul>
<li>In my environment (Windows 10, Chrome), there was a frequent phenomenon where the page would freeze upon clicking the button and transitioning, erasing the input content. Changing the browser to Edge avoided this phenomenon, so please refer to this if something similar happens.</li>
</ul>
<p><a href="https://publish.unrealengine.com/v2/welcome">Publisher Portal</a></p>
<figure>
    <img loading="lazy" src="/images/2019/02/10/171408/20190210153845.png"/> 
</figure>

<h2 id="registration-information">Registration Information</h2>
<p>First, register personal information such as name, phone number, and email address.</p>
<p>The content registered on this page is registered only with Epic Games and is not disclosed externally.</p>
<figure>
    <img loading="lazy" src="/images/2019/02/10/171408/20190210154155.png"/> 
</figure>

<h2 id="seller-public-information">Seller Public Information</h2>
<p>Next, register the information to be disclosed as a seller.</p>
<p>Required are the seller name and support email address.
Others seem optional, so enter information that can be disclosed, such as homepage, Twitter, Facebook, etc., if available.</p>
<figure>
    <img loading="lazy" src="/images/2019/02/10/171408/20190210154515.png"/> 
</figure>

<h2 id="payment-information">Payment Information</h2>
<p>Enter the information to receive payments when selling paid content.</p>
<p>You can choose between Paypal and bank transfer, but bank transfer involves troublesome overseas transfers, so I registered with Paypal.</p>
<figure>
    <img loading="lazy" src="/images/2019/02/10/171408/20190210160520.png"/> 
</figure>

<h2 id="tax-information">Tax Information</h2>
<p>Enter tax-related items.
The input items may differ for corporations, but for individual developers in Japan, it&rsquo;s mostly about registering the address.</p>
<figure>
    <img loading="lazy" src="/images/2019/02/10/171408/20190210161115.png"/> 
</figure>

<h2 id="registration">Registration</h2>
<p>That completes the input of registration information. After registering, an email will arrive, so click the link within the email.</p>
<h1 id="listing">Listing</h1>
<p>Now that seller registration is complete, list the created content.</p>
<p>Go to the <a href="https://publish.unrealengine.com/v2/products">Publisher Portal</a> and click the &ldquo;ADD PRODUCT&rdquo; button to proceed with registration.</p>
<figure>
    <img loading="lazy" src="/images/2019/02/10/171408/20190210161816.png"/> 
</figure>

<p>The display here changes depending on the selection state of the dropdown menu.</p>
<p>The following explanation only covers the items displayed during ObjectDeliverer&rsquo;s registration.</p>
<h2 id="registering-images">Registering Images</h2>
<p>Register the images required for listing.</p>
<ul>
<li>GALLERY<br/>
Register 25 or fewer images of 1920x1080.<br/>
These are the images displayed on your content's detail page.<br/>
For 3D models etc., I think this is where you express what's included in the content with screenshots.</li>
<li>Thumbnail<br/>
Register one image of 284x284.<br/>
Used for list displays, such as when searched on the Marketplace.</li>
<li>FEATURED IMAGE<br/>
Register one image of 894x488.<br/>
I couldn't figure out where this is used.<br/>
Maybe I just haven't found it, but the description also says "may be used," so perhaps it will be displayed somewhere in the future.</li>
</ul>
<figure>
    <img loading="lazy" src="/images/2019/02/10/171408/20190210161954.png"/> 
</figure>

<h2 id="registering-content-information">Registering Content Information</h2>
<ul>
<li>PRODUCT TITLE<br/>
Enter the name of the content to be registered.</li>
<li>Price<br/>
Select the selling price. Choose Free for free content, or select an amount from the list for paid content.</li>
<li>CATEGORY <br/>
Select the type of content to be registered.<br/>
For example, "Characters" for characters, "Materials" for materials.<br/>
Since ObjectDeliverer is a plugin, I selected "Code Plugins".</li>
</ul>
<figure>
    <img loading="lazy" src="/images/2019/02/10/171408/20190210165045.png"/> 
</figure>

<ul>
<li>THIRD PARTY SOFTWARE USAGE (Appears when Code Plugins is selected in CATEGORY)<br/>
Select whether it includes software created by a third party.<br/>
If your library references another library, select "This Product Uses Third Party Software".</li>
<li>TAGS<br/>
Enter tags related to your content.<br/>
Helps users in searching.</li>
</ul>
<figure>
    <img loading="lazy" src="/images/2019/02/10/171408/20190210165120.png"/> 
</figure>

<ul>
<li>SHORT DESCRIPTION<br/>
Register a brief description of the content.<br/>
Max 255 characters, but within 100 characters is recommended.</li>
<li>Long Description<br/>
Describe in detail within 1900 characters.<br/>
Describe videos or links for explanation here.</li>
<li>Technical Information<br/>
Describe how to use the registered content.<br/>
Links to documentation for explanation are described here.<br/>
A template is displayed in the input field, so following it should be fine, but looking at the Marketplace, displays different from this template are also seen, so it doesn't seem mandatory.</li>
</ul>
<figure>
    <img loading="lazy" src="/images/2019/02/10/171408/20190210171316.png"/> 
</figure>

<ul>
<li>PROJECT VERSIONS<br/>
Register your content files.
<p>If different files are needed for each Engine version, register multiple.</p>
<p>ObjectDeliverer supports 3 versions: 4.19, 20, 21, but since different packages are needed for each, I registered 3 files.</p>
<p>Enter the URL where the downloadable zip file for each file is located.</li></p>
</ul>
<ul>
<li>The method for creating a Plugin package is posted as a separate article here.
<a href="https://www.ayumax.net/entry/2019/02/07/235700">Creating a Package for a Custom UE4 Plugin for the Marketplace - AYU MAX</a></li>
</ul>
<figure>
    <img loading="lazy" src="/images/2019/02/10/171408/20190210165738.png"/> 
</figure>

<p>After entering everything and confirming there are no mistakes, click the &ldquo;SUBMIT FOR APPROVAL&rdquo; button to complete.</p>
<h1 id="awaiting-review">Awaiting Review</h1>
<p>An email confirming receipt will arrive at the registered email address.</p>
<p>This email also includes an estimate of when the review will take place.</p>
<p>In my case, it was &ldquo;15-20 business days&rdquo;.</p>
<p>It&rsquo;s quite a wait, but perhaps it&rsquo;s just that busy right now.</p>
<p>All that&rsquo;s left is to wait and pray it doesn&rsquo;t get rejected.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Bought a REALFORCE (R2TLS-JP4-BK)</title>
      <link>https://ayumax.net/entry/2019/02/10/144210/</link>
      <pubDate>Sun, 10 Feb 2019 14:42:10 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/02/10/144210/</guid>
      <description>&lt;h1 id=&#34;keyboard-craving&#34;&gt;Keyboard Craving&lt;/h1&gt;
&lt;p&gt;Since the end of last year, my craving for a keyboard had been growing, and after agonizing over what to do for a long time, I finally made a purchase.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;ja&#34; dir=&#34;ltr&#34;&gt;買ってしまった。&lt;br&gt;買う前はAll 30gにしようと思ってたけど、なんか軽すぎる感じがしたので45gのやつに。&lt;br&gt;やっぱり触ってから買うようにしてよかった。&lt;a href=&#34;https://twitter.com/hashtag/realforce?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#realforce&lt;/a&gt; &lt;a href=&#34;https://t.co/giz3G0Weva&#34;&gt;pic.twitter.com/giz3G0Weva&lt;/a&gt;&lt;/p&gt;&amp;mdash; ayuma (@ayuma_x) &lt;a href=&#34;https://twitter.com/ayuma_x/status/1094424051114594304?ref_src=twsrc%5Etfw&#34;&gt;February 10, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;


&lt;h1 id=&#34;the-trigger&#34;&gt;The Trigger&lt;/h1&gt;
&lt;p&gt;It all started last year when my development environment PC at work was replaced, and the keyboard became a REALFORCE.&lt;/p&gt;
&lt;p&gt;The one at work is probably the one below, which can be purchased together with a Mouse Computer PC.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="keyboard-craving">Keyboard Craving</h1>
<p>Since the end of last year, my craving for a keyboard had been growing, and after agonizing over what to do for a long time, I finally made a purchase.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">買ってしまった。<br>買う前はAll 30gにしようと思ってたけど、なんか軽すぎる感じがしたので45gのやつに。<br>やっぱり触ってから買うようにしてよかった。<a href="https://twitter.com/hashtag/realforce?src=hash&amp;ref_src=twsrc%5Etfw">#realforce</a> <a href="https://t.co/giz3G0Weva">pic.twitter.com/giz3G0Weva</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1094424051114594304?ref_src=twsrc%5Etfw">February 10, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<h1 id="the-trigger">The Trigger</h1>
<p>It all started last year when my development environment PC at work was replaced, and the keyboard became a REALFORCE.</p>
<p>The one at work is probably the one below, which can be purchased together with a Mouse Computer PC.</p>
<p><a href="http://www.realforce.co.jp/products/108UG-HiPro_YK0100/index.html">Product : REALFORCE 108UG-HiPro | REALFORCE | The pinnacle of Japanese premium keyboards</a></p>
<p>I didn&rsquo;t know much about keyboards and had used them without much preference until then.
Before that, I used the Magic Keyboard that came with my iMac.</p>
<p>So, since I was used to thin, space-saving types, I couldn&rsquo;t get used to it at first.</p>
<p>It felt big, took up space, was heavy, the keys were much deeper than the Magic Keyboard, and it just felt difficult to use.</p>
<p>However, after using it for nearly a year, I suddenly realized how pleasant it was (late, I know).</p>
<p>Then, the desire to change my home keyboard emerged.</p>
<p>At home, wanting something similar to the Magic Keyboard at the time, I was using the Microsoft one below.</p>
<p><a href="https://www.microsoft.com/accessories/en-us/products/keyboards/designer-bluetooth-desktop/7n9-00023">Designer Bluetooth Desktop | Microsoft Accessories</a></p>
<p>Although I liked its appearance, being Bluetooth, there was a delay before typing registered, and the key layout was also a bit awkward for me.</p>
<p>Also, my desk at home is small, so I was dissatisfied that a keyboard with a numeric keypad took up space.</p>
<p>So, I decided to buy a good keyboard for home as well and started considering options.</p>
<h1 id="realforce-or-hhkb">REALFORCE or HHKB?</h1>
<p>First, I considered REALFORCE, which was the trigger.</p>
<p>Wanting to save space, I first narrowed my search to tenkeyless models, but then several other parameters emerged to agonize over, such as &ldquo;Silent or Normal,&rdquo; &ldquo;APC available,&rdquo; and &ldquo;Key input weight,&rdquo; and I worried/agonized for quite a few days.</p>
<p>Also, whether to stick with a JP keyboard as before, or switch to EN.
I thought EN looked cooler, but decided on JP because I thought my head would get confused if it wasn&rsquo;t consistent with work.</p>
<p>Also, sites writing about REALFORCE often mentioned HHKB, so I researched that too.
I was ignorant before and didn&rsquo;t know, but HHKB uses Topre keys, right?</p>
<p>Also, I sometimes saw people at study sessions using small keyboards placed on top of their laptops, and I realized that the ones I saw, thinking &ldquo;they must have strong preferences,&rdquo; were likely HHKB.</p>
<p>The major differences between HHKB and REALFORCE are the number of keys and weight. Honestly, I started thinking the HHKB, which eliminates waste to the extreme, was also good, making it even harder to decide what to buy.</p>
<p>I think the decision criteria were probably:</p>
<ul>
<li>Use at home only, no carrying & prioritizing the same environment as work → REALFORCE</li>
<li>Carry it for work outside & can manage even if the environment differs from work → HHKB</li>
</ul>
<p>I summarized it like that, but couldn&rsquo;t decide.</p>
<h1 id="unable-to-decide-went-to-see-them-in-person">Unable to Decide, Went to See Them in Person</h1>
<p>Lately, I often buy things online, but for this, I thought I really needed to touch the real thing, so I went to a store.</p>
<p>First, I went to Yodobashi, but only one full-size REALFORCE was on display, and no tenkeyless models.</p>
<p>When I asked the staff, they brought out two tenkeyless EN keyboards from the back. Unfortunately, there were no JP tenkeyless models.</p>
<p>However, wanting to try more types, I went straight to Tsukumo.</p>
<p>Thinking they might not have them here either, I got excited when I found a dedicated REALFORCE section!!</p>
<p>I tried the tenkeyless models one by one from the end, and there were many things I wouldn&rsquo;t have known without actually touching them.
Specifically, knowing the following two things was significant:</p>
<ul>
<li>There's really quite a difference in sound volume between the normal and silent models (or rather, the sound quality? is different)</li>
<li>Before touching them, I thought the light ALL 30g would be good, but it was too light for me and didn't suit me</li>
</ul>
<p>I couldn&rsquo;t find HHKB at Tsukumo, and although I wondered what to do, I feared that touching it would make me hesitate and unable to decide, so I stopped searching further and decided on the REALFORCE R2TLS-JP4-BK right there.</p>
<p>The price was around 25,000 yen including tax.</p>
<p>Previously, it was an amount I would never spend on a keyboard, but I convinced myself with the strange excuse, &ldquo;It&rsquo;s cheaper than the HHKB Type-S, so I&rsquo;m lucky,&rdquo; and bought it.</p>
<h1 id="trying-it-out">Trying It Out</h1>
<p>I&rsquo;m writing this article on the day I bought it, so typing this article is essentially the trial run.</p>
<p>That&rsquo;s why it ended up longer than expected.</p>
<p>Using it, the &ldquo;thock thock&rdquo; feeling when typing is really pleasant.
The key layout is the same as the one I use at work, which is convenient, so I&rsquo;m glad I chose this one.</p>
<p>It&rsquo;s compact in size, but quite heavy, so carrying it seems tough, but I only take my PC outside about once or twice a month, so it seems acceptable.</p>
<p>I&rsquo;ll try writing on the blog again after using it for a longer period if my feelings change.</p>
<figure>
    <img loading="lazy" src="/images/2019/02/10/144210/IMG_20190210_131043.jpg"/> 
</figure>

]]></content:encoded>
    </item>
    <item>
      <title>Creating a Package for a Custom UE4 Plugin for the Marketplace</title>
      <link>https://ayumax.net/entry/2019/02/07/235700/</link>
      <pubDate>Thu, 07 Feb 2019 23:57:00 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/02/07/235700/</guid>
      <description>&lt;h1 id=&#34;submission-to-the-marketplace&#34;&gt;Submission to the Marketplace&lt;/h1&gt;
&lt;p&gt;Since the data send/receive plugin &lt;code&gt;ObjectDeliverer&lt;/code&gt; I am currently creating for Unreal Engine is aimed for submission to the Marketplace, I tried packaging it once.&lt;/p&gt;
&lt;h1 id=&#34;how-to&#34;&gt;How To&lt;/h1&gt;
&lt;p&gt;Packaging a UE4 project can be done from the Editor, so I know how to do that, but I had never packaged a Plugin before and wasn&amp;rsquo;t sure how to do it, so I searched.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://wiki.unrealengine.com/How_To_Package_Plugins_For_UE4_Marketplace&#34;&gt;How To Package Plugins For UE4 Marketplace - Epic Wiki&lt;/a&gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="submission-to-the-marketplace">Submission to the Marketplace</h1>
<p>Since the data send/receive plugin <code>ObjectDeliverer</code> I am currently creating for Unreal Engine is aimed for submission to the Marketplace, I tried packaging it once.</p>
<h1 id="how-to">How To</h1>
<p>Packaging a UE4 project can be done from the Editor, so I know how to do that, but I had never packaged a Plugin before and wasn&rsquo;t sure how to do it, so I searched.</p>
<p><a href="https://wiki.unrealengine.com/How_To_Package_Plugins_For_UE4_Marketplace">How To Package Plugins For UE4 Marketplace - Epic Wiki</a></p>
<p>I found a page that was exactly what I was looking for, so I basically followed its instructions.</p>
<h2 id="describing-whitelistplatforms">Describing WhitelistPlatforms</h2>
<p>It seems necessary to describe which platforms the package is for in the .uplugin file.
Since ObjectDeliverer has currently only been confirmed on Windows, this time I limited it to Win64 and Win32 only.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;FileVersion&#34;</span>: <span style="color:#ae81ff">3</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;Version&#34;</span>: <span style="color:#ae81ff">1</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;VersionName&#34;</span>: <span style="color:#e6db74">&#34;1.0.0&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;FriendlyName&#34;</span>: <span style="color:#e6db74">&#34;ObjectDeliverer&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;Description&#34;</span>: <span style="color:#e6db74">&#34;ObjectDeliverer is a data transmission / reception library for Unreal Engine (C ++, Blueprint). &#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;Category&#34;</span>: <span style="color:#e6db74">&#34;Programming&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;CreatedBy&#34;</span>: <span style="color:#e6db74">&#34;ayumax&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;CreatedByURL&#34;</span>: <span style="color:#e6db74">&#34;https://github.com/ayumax&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;DocsURL&#34;</span>: <span style="color:#e6db74">&#34;&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;MarketplaceURL&#34;</span>: <span style="color:#e6db74">&#34;&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;SupportURL&#34;</span>: <span style="color:#e6db74">&#34;https://github.com/ayumax/ObjectDeliverer&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;EnabledByDefault&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;CanContainContent&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;IsBetaVersion&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;Installed&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;Modules&#34;</span>: [
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;Name&#34;</span>: <span style="color:#e6db74">&#34;ObjectDeliverer&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;Type&#34;</span>: <span style="color:#e6db74">&#34;Runtime&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;LoadingPhase&#34;</span>: <span style="color:#e6db74">&#34;Default&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;WhitelistPlatforms&#34;</span>: [
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;Win64&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;Win32&#34;</span>
</span></span><span style="display:flex;"><span>      ]
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="creating-the-build-batch-file">Creating the Build Batch File</h2>
<p>Following the instructions, I created a build batch file.
I saved a file with the following content as <code>buildPlugin.bat</code>.</p>
<p>Following the explanation page, instead of the folder where the Plugin&rsquo;s .uproject is located, I created an empty build folder elsewhere and placed <code>buildPlugin.bat</code> there.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-batch" data-lang="batch"><span style="display:flex;"><span><span style="color:#e6db74">&#34;C:\Program Files\Epic Games\UE_4.21\Engine\Build\BatchFiles\RunUAT.bat&#34;</span> BuildPlugin -Plugin=<span style="color:#e6db74">&#34;C:\source\repos\ObjectDelivererTest\Plugins\ObjectDeliverer\ObjectDeliverer.uplugin&#34;</span> -Package=<span style="color:#e6db74">&#34;</span>%CD%<span style="color:#e6db74">\PluginStaging_ALL\UE4_421&#34;</span> -Rocket
</span></span></code></pre></div><h2 id="running-the-batch-file">Running the Batch File</h2>
<p>In the folder where the batch file was placed, hold down the left Shift key while right-clicking, select &ldquo;Open PowerShell window here&rdquo; to open a PowerShell console, and execute by typing <code>.buildPlugin.bat</code>.</p>
<h2 id="crushing-errors">Crushing Errors</h2>
<p>During development, I had always launched and checked with DebugGame Editor, so I hadn&rsquo;t built for Shipping.
Probably because of that, there were many places where the description was lax, and build errors occurred frequently&hellip;</p>
<p>Most of the errors were in places where includes were written abbreviatedly.</p>
<p>For example, writing <code>#include &quot;TcpSocketBuilder.h&quot;</code> where <code>#include &quot;Common/TcpSocketBuilder.h&quot;</code> should have been written.</p>
<p>Since most were of the above pattern, I rechecked and corrected the includes in all C++ sources.</p>
<h2 id="after-execution">After Execution</h2>
<p>If there were no errors during the build, waiting until it finished resulted in the <code>PluginStaging_ALL\UE4_421</code> folder being generated in the folder where the batch file was placed, containing the complete Plugin set.</p>
<h1 id="summary">Summary</h1>
<p>Referring to the page with the procedure, I succeeded in creating a package for my custom plugin.</p>
<p>Now, I need to think about the description for Marketplace submission, and what seems subtly troublesome is preparing the images for submission.
This is similar for other app stores&hellip;</p>
<p>I need to make it properly so it doesn&rsquo;t fail the review.</p>
]]></content:encoded>
    </item>
    <item>
      <title>ObjectDeliverer Log File Saving and Playback Feature</title>
      <link>https://ayumax.net/entry/2019/02/07/001029/</link>
      <pubDate>Thu, 07 Feb 2019 00:10:29 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/02/07/001029/</guid>
      <description>&lt;h1 id=&#34;recording-communication-content&#34;&gt;Recording Communication Content&lt;/h1&gt;
&lt;p&gt;When implementing communication features, there are almost always times when you want to reproduce the situation later.&lt;br/&gt;
This is especially essential when the environment of the communication partner is difficult to prepare.&lt;/p&gt;
&lt;p&gt;Therefore, I implemented a feature in ObjectDeliverer to save communication content to a log file and play it back.&lt;/p&gt;
&lt;h1 id=&#34;sample&#34;&gt;Sample&lt;/h1&gt;
&lt;p&gt;Here is a sample using the save and playback features.&lt;/p&gt;
&lt;p&gt;The communication content here is a captured bitmap of 800px x 450px 32bit ARGB, so 1,440,000 bytes = (800 x 450 x 4) of data are sent and received every 60fps (=16.66ms).&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="recording-communication-content">Recording Communication Content</h1>
<p>When implementing communication features, there are almost always times when you want to reproduce the situation later.<br/>
This is especially essential when the environment of the communication partner is difficult to prepare.</p>
<p>Therefore, I implemented a feature in ObjectDeliverer to save communication content to a log file and play it back.</p>
<h1 id="sample">Sample</h1>
<p>Here is a sample using the save and playback features.</p>
<p>The communication content here is a captured bitmap of 800px x 450px 32bit ARGB, so 1,440,000 bytes = (800 x 450 x 4) of data are sent and received every 60fps (=16.66ms).</p>
<p>The data flow repeats as follows:
[WPF App] → (Shared Memory) → [UE4 App] → (Log File)</p>
<p>Since the video capture for recording was also running in parallel, it was quite choppy, but it managed to work somehow.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ObjectDelivererのログ保存機能と再生機能のサンプル。<br>WPFのアプリの映像を共有メモリ経由で表示しながらログファイルに保存して、後から読み込んでもう一度再現してます。<br>ちょっと重くてカクついてますが。<a href="https://twitter.com/hashtag/UE4?src=hash&amp;ref_src=twsrc%5Etfw">#UE4</a> <a href="https://twitter.com/hashtag/UE4Study?src=hash&amp;ref_src=twsrc%5Etfw">#UE4Study</a> <a href="https://twitter.com/hashtag/ObjectDeliverer?src=hash&amp;ref_src=twsrc%5Etfw">#ObjectDeliverer</a> <a href="https://t.co/fbdxyxK9nO">pic.twitter.com/fbdxyxK9nO</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1093157903744196610?ref_src=twsrc%5Etfw">February 6, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<h1 id="log-file-saving-feature">Log File Saving Feature</h1>
<p>Set and use <code>ProtocolLogWriter</code> during ObjectDeliverer&rsquo;s Start.</p>
<p>Calling <code>Send</code> writes data to the log file.</p>
<p>Each write to the log file also records the elapsed time from the start in millisecond order.</p>
<figure>
    <img loading="lazy" src="/images/2019/02/07/001029/20190206235934.png"/> 
</figure>

<h1 id="log-file-playback-feature">Log File Playback Feature</h1>
<p>Set and use <code>ProtocolLogReader</code> during ObjectDeliverer&rsquo;s Start.</p>
<figure>
    <img loading="lazy" src="/images/2019/02/07/001029/20190207000232.png"/> 
</figure>

<p>Calling Start triggers the <code>ReceiveData</code> event each time the time recorded in the log file elapses.
Therefore, you can process the received data just like in normal communication with a partner.</p>
<figure>
    <img loading="lazy" src="/images/2019/02/07/001029/20190207000419.png"/> 
</figure>

<h1 id="summary">Summary</h1>
<p>By implementing the log file saving and playback features, I was able to cover a significant portion of the functionality I initially wanted to implement in ObjectDeliverer.</p>
<p>All that remains is to implement Object sending/receiving using serialization with MessagePack, and then it will be a good stopping point.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Got Stuck with BlueprintNativeEvent</title>
      <link>https://ayumax.net/entry/2019/01/31/222137/</link>
      <pubDate>Thu, 31 Jan 2019 22:21:37 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/01/31/222137/</guid>
      <description>&lt;h1 id=&#34;what-i-got-stuck-on&#34;&gt;What I Got Stuck On&lt;/h1&gt;
&lt;p&gt;Today&amp;rsquo;s article is a memo recording a problem I encountered recently.
By the way, I still don&amp;rsquo;t know the exact cause and am currently using a workaround.&lt;/p&gt;
&lt;p&gt;In the Plugin I&amp;rsquo;m currently creating, I wanted to override functions in both C++ and Blueprint, so I implemented the pattern below in various places.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;UFUNCTION(BlueprintNativeEvent, Category &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ObjectDeliverer&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; Start();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;virtual&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Start_Implementation&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the example above, &lt;code&gt;Start()&lt;/code&gt; is expected to be called from another C++ class.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="what-i-got-stuck-on">What I Got Stuck On</h1>
<p>Today&rsquo;s article is a memo recording a problem I encountered recently.
By the way, I still don&rsquo;t know the exact cause and am currently using a workaround.</p>
<p>In the Plugin I&rsquo;m currently creating, I wanted to override functions in both C++ and Blueprint, so I implemented the pattern below in various places.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>UFUNCTION(BlueprintNativeEvent, Category <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;ObjectDeliverer&#34;</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> Start();
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">virtual</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">Start_Implementation</span>();
</span></span></code></pre></div><p>In the example above, <code>Start()</code> is expected to be called from another C++ class.</p>
<p>The intention was that a C++ class inheriting this class would override <code>Start_Implementation()</code>, and a Blueprint would override <code>Start()</code>, making it okay to inherit the class in either way.</p>
<p>After implementing and running it, it seemed to work fine for a while, but I noticed it occasionally crashed when <code>Start()</code> was called.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">うーん、このProcessEventのIsUnreachableにひっかかって落ちる問題なんだ？<br>BlueprintNativeEventの関数使っているところが該当するってことはわかったんだけど、どう直したらよいのか不明だ。</p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1090251296286724096?ref_src=twsrc%5Etfw">January 29, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>Debugging and tracing it, I found that <code>ProcessEvent</code> was called within <code>Start()</code>, and the function was being executed via reflection.</p>
<p>I understood that it was crashing at the <code>check(!IsUnreachable)</code> within it, but I have no idea why that was happening.</p>
<p>Does <code>IsUnreachable</code> mean it became a target for Garbage Collection (GC)??? I thought, and checked the code, but it was properly held by a variable specified with <code>UPROPERTY()</code>.</p>
<p>Just in case, I decided to try another approach and also tried the content of the article below, but the phenomenon didn&rsquo;t change.</p>
<p><a href="https://qiita.com/go_astrayer/items/11b99ef8849b43796fee">How to prevent an object from being garbage collected without using UPROPERTY - Qiita</a></p>
<p>Even among the places using <code>BlueprintNativeEvent</code>, it crashed at two different timings: sometime after startup, and during <code>BeginDestroy</code>.</p>
<p><code>BeginDestroy</code> is still understandable, perhaps such function calls shouldn&rsquo;t be made during termination, but I don&rsquo;t understand the other pattern.</p>
<p>However, what&rsquo;s slightly unusual is that it crashes within a worker thread run using <code>FRunnableThread</code>, so I wonder if that&rsquo;s related.</p>
<p>In the end, I couldn&rsquo;t figure out the cause or how to fix it, leading to the pathetic conclusion of giving up on Blueprint overriding and removing <code>BlueprintNativeEvent</code>, changing it to a normal virtual function.</p>
<p>After that, it stopped crashing completely, which is good for now, but it&rsquo;s bothering me, so I want to take the time to investigate it properly somewhere.</p>
<p>The fact that it doesn&rsquo;t crash afterwards means it wasn&rsquo;t collected by GC, which makes it even more confusing&hellip;</p>
]]></content:encoded>
    </item>
    <item>
      <title>Video Synchronization Using ObjectDeliverer Shared Memory</title>
      <link>https://ayumax.net/entry/2019/01/30/233143/</link>
      <pubDate>Wed, 30 Jan 2019 23:31:43 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/01/30/233143/</guid>
      <description>&lt;h1 id=&#34;sample-explanation&#34;&gt;Sample Explanation&lt;/h1&gt;
&lt;p&gt;This article explains the implementation of the shared memory sample I wrote about &lt;a href=&#34;https://www.ayumax.net/entry/2019/01/29/225525&#34;&gt;yesterday&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;ja&#34; dir=&#34;ltr&#34;&gt;ObjectDelivererの共有メモリのテスト題材作成中。&lt;br&gt;WPFアプリが毎フレーム自分のウィンドウを共有メモリに書き込んで、それをUE4側が読み込みテクスチャを更新してる。&lt;a href=&#34;https://twitter.com/hashtag/ObjectDeliverer?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#ObjectDeliverer&lt;/a&gt; &lt;a href=&#34;https://twitter.com/hashtag/UE4?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#UE4&lt;/a&gt; &lt;a href=&#34;https://twitter.com/hashtag/UE4Study?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#UE4Study&lt;/a&gt; &lt;a href=&#34;https://t.co/uWY2QhHnYP&#34;&gt;pic.twitter.com/uWY2QhHnYP&lt;/a&gt;&lt;/p&gt;&amp;mdash; ayuma (@ayuma_x) &lt;a href=&#34;https://twitter.com/ayuma_x/status/1090203272730664960?ref_src=twsrc%5Etfw&#34;&gt;January 29, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;


&lt;h1 id=&#34;wpf-app-side&#34;&gt;WPF App Side&lt;/h1&gt;
&lt;p&gt;The WPF side writes the display content of its own window to shared memory.&lt;/p&gt;
&lt;p&gt;The complete source code is in the following repository.&lt;/p&gt;
&lt;div class=&#34;github-card&#34; data-user=&#34;ayumax&#34; data-repo=&#34;CaptureToSharedMemory&#34; data-width=&#34;400&#34; data-height=&#34;&#34; data-theme=&#34;default&#34;&gt;&lt;/div&gt;
&lt;script src=&#34;https://cdn.jsdelivr.net/github-cards/latest/widget.js&#34;&gt;&lt;/script&gt;
&lt;h2 id=&#34;creating-shared-memory&#34;&gt;Creating Shared Memory&lt;/h2&gt;
&lt;p&gt;Create shared memory named &amp;ldquo;SharedMemory&amp;rdquo; with a size of 800 * 450 * 4 + 5.
This size can store a bitmap of 800 pixels width, 450 pixels height, and 32-bit BGRA format.
The final +5 is for the header elements used by ObjectDeliverer shared memory.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="sample-explanation">Sample Explanation</h1>
<p>This article explains the implementation of the shared memory sample I wrote about <a href="https://www.ayumax.net/entry/2019/01/29/225525">yesterday</a>.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ObjectDelivererの共有メモリのテスト題材作成中。<br>WPFアプリが毎フレーム自分のウィンドウを共有メモリに書き込んで、それをUE4側が読み込みテクスチャを更新してる。<a href="https://twitter.com/hashtag/ObjectDeliverer?src=hash&amp;ref_src=twsrc%5Etfw">#ObjectDeliverer</a> <a href="https://twitter.com/hashtag/UE4?src=hash&amp;ref_src=twsrc%5Etfw">#UE4</a> <a href="https://twitter.com/hashtag/UE4Study?src=hash&amp;ref_src=twsrc%5Etfw">#UE4Study</a> <a href="https://t.co/uWY2QhHnYP">pic.twitter.com/uWY2QhHnYP</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1090203272730664960?ref_src=twsrc%5Etfw">January 29, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<h1 id="wpf-app-side">WPF App Side</h1>
<p>The WPF side writes the display content of its own window to shared memory.</p>
<p>The complete source code is in the following repository.</p>
<div class="github-card" data-user="ayumax" data-repo="CaptureToSharedMemory" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<h2 id="creating-shared-memory">Creating Shared Memory</h2>
<p>Create shared memory named &ldquo;SharedMemory&rdquo; with a size of 800 * 450 * 4 + 5.
This size can store a bitmap of 800 pixels width, 450 pixels height, and 32-bit BGRA format.
The final +5 is for the header elements used by ObjectDeliverer shared memory.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#66d9ef">private</span> MemoryMappedFile share_mem;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">private</span> MemoryMappedViewAccessor accessor;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>share_mem = MemoryMappedFile.CreateOrOpen(<span style="color:#e6db74">&#34;SharedMemory&#34;</span>, <span style="color:#ae81ff">800</span> * <span style="color:#ae81ff">450</span> * <span style="color:#ae81ff">4</span> + <span style="color:#ae81ff">5</span>);
</span></span><span style="display:flex;"><span>accessor = share_mem.CreateViewAccessor();
</span></span></code></pre></div><h2 id="hooking-into-wpf-frame-rendering-timing">Hooking into WPF Frame Rendering Timing</h2>
<p>Monitor the <code>CompositionTarget.Rendering</code> event to enable processing on every rendering frame.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span>CompositionTarget.Rendering += CompositionTarget_Rendering;
</span></span></code></pre></div><h2 id="writing-display-content-to-bitmap">Writing Display Content to Bitmap</h2>
<p><code>Root</code> is the Name given to the control whose display content is to be obtained.
First, get the size of the display area using <code>VisualTreeHelper.GetDescendantBounds</code>, and create a <code>RenderTargetBitmap</code> matching that size.</p>
<p>Next, create a <code>DrawingVisual</code> and then write the display content to the bitmap.
Once writing is complete, copy the content of the bitmap&rsquo;s pixel buffer into a byte array.
This byte array is what we need this time.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> visual = Root;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> bounds = VisualTreeHelper.GetDescendantBounds(visual);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> bitmap = <span style="color:#66d9ef">new</span> RenderTargetBitmap(
</span></span><span style="display:flex;"><span>            (<span style="color:#66d9ef">int</span>)bounds.Width,
</span></span><span style="display:flex;"><span>            (<span style="color:#66d9ef">int</span>)bounds.Height,
</span></span><span style="display:flex;"><span>            <span style="color:#ae81ff">96.0</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#ae81ff">96.0</span>,
</span></span><span style="display:flex;"><span>            PixelFormats.Pbgra32);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> dv = <span style="color:#66d9ef">new</span> DrawingVisual();
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">using</span> (<span style="color:#66d9ef">var</span> dc = dv.RenderOpen())
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">var</span> vb = <span style="color:#66d9ef">new</span> VisualBrush(visual);
</span></span><span style="display:flex;"><span>      dc.DrawRectangle(vb, <span style="color:#66d9ef">null</span>, bounds);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>bitmap.Render(dv);
</span></span><span style="display:flex;"><span>bitmap.Freeze();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> buffer = <span style="color:#66d9ef">new</span> <span style="color:#66d9ef">byte</span>[<span style="color:#ae81ff">800</span> * <span style="color:#ae81ff">450</span> * <span style="color:#ae81ff">4</span>];
</span></span><span style="display:flex;"><span>bitmap.CopyPixels(buffer, <span style="color:#ae81ff">800</span> * <span style="color:#ae81ff">4</span>, <span style="color:#ae81ff">0</span>);
</span></span></code></pre></div><h2 id="writing-to-shared-memory">Writing to Shared Memory</h2>
<p>Finally, perform the write to shared memory.</p>
<p>First, to conform to the ObjectDeliverer format, write a 1-byte counter.
ObjectDeliverer only reads the subsequent content if this counter&rsquo;s number changes, so it&rsquo;s incremented with each write.</p>
<p>After the counter, write the size of the pixel buffer.</p>
<p>Next, copy the content of the pixel buffer, and it&rsquo;s complete.</p>
<p>The above writing is performed every frame.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#75715e">// write counter</span>
</span></span><span style="display:flex;"><span>accessor.Write(<span style="color:#ae81ff">0</span>, counter++);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// write buffer size</span>
</span></span><span style="display:flex;"><span>accessor.Write(<span style="color:#ae81ff">1</span>, (<span style="color:#66d9ef">int</span>)buffer.Length); <span style="color:#75715e">// Cast to int for Write</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// write buffer</span>
</span></span><span style="display:flex;"><span>accessor.WriteArray(<span style="color:#ae81ff">5</span>, buffer, <span style="color:#ae81ff">0</span>, buffer.Length);
</span></span></code></pre></div><h1 id="ue4-side">UE4 Side</h1>
<p>The UE4 side reads the pixel buffer from shared memory using ObjectDeliverer and updates the texture using its content.</p>
<h2 id="creating-a-texture-helper-class">Creating a Texture Helper Class</h2>
<p>As preparation for the necessary functionality, create a <code>UTextureUtil</code> class in C++.</p>
<p>Implement the following two functions in it.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">// Fill out your copyright notice in the Description page of Project Settings.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#pragma once
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;CoreMinimal.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;Kismet/BlueprintFunctionLibrary.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;Engine/Texture2D.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;TextureUtil.generated.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">/**
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> *
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> */</span>
</span></span><span style="display:flex;"><span>UCLASS()
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">OBJECTDELIVERER_API</span> UTextureUtil : <span style="color:#66d9ef">public</span> UBlueprintFunctionLibrary
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    GENERATED_BODY()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>    UFUNCTION(BlueprintPure, Category <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;ObjectDeliverer Test&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">static</span> UTexture2D<span style="color:#f92672">*</span> CreateTexture(int32 Width, int32 Height);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    UFUNCTION(BlueprintCallable, Category <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;ObjectDeliverer Test&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> UpdateTexture(UTexture2D<span style="color:#f92672">*</span> Texture, <span style="color:#66d9ef">const</span> TArray<span style="color:#f92672">&lt;</span>uint8<span style="color:#f92672">&gt;&amp;</span> PixelsBuffer);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Fill out your copyright notice in the Description page of Project Settings.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;TextureUtil.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;Engine/Texture2D.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;RenderingThread.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>UTexture2D<span style="color:#f92672">*</span> UTextureUtil<span style="color:#f92672">::</span>CreateTexture(int32 Width, int32 Height)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">auto</span> Texture <span style="color:#f92672">=</span> UTexture2D<span style="color:#f92672">::</span>CreateTransient(Width, Height, PF_B8G8R8A8);
</span></span><span style="display:flex;"><span><span style="color:#75715e">#if WITH_EDITORONLY_DATA
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    Texture<span style="color:#f92672">-&gt;</span>MipGenSettings <span style="color:#f92672">=</span> TMGS_NoMipmaps;
</span></span><span style="display:flex;"><span><span style="color:#75715e">#endif
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    Texture<span style="color:#f92672">-&gt;</span>CompressionSettings <span style="color:#f92672">=</span> TC_VectorDisplacementmap;
</span></span><span style="display:flex;"><span>    Texture<span style="color:#f92672">-&gt;</span>SRGB <span style="color:#f92672">=</span> false;
</span></span><span style="display:flex;"><span>    Texture<span style="color:#f92672">-&gt;</span>UpdateResource();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> Texture;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> UTextureUtil<span style="color:#f92672">::</span>UpdateTexture(UTexture2D<span style="color:#f92672">*</span> Texture, <span style="color:#66d9ef">const</span> TArray<span style="color:#f92672">&lt;</span>uint8<span style="color:#f92672">&gt;&amp;</span> PixelsBuffer)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>Texture <span style="color:#f92672">||</span> <span style="color:#f92672">!</span>Texture<span style="color:#f92672">-&gt;</span>Resource <span style="color:#f92672">||</span> PixelsBuffer.Num() <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    FUpdateTextureRegion2D<span style="color:#f92672">*</span> Region <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> FUpdateTextureRegion2D(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>, Texture<span style="color:#f92672">-&gt;</span>GetSizeX(), Texture<span style="color:#f92672">-&gt;</span>GetSizeY());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">FUpdateTextureRegionsData</span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        UTexture2D<span style="color:#f92672">*</span> Texture;
</span></span><span style="display:flex;"><span>        int32 MipIndex;
</span></span><span style="display:flex;"><span>        uint32 NumRegions;
</span></span><span style="display:flex;"><span>        FUpdateTextureRegion2D<span style="color:#f92672">*</span> Regions;
</span></span><span style="display:flex;"><span>        uint32 SrcPitch;
</span></span><span style="display:flex;"><span>        uint32 SrcBpp;
</span></span><span style="display:flex;"><span>        uint8<span style="color:#f92672">*</span> SrcData;
</span></span><span style="display:flex;"><span>    };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    FUpdateTextureRegionsData<span style="color:#f92672">*</span> RegionData <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> FUpdateTextureRegionsData;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    RegionData<span style="color:#f92672">-&gt;</span>Texture <span style="color:#f92672">=</span> Texture;
</span></span><span style="display:flex;"><span>    RegionData<span style="color:#f92672">-&gt;</span>MipIndex <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    RegionData<span style="color:#f92672">-&gt;</span>NumRegions <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>    RegionData<span style="color:#f92672">-&gt;</span>Regions <span style="color:#f92672">=</span> Region;
</span></span><span style="display:flex;"><span>    RegionData<span style="color:#f92672">-&gt;</span>SrcPitch <span style="color:#f92672">=</span> (uint32)(<span style="color:#ae81ff">4</span> <span style="color:#f92672">*</span> Texture<span style="color:#f92672">-&gt;</span>GetSizeX());
</span></span><span style="display:flex;"><span>    RegionData<span style="color:#f92672">-&gt;</span>SrcBpp <span style="color:#f92672">=</span> <span style="color:#ae81ff">4</span>;
</span></span><span style="display:flex;"><span>    RegionData<span style="color:#f92672">-&gt;</span>SrcData <span style="color:#f92672">=</span> (uint8<span style="color:#f92672">*</span>)PixelsBuffer.GetData();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    ENQUEUE_RENDER_COMMAND(UpdateTextureRegionsData)(
</span></span><span style="display:flex;"><span>        [RegionData](FRHICommandListImmediate<span style="color:#f92672">&amp;</span> RHICmdList)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            RHIUpdateTexture2D(
</span></span><span style="display:flex;"><span>                RegionData<span style="color:#f92672">-&gt;</span>Texture<span style="color:#f92672">-&gt;</span>Resource<span style="color:#f92672">-&gt;</span>TextureRHI<span style="color:#f92672">-&gt;</span>GetTexture2D(),
</span></span><span style="display:flex;"><span>                RegionData<span style="color:#f92672">-&gt;</span>MipIndex,
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">*</span>RegionData<span style="color:#f92672">-&gt;</span>Regions,
</span></span><span style="display:flex;"><span>                RegionData<span style="color:#f92672">-&gt;</span>SrcPitch,
</span></span><span style="display:flex;"><span>                RegionData<span style="color:#f92672">-&gt;</span>SrcData
</span></span><span style="display:flex;"><span>            );
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">delete</span> RegionData<span style="color:#f92672">-&gt;</span>Regions;
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">delete</span> RegionData;
</span></span><span style="display:flex;"><span>        });
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><code>CreateTexture</code> is a function to create a texture of the specified size.
<code>UpdateTexture</code> is a function to write the pixel buffer into the content of the passed texture.
(Note: UpdateTexture implementation updated to use render thread for safety)</p>
<h2 id="creating-a-real-time-updating-material">Creating a Real-time Updating Material</h2>
<p>Prepare a simple material like the one below.
Just set the parameter name of <code>TextureSampleParameter2D</code> to &ldquo;Tex&rdquo; and plug it into Base Color.</p>
<figure>
    <img loading="lazy" src="/images/2019/01/30/233143/20190130231141.png"/> 
</figure>

<h2 id="creating-an-actor">Creating an Actor</h2>
<p>Create an empty Actor and place a Cube inside it.</p>
<figure>
    <img loading="lazy" src="/images/2019/01/30/233143/20190130231706.png"/> 
</figure>

<h2 id="implementing-logic-in-the-actor">Implementing Logic in the Actor</h2>
<p>Connect the nodes sequentially in BeginPlay.</p>
<h3 id="creating-the-texture">Creating the Texture</h3>
<p>Create the texture using the pre-created <code>UTextureUtil::CreateTexture</code>.</p>
<p>Set the texture size to 800x450 to match the WPF bitmap size.
<figure>
    <img loading="lazy" src="/images/2019/01/30/233143/20190130232004.png"/> 
</figure>
</p>
<h3 id="creating-dynamic-material-and-setting-texture">Creating Dynamic Material and Setting Texture</h3>
<p>Create a Dynamic Material for the Cube and set the previously created texture to the material&rsquo;s &ldquo;Tex&rdquo; parameter.</p>
<p>Now, the texture display will be reflected in the material.</p>
<figure>
    <img loading="lazy" src="/images/2019/01/30/233143/20190130232145.png"/> 
</figure>

<h3 id="registering-objectdeliverer-receive-event">Registering ObjectDeliverer Receive Event</h3>
<p>Create an instance of ObjectDelivererManager and monitor the <code>ReceiveData</code> event.</p>
<p>When the event occurs, update the content of the previously created texture using <code>UTextureUtil::UpdateTexture</code>.</p>
<figure>
    <img loading="lazy" src="/images/2019/01/30/233143/20190130232351.png"/> 
</figure>

<h3 id="starting-objectdeliverer">Starting ObjectDeliverer</h3>
<p>Plug in the SharedMemory Protocol and Start.</p>
<p>For SharedMemory, specify the same name as the shared memory created in WPF, and for the size, specify the bitmap size (800x450x4 = 1,440,000 bytes).</p>
<p>Do not include the 5 bytes for the header in this size.</p>
<figure>
    <img loading="lazy" src="/images/2019/01/30/233143/20190130232550.png"/> 
</figure>

<h3 id="entire-blueprint">Entire Blueprint</h3>
<p>Connecting the above Blueprints results in the following:</p>
<figure>
    <img loading="lazy" src="/images/2019/01/30/233143/20190130232902.png"/> 
</figure>

<h1 id="done">Done!</h1>
<p>After implementing the above and launching both the WPF application and the UE4 application, the content displayed in the WPF window will be displayed on the surface of the UE4 Cube.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Adding Shared Memory Protocol to ObjectDeliverer</title>
      <link>https://ayumax.net/entry/2019/01/29/225525/</link>
      <pubDate>Tue, 29 Jan 2019 22:55:25 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/01/29/225525/</guid>
      <description>&lt;h1 id=&#34;shared-memory-feature&#34;&gt;Shared Memory Feature&lt;/h1&gt;
&lt;p&gt;I have added a shared memory protocol implementation to my custom UE4 library, &lt;a href=&#34;https://www.ayumax.net/entry/2019/01/28/000355&#34;&gt;ObjectDeliverer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This allows data transfer using shared memory in addition to the previously implemented TCP/IP and UDP.
However, shared memory is Windows Only&amp;hellip;&lt;/p&gt;
&lt;h1 id=&#34;how-to-use&#34;&gt;How to Use&lt;/h1&gt;
&lt;p&gt;Since it&amp;rsquo;s implemented as a protocol for ObjectDeliverer, you can use it simply by switching the protocol passed to the ObjectDelivererManager&amp;rsquo;s Start method.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;deliverer&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;Start(UProtocolFactory&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;CreateProtocolSharedMemory(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;memory_test&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1024&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 UPacketRuleFactory&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;CreatePacketRuleSizeBody());
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pass the shared memory name and memory size to &lt;code&gt;CreateProtocolSharedMemory&lt;/code&gt;.
These two values must be the same as the counterpart exchanging data.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="shared-memory-feature">Shared Memory Feature</h1>
<p>I have added a shared memory protocol implementation to my custom UE4 library, <a href="https://www.ayumax.net/entry/2019/01/28/000355">ObjectDeliverer</a>.</p>
<p>This allows data transfer using shared memory in addition to the previously implemented TCP/IP and UDP.
However, shared memory is Windows Only&hellip;</p>
<h1 id="how-to-use">How to Use</h1>
<p>Since it&rsquo;s implemented as a protocol for ObjectDeliverer, you can use it simply by switching the protocol passed to the ObjectDelivererManager&rsquo;s Start method.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>deliverer<span style="color:#f92672">-&gt;</span>Start(UProtocolFactory<span style="color:#f92672">::</span>CreateProtocolSharedMemory(<span style="color:#e6db74">&#34;memory_test&#34;</span>, <span style="color:#ae81ff">1024</span>),
</span></span><span style="display:flex;"><span>                 UPacketRuleFactory<span style="color:#f92672">::</span>CreatePacketRuleSizeBody());
</span></span></code></pre></div><p>Pass the shared memory name and memory size to <code>CreateProtocolSharedMemory</code>.
These two values must be the same as the counterpart exchanging data.</p>
<h1 id="specification">Specification</h1>
<p>To use it as a data send/receive protocol, the content of the created shared memory is polled periodically.
However, accessing the data every time increases processing load, so it&rsquo;s handled with the following mechanism:</p>
<table>
<thead>
<tr>
<th>Block</th>
<th>Size (byte)</th>
<th>Content</th>
</tr>
</thead>
<tbody>
<tr>
<td>Counter</td>
<td>1</td>
<td>Incremented each time data is written</td>
</tr>
<tr>
<td>Size</td>
<td>4</td>
<td>Size of the data part</td>
</tr>
<tr>
<td>Data</td>
<td>n</td>
<td>The written data</td>
</tr>
</tbody>
</table>
<p>During periodic polling, it first reads the first byte of the shared memory and checks if the counter value differs from the previous read.</p>
<p>If it differs, it determines that new data has been written, reads the next 4 bytes to confirm the data size, and then reads the data body.</p>
<p>Therefore, when exchanging data using shared memory with a process not using ObjectDeliverer, it needs to conform to this specification.</p>
<h1 id="sample">Sample</h1>
<p>Using the shared memory protocol created this time, I made a sample like the movie below.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ObjectDelivererの共有メモリのテスト題材作成中。<br>WPFアプリが毎フレーム自分のウィンドウを共有メモリに書き込んで、それをUE4側が読み込みテクスチャを更新してる。<a href="https://twitter.com/hashtag/ObjectDeliverer?src=hash&amp;ref_src=twsrc%5Etfw">#ObjectDeliverer</a> <a href="https://twitter.com/hashtag/UE4?src=hash&amp;ref_src=twsrc%5Etfw">#UE4</a> <a href="https://twitter.com/hashtag/UE4Study?src=hash&amp;ref_src=twsrc%5Etfw">#UE4Study</a> <a href="https://t.co/uWY2QhHnYP">pic.twitter.com/uWY2QhHnYP</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1090203272730664960?ref_src=twsrc%5Etfw">January 29, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>A WPF application writes its window display content to shared memory every frame, and the UE4 side receives the data using ObjectDeliverer.</p>
<p>Using the received data (pixel buffer), it updates the texture content, mirroring the WPF side on the UE4 display side.</p>
<p>Since it&rsquo;s shared memory, it can only be used if both applications are on the same machine, but at a glance, it seems to synchronize without delay.</p>
<p>For reference, the WPF app created here is ↓.</p>
<div class="github-card" data-user="ayumax" data-repo="CaptureToSharedMemory" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<h1 id="issue">Issue</h1>
<p><s>When mirroring as described above for a long time, a phenomenon occurs where it crashes due to hitting the <code>!IsUnreachable()</code> check in <code>UObject::ProcessEvent</code> during shared memory reading.</s></p>
<p><s>It&rsquo;s unusable unless this is fixed.</s></p>
<p>As a temporary fix, removing all uses of <code>BlueprintNativeEvent</code> resolved the issue.
However, this prevents overriding in Blueprint, so I will consider that area again.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Easy Inter-Process Communication in UE4 with ObjectDeliverer</title>
      <link>https://ayumax.net/entry/2019/01/28/000355/</link>
      <pubDate>Mon, 28 Jan 2019 00:03:55 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/01/28/000355/</guid>
      <description>&lt;h1 id=&#34;inter-process-communication-in-ue4&#34;&gt;Inter-Process Communication in UE4&lt;/h1&gt;
&lt;p&gt;I often link applications developed with Unreal Engine to apps created with C# etc., and the most common method I use for this is socket communication like TCP/IP or UDP.&lt;/p&gt;
&lt;p&gt;Until now, whenever needed, I created features tailored to the specifications at that time.&lt;/p&gt;
&lt;p&gt;However, implementing this each time is tedious, and the communication part is delicate, making it prone to bugs if not built properly.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="inter-process-communication-in-ue4">Inter-Process Communication in UE4</h1>
<p>I often link applications developed with Unreal Engine to apps created with C# etc., and the most common method I use for this is socket communication like TCP/IP or UDP.</p>
<p>Until now, whenever needed, I created features tailored to the specifications at that time.</p>
<p>However, implementing this each time is tedious, and the communication part is delicate, making it prone to bugs if not built properly.</p>
<p>Therefore, I aimed for reusability by turning it into a plugin.</p>
<p>Although there are still planned items yet to be implemented,
the current implementation can be checked from the following repository.</p>
<div class="github-card" data-user="ayumax" data-repo="ObjectDeliverer" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<p>Basic usage should be understandable from the README, but since it&rsquo;s written in my weak English, it might be hard to read&hellip;</p>
<p>So, I&rsquo;ll write it again in this article.</p>
<h1 id="concept">Concept</h1>
<p>The plugin I created this time (ObjectDeliverer) is based on the following three concepts.</p>
<h2 id="compactness">Compactness</h2>
<p>UE4&rsquo;s socket communication, especially TCP/IP implementation, is quite low-level, requiring more implementation effort compared to C# etc.</p>
<p>While this introduces some constraints, the design concept was to make the implementation amount as compact as possible when using it.</p>
<h2 id="usability-in-blueprint">Usability in Blueprint</h2>
<p>Another concept was to make it usable in Blueprint, which is a strength of UE4. Although more could be done if it were a C++ only plugin abandoning Blueprint support, I insisted on this.</p>
<h2 id="preventing-blueprint-disconnection">Preventing Blueprint Disconnection</h2>
<p>ObjectDeliverer supports multiple communication protocols (with plans to add more), but if they were implemented as separate types, switching the protocol type in an already implemented Blueprint would cause disconnection.</p>
<p>Therefore, I aimed for a design that minimizes disconnection as much as possible during specification changes after implementation.</p>
<h1 id="feature-explanation">Feature Explanation</h1>
<p>Here&rsquo;s a brief explanation of ObjectDeliverer&rsquo;s features.</p>
<h2 id="communication-protocols">Communication Protocols</h2>
<p>Currently, the following four protocols are supported.</p>
<ul>
<li>TCP/IP Server (supports multiple client connections)</li>
<li>TCP/IP Client</li>
<li>UDP (Send only)</li>
<li>UDP (Receive only)</li>
</ul>
<p>TCP/IP supports both sending and receiving for both server and client.</p>
<p>In a situation where multiple clients are connected to the server, the default setting is to broadcast transmissions from the server.</p>
<p>For UDP, I hesitated, but considering that use cases for UDP rarely involve simultaneous sending and receiving, I separated them.
Of course, using both simultaneously enables sending and receiving.</p>
<h2 id="data-splitting-rules">Data Splitting Rules</h2>
<p>In UDP, received data is often treated as a single data unit per reception. However, in TCP/IP, received data might arrive partially, or multiple data units might arrive combined, necessitating splitting rules.</p>
<p>Therefore, I have currently implemented three splitting rules that I often use.</p>
<ul>
<li>Fixed Size</li>
<li>Header + Body</li>
<li>Terminator Symbol</li>
</ul>
<p>The fixed-size method divides data into chunks of a predetermined size every time.
Even if the sent/received data size is less than the fixed size, the fixed size amount must be sent.</p>
<p>Conversely, it does not support cases where the data size to be sent in one go exceeds the fixed size.</p>
<p>In the Header + Body format, the body size is stored at the beginning of the data.</p>
<p>Therefore, the receiving side first reads the size field to recognize the size of the following body part, and then reads the body.</p>
<p>The byte count and endianness of the size part can be changed externally.</p>
<p>Personally, I find this the most convenient.</p>
<p>The final terminator symbol method was created to support common patterns like &ldquo;delimited by newline characters&rdquo;.</p>
<h2 id="sendreceive-data-format">Send/Receive Data Format</h2>
<p>By default, ObjectDeliverer sends and receives data in byte array format (TArray<uint8>).</p>
<p>However, by using an option called DeliveryBox, it&rsquo;s possible to send and receive strings or objects directly.</p>
<p>Currently, the following two patterns are supported.</p>
<ul>
<li>UTF-8 String</li>
<li>UObject via JSON string format</li>
</ul>
<h1 id="how-to-use">How to Use</h1>
<p>Clone the GitHub repository and copy the Plugins folder into your project folder to use it.
Please enable the ObjectDeliverer plugin in the Editor.</p>
<h2 id="usage-in-blueprint">Usage in Blueprint</h2>
<ol>
<li>Create an instance of ObjectDelivererManager.</li>
<li>If necessary, create an instance of DeliveryBox.</li>
<li>Set the Protocol and PacketRule for the ObjectDelivererManager and call the Start method.</li>
</ol>
<p><a href="https://user-images.githubusercontent.com/8191970/51612470-de671900-1f64-11e9-83eb-993b6e8c2a12.PNG" class="http-image" target="_blank"><img src="https://user-images.githubusercontent.com/8191970/51612470-de671900-1f64-11e9-83eb-993b6e8c2a12.PNG" class="http-image" alt="Blueprint Setup Example"/></a></p>
<h2 id="usage-in-c">Usage in C++</h2>
<p>The usage procedure is the same as in Blueprint.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">// Create an instance of ObjectDelivererManager
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">auto</span> deliverer <span style="color:#f92672">=</span> NewObject<span style="color:#f92672">&lt;</span>UObjectDelivererManager<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Monitor the receive event
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>deliverer<span style="color:#f92672">-&gt;</span>ReceiveData.AddDynamic(<span style="color:#66d9ef">this</span>, <span style="color:#f92672">&amp;</span>UMyClass<span style="color:#f92672">::</span>OnReceive);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Set Protocol and PacketRule and Start
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>deliverer<span style="color:#f92672">-&gt;</span>Start(UProtocolFactory<span style="color:#f92672">::</span>CreateProtocolTcpIpServer(<span style="color:#ae81ff">9099</span>),
</span></span><span style="display:flex;"><span>                     UPacketRuleFactory<span style="color:#f92672">::</span>CreatePacketRuleSizeBody());
</span></span></code></pre></div><h2 id="sending-and-receiving-data">Sending and Receiving Data</h2>
<p>The implementation method differs depending on whether the data to be sent is a byte array or something else.</p>
<h3 id="for-byte-arrays">For Byte Arrays</h3>
<p>Sending and receiving are done via the ObjectDelivererManager instance.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">// Create an instance of ObjectDelivererManager
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">auto</span> deliverer <span style="color:#f92672">=</span> NewObject<span style="color:#f92672">&lt;</span>UObjectDelivererManager<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Monitor the receive event
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>deliverer<span style="color:#f92672">-&gt;</span>ReceiveData.AddDynamic(<span style="color:#66d9ef">this</span>, <span style="color:#f92672">&amp;</span>UMyClass<span style="color:#f92672">::</span>OnReceive);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Set Protocol and PacketRule and Start
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>deliverer<span style="color:#f92672">-&gt;</span>Start(UProtocolFactory<span style="color:#f92672">::</span>CreateProtocolTcpIpServer(<span style="color:#ae81ff">9099</span>),
</span></span><span style="display:flex;"><span>                     UPacketRuleFactory<span style="color:#f92672">::</span>CreatePacketRuleSizeBody());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>TArray<span style="color:#f92672">&lt;</span>uint8<span style="color:#f92672">&gt;</span> buffer;
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Fill buffer with data...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Send byte array
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>deliverer<span style="color:#f92672">-&gt;</span>Send(buffer);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> UMyClass<span style="color:#f92672">::</span>OnReceive(UObjectDelivererProtocol<span style="color:#f92672">*</span> ClientSocket, <span style="color:#66d9ef">const</span> TArray<span style="color:#f92672">&lt;</span>uint8<span style="color:#f92672">&gt;&amp;</span> Buffer)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Use the received byte array
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
</span></span></code></pre></div><h3 id="for-non-byte-arrays">For Non-Byte Arrays</h3>
<p>This is done via the DeliveryBox set in ObjectDelivererManager.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">// Create a DeliveryBox with Object send/receive functionality via JSON serialization
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">auto</span> deliverybox <span style="color:#f92672">=</span> NewObject<span style="color:#f92672">&lt;</span>UObjectDeliveryBoxUsingJson<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Monitor the object receive event for the DeliveryBox
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>deliverybox<span style="color:#f92672">-&gt;</span>Received.AddDynamic(<span style="color:#66d9ef">this</span>, <span style="color:#f92672">&amp;</span>UMyClass<span style="color:#f92672">::</span>OnReceiveObject);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>deliverer<span style="color:#f92672">-&gt;</span>Start(UProtocolFactory<span style="color:#f92672">::</span>CreateProtocolTcpIpServer(<span style="color:#ae81ff">9099</span>),
</span></span><span style="display:flex;"><span>                 UPacketRuleFactory<span style="color:#f92672">::</span>CreatePacketRuleSizeBody(),
</span></span><span style="display:flex;"><span>                 deliverybox);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">auto</span> obj <span style="color:#f92672">=</span> NewObject<span style="color:#f92672">&lt;</span>USampleObject<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Set properties of obj...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Send the object using DeliveryBox
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>deliverybox<span style="color:#f92672">-&gt;</span>Send(obj);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> UMyClass<span style="color:#f92672">::</span>OnReceiveObject(UObject<span style="color:#f92672">*</span> ReceivedObject)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Extract the received object
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    USampleObject<span style="color:#f92672">*</span> obj <span style="color:#f92672">=</span> Cast<span style="color:#f92672">&lt;</span>USampleObject<span style="color:#f92672">&gt;</span>(ReceivedObject);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (obj)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Use the received object
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h1 id="future-plans">Future Plans</h1>
<p>ObjectDeliverer is currently under development, so changes will likely continue for some time.</p>
<p>Therefore, although I will try to avoid it as much as possible, there might be changes that break backward compatibility. Please be aware of this if you decide to try it.</p>
<h2 id="planned-additions">Planned Additions</h2>
<p>The following features are planned for implementation.</p>
<ul>
<li>Create shared memory as a communication protocol</li>
<li>Create a DeliveryBox that uses MessagePack for serialization</li>
<li>Save communication content to log files and a function to replay saved log files</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Writing UE4 Automated Tests Easily Using Lambdas</title>
      <link>https://ayumax.net/entry/2019/01/16/205500/</link>
      <pubDate>Wed, 16 Jan 2019 20:55:00 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/01/16/205500/</guid>
      <description>&lt;p&gt;UE4 supports testing as part of its development environment, allowing you to write automated tests without needing separate tools.&lt;/p&gt;
&lt;p&gt;Furthermore, by using Latent Commands, you can describe tests that span multiple frames, which is quite convenient.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.unrealengine.com/en-US/Programming/Automation/TechnicalGuide/index.html&#34;&gt;Automation Technical Guide&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;However, when trying to perform delayed evaluation using multiple Latent Commands, I always found it cumbersome that I had to define a &lt;code&gt;DEFINE_LATENT_AUTOMATION_COMMAND&lt;/code&gt; macro for each type of evaluation I wanted to perform.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>UE4 supports testing as part of its development environment, allowing you to write automated tests without needing separate tools.</p>
<p>Furthermore, by using Latent Commands, you can describe tests that span multiple frames, which is quite convenient.</p>
<p><a href="https://docs.unrealengine.com/en-US/Programming/Automation/TechnicalGuide/index.html">Automation Technical Guide</a></p>
<p>However, when trying to perform delayed evaluation using multiple Latent Commands, I always found it cumbersome that I had to define a <code>DEFINE_LATENT_AUTOMATION_COMMAND</code> macro for each type of evaluation I wanted to perform.</p>
<p>For example, something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>DEFINE_LATENT_AUTOMATION_COMMAND_TWO_PARAMETER(FHogeObjCommand, FAutomationTestBase<span style="color:#f92672">*</span>, Test, UMyObject<span style="color:#f92672">*</span>, Obj);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> FHogeObjCommand<span style="color:#f92672">::</span>Update()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    check(Test);
</span></span><span style="display:flex;"><span>    check(Obj);
</span></span><span style="display:flex;"><span>    Test<span style="color:#f92672">-&gt;</span>TestEqual(TEXT(<span style="color:#e6db74">&#34;check&#34;</span>), Obj<span style="color:#f92672">-&gt;</span>Property, <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> true;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>DEFINE_LATENT_AUTOMATION_COMMAND_TWO_PARAMETER(FHogeObjCommand2, FAutomationTestBase<span style="color:#f92672">*</span>, Test, UMyObject<span style="color:#f92672">*</span>, Obj);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> FHogeObjCommand2<span style="color:#f92672">::</span>Update()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    check(Test);
</span></span><span style="display:flex;"><span>    check(Obj);
</span></span><span style="display:flex;"><span>    Obj<span style="color:#f92672">-&gt;</span>Hoge();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> true;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>IMPLEMENT_SIMPLE_AUTOMATION_TEST(FHogeTest, <span style="color:#e6db74">&#34;Hoge.HogeTest&#34;</span>, EAutomationTestFlags<span style="color:#f92672">::</span>EditorContext <span style="color:#f92672">|</span> EAutomationTestFlags<span style="color:#f92672">::</span>EngineFilter)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> FHogeTest<span style="color:#f92672">::</span>RunTest(<span style="color:#66d9ef">const</span> FString<span style="color:#f92672">&amp;</span> Parameters)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">auto</span> obj <span style="color:#f92672">=</span> NewObject<span style="color:#f92672">&lt;</span>UMyObject<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(<span style="color:#ae81ff">1.0f</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    ADD_LATENT_AUTOMATION_COMMAND(FHogeObjCommand(<span style="color:#66d9ef">this</span>, obj));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    ADD_LATENT_AUTOMATION_COMMAND(FHogeObjCommand2(<span style="color:#66d9ef">this</span>, obj));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(<span style="color:#ae81ff">1.0f</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    ADD_LATENT_AUTOMATION_COMMAND(FHogeObjCommand(<span style="color:#66d9ef">this</span>, obj));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> true; <span style="color:#75715e">// Added return true
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
</span></span></code></pre></div><p>So, tired of defining multiple commands every time, I defined the following Latent Command, and it seems to work for almost everything.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER(FLambdaCommand, TFunction<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">void</span>()<span style="color:#f92672">&gt;</span>, InWork);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> FLambdaCommand<span style="color:#f92672">::</span>Update()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    InWork();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> true;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Using this Latent Command, the previous test can be written as:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>IMPLEMENT_SIMPLE_AUTOMATION_TEST(FHogeTest, <span style="color:#e6db74">&#34;Hoge.HogeTest&#34;</span>, EAutomationTestFlags<span style="color:#f92672">::</span>EditorContext <span style="color:#f92672">|</span> EAutomationTestFlags<span style="color:#f92672">::</span>EngineFilter)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> FHogeTest<span style="color:#f92672">::</span>RunTest(<span style="color:#66d9ef">const</span> FString<span style="color:#f92672">&amp;</span> Parameters)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">auto</span> obj <span style="color:#f92672">=</span> NewObject<span style="color:#f92672">&lt;</span>UMyObject<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(<span style="color:#ae81ff">1.0f</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    ADD_LATENT_AUTOMATION_COMMAND(FLambdaCommand([<span style="color:#66d9ef">this</span>, <span style="color:#f92672">&amp;</span>obj]()
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        TestEqual(TEXT(<span style="color:#e6db74">&#34;check&#34;</span>), obj<span style="color:#f92672">-&gt;</span>Property, <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>    })); <span style="color:#75715e">// Corrected closing parenthesis
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    ADD_LATENT_AUTOMATION_COMMAND(FLambdaCommand([<span style="color:#f92672">&amp;</span>obj]()
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        obj<span style="color:#f92672">-&gt;</span>Hoge();
</span></span><span style="display:flex;"><span>    })); <span style="color:#75715e">// Corrected closing parenthesis
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(<span style="color:#ae81ff">1.0f</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    ADD_LATENT_AUTOMATION_COMMAND(FLambdaCommand([<span style="color:#66d9ef">this</span>, <span style="color:#f92672">&amp;</span>obj]()
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        TestEqual(TEXT(<span style="color:#e6db74">&#34;check&#34;</span>), obj<span style="color:#f92672">-&gt;</span>Property, <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>    })); <span style="color:#75715e">// Corrected closing parenthesis
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> true; <span style="color:#75715e">// Added return true
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
</span></span></code></pre></div><p>I prefer this way as it makes the flow of processing easier to follow.</p>
<p>However, while casually browsing the Engine source code, I found that a similar command already existed without needing to create it myself.
I missed it because other Latent Commands were grouped in AutomationCommon.h.
I wonder if it existed before&hellip;</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">// AutomationTest.h
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">FFunctionLatentCommand</span> <span style="color:#f92672">:</span> <span style="color:#66d9ef">public</span> IAutomationLatentCommand
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>    FFunctionLatentCommand(TFunction<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">bool</span>()<span style="color:#f92672">&gt;</span> InLatentPredicate)
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">:</span> LatentPredicate(MoveTemp(InLatentPredicate))
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">virtual</span> <span style="color:#f92672">~</span>FFunctionLatentCommand()
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">virtual</span> <span style="color:#66d9ef">bool</span> <span style="color:#a6e22e">Update</span>() <span style="color:#66d9ef">override</span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> LatentPredicate();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">private</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>    TFunction<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">bool</span>()<span style="color:#f92672">&gt;</span> LatentPredicate;
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div>]]></content:encoded>
    </item>
    <item>
      <title>Reflecting on the Past Year and Resolutions for the New Year</title>
      <link>https://ayumax.net/entry/2019/01/02/111426/</link>
      <pubDate>Wed, 02 Jan 2019 11:14:26 +0000</pubDate>
      <guid>https://ayumax.net/entry/2019/01/02/111426/</guid>
      <description>&lt;h2 id=&#34;happy-new-year&#34;&gt;Happy New Year!&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s 2019, and it feels like about a year has passed quickly since I started blogging.&lt;/p&gt;
&lt;p&gt;Here, I&amp;rsquo;ll try writing down my reflections on 2018 and my resolutions for 2019.&lt;/p&gt;
&lt;h2 id=&#34;reflecting-on-2018&#34;&gt;Reflecting on 2018&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Month  &lt;/th&gt;
&lt;th&gt;What did I do? &lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;January  &lt;/td&gt;
&lt;td&gt;Created a custom Alexa skill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;Studied basic deep learning theory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;February  &lt;/td&gt;
&lt;td&gt;Attended a machine learning study group&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;March  &lt;/td&gt;
&lt;td&gt;Technical verification of Unreal.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;April  &lt;/td&gt;
&lt;td&gt;  &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May  &lt;/td&gt;
&lt;td&gt;Started designing MDToPPTX&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;  &lt;/td&gt;
&lt;td&gt;Started using Qt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;Bought an Oculus Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;June  &lt;/td&gt;
&lt;td&gt;Completed the initial version of MDToPPTX&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;July  &lt;/td&gt;
&lt;td&gt;Started creating the MDToPPTX editor using Xamarin Forms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;August  &lt;/td&gt;
&lt;td&gt;First Lightning Talk (LT)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;Started using F#&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;September  &lt;/td&gt;
&lt;td&gt;Worked on Qt3D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;October  &lt;/td&gt;
&lt;td&gt;Integrated Unreal.js into a development project&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;November  &lt;/td&gt;
&lt;td&gt;Xamarin App development&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;December  &lt;/td&gt;
&lt;td&gt;Started touching Unity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;VR project got approved at work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;Posted one article to the &lt;a href=&#34;https://qiita.com/advent-calendar/2018/ue4&#34;&gt;Unreal Engine 4 (UE4) Advent Calendar 2018&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Looking back now, this is how it feels.
Looking at it this way, I&amp;rsquo;ve dabbled in many different things.
This year, I want to narrow my focus a bit more and develop my strengths.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="happy-new-year">Happy New Year!</h2>
<p>It&rsquo;s 2019, and it feels like about a year has passed quickly since I started blogging.</p>
<p>Here, I&rsquo;ll try writing down my reflections on 2018 and my resolutions for 2019.</p>
<h2 id="reflecting-on-2018">Reflecting on 2018</h2>
<table>
<thead>
<tr>
<th>Month  </th>
<th>What did I do? </th>
</tr>
</thead>
<tbody>
<tr>
<td>January  </td>
<td>Created a custom Alexa skill</td>
</tr>
<tr>
<td> </td>
<td>Studied basic deep learning theory</td>
</tr>
<tr>
<td>February  </td>
<td>Attended a machine learning study group</td>
</tr>
<tr>
<td>March  </td>
<td>Technical verification of Unreal.js</td>
</tr>
<tr>
<td>April  </td>
<td>  </td>
</tr>
<tr>
<td>May  </td>
<td>Started designing MDToPPTX</td>
</tr>
<tr>
<td>  </td>
<td>Started using Qt</td>
</tr>
<tr>
<td> </td>
<td>Bought an Oculus Go</td>
</tr>
<tr>
<td>June  </td>
<td>Completed the initial version of MDToPPTX</td>
</tr>
<tr>
<td>July  </td>
<td>Started creating the MDToPPTX editor using Xamarin Forms</td>
</tr>
<tr>
<td>August  </td>
<td>First Lightning Talk (LT)</td>
</tr>
<tr>
<td> </td>
<td>Started using F#</td>
</tr>
<tr>
<td>September  </td>
<td>Worked on Qt3D</td>
</tr>
<tr>
<td>October  </td>
<td>Integrated Unreal.js into a development project</td>
</tr>
<tr>
<td>November  </td>
<td>Xamarin App development</td>
</tr>
<tr>
<td>December  </td>
<td>Started touching Unity</td>
</tr>
<tr>
<td> </td>
<td>VR project got approved at work</td>
</tr>
<tr>
<td> </td>
<td>Posted one article to the <a href="https://qiita.com/advent-calendar/2018/ue4">Unreal Engine 4 (UE4) Advent Calendar 2018</a></td>
</tr>
</tbody>
</table>
<p>Looking back now, this is how it feels.
Looking at it this way, I&rsquo;ve dabbled in many different things.
This year, I want to narrow my focus a bit more and develop my strengths.</p>
<p>Also, a big thing for me was speaking in front of people for the first time in August. That experience was significant.</p>
<p>Additionally, due to a confluence of good timing at work, I got the opportunity to do VR development, which I had wanted to try!!
It really pays to speak up about what you want to do.</p>
<h2 id="resolutions-for-2019">Resolutions for 2019</h2>
<h3 id="succeed-in-the-vr-development-project-at-work">Succeed in the VR Development Project at Work</h3>
<p>Since they bought me high-spec machines and several VR headsets, I really want to achieve some results.
I strongly feel like using this opportunity to increase the amount of work I want to do.</p>
<h3 id="increase-blog-update-frequency">Increase Blog Update Frequency</h3>
<p>I didn&rsquo;t give up after three days, but in 2018, the pace was about once a month, so the goal is to make it once a week.</p>
<h3 id="give-presentations">Give Presentations</h3>
<p>Last year it was only once, so the goal is two or more times.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Trying Windows 10 IoT Core on Raspberry Pi</title>
      <link>https://ayumax.net/entry/2018/12/29/143813/</link>
      <pubDate>Sat, 29 Dec 2018 14:38:13 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/12/29/143813/</guid>
      <description>&lt;h1 id=&#34;background&#34;&gt;Background&lt;/h1&gt;
&lt;p&gt;Apparently, Windows 10 IoT Core has been out for quite some time. Although I&amp;rsquo;m late to the party, I became interested after reading the following article:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.buildinsider.net/small/windowsiot/01&#34;&gt;What can you do with Windows 10 IoT Core (latest Creators Update version)?&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So, I decided to try it out on the Raspberry Pi 3 that was sleeping in my drawer.&lt;/p&gt;
&lt;p&gt;It seems that by installing this, I can develop and deploy UWP apps from Visual Studio on my development machine, which sounds fun.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="background">Background</h1>
<p>Apparently, Windows 10 IoT Core has been out for quite some time. Although I&rsquo;m late to the party, I became interested after reading the following article:</p>
<p><a href="https://www.buildinsider.net/small/windowsiot/01">What can you do with Windows 10 IoT Core (latest Creators Update version)?</a></p>
<p>So, I decided to try it out on the Raspberry Pi 3 that was sleeping in my drawer.</p>
<p>It seems that by installing this, I can develop and deploy UWP apps from Visual Studio on my development machine, which sounds fun.</p>
<h1 id="installation">Installation</h1>
<h2 id="downloading-and-installing-windows-10-iot-core-dashboard">Downloading and Installing Windows 10 IoT Core Dashboard</h2>
<p>Download setup.exe from the link below and install it.</p>
<p><a href="https://docs.microsoft.com/en-us/windows/iot-core/downloads">Downloads - Windows IoT | Microsoft Docs</a></p>
<p>At that time, on my environment (Surface Laptop, Windows 10 Pro 1803), the following warning appeared, and I couldn&rsquo;t install it.</p>
<figure>
    <img loading="lazy" src="/images/2018/12/29/143813/20181229141521.jpg"/> 
</figure>

<p><a href="https://about-alvis-kh.amebaownd.com/posts/3793040">Memo regarding the issue &ldquo;Your security settings do not allow this application to be installed on your computer.&rdquo;</a></p>
<p>So, referring to the site above, I changed the following registry key and rebooted:</p>
<p>[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\Security\TrustManager\PromptingLevel]
Change
Internet from Disabled to Enabled</p>
<p>Then, I was able to install it.
(I changed the registry back after the installation was complete.)</p>
<h2 id="writing-the-os-to-micro-sd">Writing the OS to Micro SD</h2>
<figure>
    <img loading="lazy" src="/images/2018/12/29/143813/20181229144604.jpg"/> 
</figure>

<p>After launching the installed Windows IoT Core Dashboard, insert the Micro SD card and write the OS.
I thought selecting Wi-Fi here would automatically set it up, but it didn&rsquo;t get enabled&hellip;</p>
<figure>
    <img loading="lazy" src="/images/2018/12/29/143813/20181229144412.jpg"/> 
</figure>

<p>Once writing is complete, the screen changes as shown above. Insert the SD card into the Raspberry Pi and boot it up.</p>
<h2 id="setting-up-windows-iot-core">Setting up Windows IoT Core</h2>
<p>Wait for the setup screen to appear with a display connected via HDMI.
In my environment, it took about 10 minutes.
I didn&rsquo;t know how to do this setup remotely, so I connected a wired keyboard and performed it.</p>
<p>As mentioned earlier, I also had to enter the Wi-Fi password here and authenticate.
(What was the Wi-Fi network connection checkbox on the main machine side for?)</p>
<h2 id="connecting-from-the-main-machine">Connecting from the Main Machine</h2>
<figure>
    <img loading="lazy" src="/images/2018/12/29/143813/20181229144414.jpg"/> 
</figure>

<p>After setup is complete, the Raspberry Pi is recognized in the Windows IoT Core Dashboard on the main machine.</p>
<p>From here, it seems various settings can be configured remotely, but I encountered several problems in my environment.</p>
<ul>
<li>Extremely slow<br/>
It seemed that having the Raspberry Pi also connected via Wi-Fi was the issue. It improved after switching to a wired LAN connection.</li>
<li>Remote client doesn't work<br/>
There's something called IoT Remote Client, which is supposed to allow usage similar to Windows Remote Desktop, but it just showed a white screen, seemingly not transferring the display.<br/>
I couldn't find a way to resolve this.</li>
<li>Connection drops<br/>
After using it for a bit, the Raspberry Pi disappears from "My devices", and it can't be recovered without rebooting.<br/>
The cause for this is also unknown. Maybe the main PC should also be on a wired LAN connection?</li>
</ul>
<h2 id="summary">Summary</h2>
<p>I tried this thinking I could utilize the sleeping Raspberry Pi, but since various things didn&rsquo;t go as expected, I&rsquo;ll let it sleep again for a while.
I&rsquo;ll try again from scratch after some time.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Dynamically Changing Logic with Unreal.js</title>
      <link>https://ayumax.net/entry/2018/11/20/000000/</link>
      <pubDate>Thu, 20 Dec 2018 00:00:35 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/11/20/000000/</guid>
      <description>&lt;p&gt;This article is for the 20th day of the &lt;a href=&#34;https://qiita.com/advent-calendar/2018/ue4&#34;&gt;Unreal Engine 4 (UE4) Advent Calendar 2018&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The previous day&amp;rsquo;s article was by &lt;a href=&#34;https://qiita.com/0xUMA&#34;&gt;0xUMA&lt;/a&gt;: &lt;a href=&#34;http://massa8080.hatenablog.com/entry/2018/12/19/001956&#34;&gt;Trying out automated testing in UE4.&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;
&lt;p&gt;There are times when you want to switch behavior patterns after creating a package for Windows from UE4. Initially, I handled this by allowing parameter changes via external text files (like XML or JSON).&lt;/p&gt;
&lt;p&gt;However, eventually, the request came to change the logic itself.&lt;br/&gt;
So, I will write about how I externalized the logic using JavaScript with Unreal.js.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>This article is for the 20th day of the <a href="https://qiita.com/advent-calendar/2018/ue4">Unreal Engine 4 (UE4) Advent Calendar 2018</a>.</p>
<p>The previous day&rsquo;s article was by <a href="https://qiita.com/0xUMA">0xUMA</a>: <a href="http://massa8080.hatenablog.com/entry/2018/12/19/001956">Trying out automated testing in UE4.</a></p>
<h2 id="overview">Overview</h2>
<p>There are times when you want to switch behavior patterns after creating a package for Windows from UE4. Initially, I handled this by allowing parameter changes via external text files (like XML or JSON).</p>
<p>However, eventually, the request came to change the logic itself.<br/>
So, I will write about how I externalized the logic using JavaScript with Unreal.js.</p>
<p>The sample project created for this article is available below.</p>
<div class="github-card" data-user="ayumax" data-repo="UnrealJsSample" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<h2 id="selecting-the-approach">Selecting the Approach</h2>
<p>In UE4, even if you change C++ code from the Editor, you can hot-reload it, allowing immediate (though with a slight delay) confirmation of behavior. However, this cannot be used after packaging.</p>
<p>Therefore, I looked for a plugin for scripting functionality that can run in the UE4 Runtime and found the following three:</p>
<ul>
<li>Unreal.js<br/>
<div class="github-card" data-user="ncsoft" data-repo="Unreal.js" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
</li>
<li>UnrealEnginePython<br/>
<div class="github-card" data-user="20tab" data-repo="UnrealEnginePython" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
</li>
<li>MonoUE<br/>
[MonoUE](https://mono-ue.github.io/)</li>
</ul>
<p>MonoUE uses C#, which I personally like, so I was interested, but it didn&rsquo;t seem easy to use casually as a script, so I removed it from the candidates.</p>
<p>Considering the remaining two, I personally preferred JavaScript, so I chose Unreal.js.</p>
<h2 id="what-is-unrealjs">What is Unreal.js?</h2>
<p>This was helpful for obtaining basic information about Unreal.js.
Although the article is about 2 years old, it was very helpful as it could be used almost as is even in the current 4.21 environment.</p>
<p>Introduction to Unreal.js<br/>
<a href="https://qiita.com/ConquestArrow/items/bb81ad5e63cf6bc4e549">Unreal.js 入門 - Qiita</a></p>
<h2 id="installation">Installation</h2>
<p>Add Unreal.js from the Marketplace.
<figure>
    <img loading="lazy" src="/images/2018/11/20/000000/20181219092954.jpg"/> 
</figure>
</p>
<p>Then, open the UE4 project in the Editor and enable Unreal.js from Edit-&gt;Plugins.
Restart the Editor, and it becomes usable.</p>
<p>As a test, place an Actor in the level, add a JavaScript Component, and enter Sample.js in Script Source File.
Create Sample.js in Content/Scripts and write the following content:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">&#34;test&#34;</span>)
</span></span></code></pre></div><p>With this setup, play the level. If &ldquo;test&rdquo; is displayed in the Output Log, it&rsquo;s working correctly.</p>
<figure>
    <img loading="lazy" src="/images/2018/11/20/000000/20181219093013.jpg"/> 
</figure>

<h2 id="checking-after-packaging">Checking After Packaging</h2>
<p>Create a package for Windows using File -&gt; Package Project -&gt; Windows -&gt; Windows (64-bit).</p>
<p>After creating the package, copy the following directory to the Content directory of the created package:</p>
<p><code>[Engine Install Path]\Engine\Plugins\Marketplace\UnrealJS\Content\Scripts</code></p>
<p>Start the application, close it immediately, and check if &ldquo;test&rdquo; is output in Saved/Logs/***.log. If it is, it&rsquo;s OK.</p>
<h2 id="creating-a-dynamic-loading-mechanism">Creating a Dynamic Loading Mechanism</h2>
<p>Using Unreal.js&rsquo;s JavaScript Component allows executing js files, but it has the following limitations:</p>
<ul>
<li>Once executed, the JavaScript cannot be changed midway.</li>
<li>The js file must be placed under Content/Scripts.</li>
</ul>
<p>Therefore, let&rsquo;s create a mechanism to eliminate these limitations, allowing js files to be placed anywhere and updated even while the script is running.
Specifically, let&rsquo;s create it with the following policy:</p>
<ul>
<li>The js file will only contain class definitions describing the externalized logic.</li>
<li>The base class for the classes described in the js file will be defined in C++.</li>
<li>The js file can be reloaded even while the application is running.</li>
<li>Minimize file access frequency.</li>
<li>Allow js files to be placed outside of Content/Scripts.</li>
</ul>
<h2 id="c-class-implementation-jsobject">C++ Class Implementation (JSObject)</h2>
<p>Define the base class for the classes defined in the js file.</p>
<p><code>FString NotifyTrigger();</code> is the interface for accessing the JavaScript side from the application side.
This time, it&rsquo;s a method returning FString, but change this according to the situation.
Multiple methods can be provided.
Make the method必ず UFUNCTION(BlueprintImplementableEvent) to make it an override-only method. Therefore, do not write the implementation in the cpp side.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">// Fill out your copyright notice in the Description page of Project Settings.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#pragma once
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;CoreMinimal.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;UObject/NoExportTypes.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;JSObject.generated.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">/**
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> *
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> */</span>
</span></span><span style="display:flex;"><span>UCLASS(BlueprintType)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">UNREALJSSAMPLE_API</span> UJSObject : <span style="color:#66d9ef">public</span> UObject
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    GENERATED_BODY()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>    UJSObject();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    UFUNCTION(BlueprintImplementableEvent)
</span></span><span style="display:flex;"><span>    FString NotifyTrigger();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">// Fill out your copyright notice in the Description page of Project Settings.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;JSObject.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>UJSObject<span style="color:#f92672">::</span>UJSObject()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="c-class-implementation-jscomponent">C++ Class Implementation (JSComponent)</h2>
<p>Implement this by referencing the implementation of Unreal.js&rsquo;s JavaScript Component.</p>
<h4 id="onregister">OnRegister</h4>
<p>Almost the same as Unreal.js&rsquo;s JavaScript Component.
Preparation for using JavaScript and registration of linkage between the C++ side and JavaScript side are also done at this point.</p>
<p>Among these, describing the single line <code>Context-&gt;Expose(&quot;Root&quot;, this);</code> allows the reference of this Component class to be used as <code>Root</code> within JavaScript.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> UJSComponent<span style="color:#f92672">::</span>OnRegister()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">auto</span> ContextOwner <span style="color:#f92672">=</span> GetOuter();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (ContextOwner <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">!</span>HasAnyFlags(RF_ClassDefaultObject) <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">!</span>ContextOwner<span style="color:#f92672">-&gt;</span>HasAnyFlags(RF_ClassDefaultObject))
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (GetWorld() <span style="color:#f92672">&amp;&amp;</span> ((GetWorld()<span style="color:#f92672">-&gt;</span>IsGameWorld() <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">!</span>GetWorld()<span style="color:#f92672">-&gt;</span>IsPreviewWorld())))
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            UJavascriptIsolate<span style="color:#f92672">*</span> Isolate <span style="color:#f92672">=</span> <span style="color:#66d9ef">nullptr</span>;
</span></span><span style="display:flex;"><span>            UJavascriptStaticCache<span style="color:#f92672">*</span> StaticGameData <span style="color:#f92672">=</span> Cast<span style="color:#f92672">&lt;</span>UJavascriptStaticCache<span style="color:#f92672">&gt;</span>(GEngine<span style="color:#f92672">-&gt;</span>GameSingleton);
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (StaticGameData)
</span></span><span style="display:flex;"><span>            {
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">if</span> (StaticGameData<span style="color:#f92672">-&gt;</span>Isolates.Num() <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>                    Isolate <span style="color:#f92672">=</span> StaticGameData<span style="color:#f92672">-&gt;</span>Isolates.Pop();
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>Isolate)
</span></span><span style="display:flex;"><span>            {
</span></span><span style="display:flex;"><span>                Isolate <span style="color:#f92672">=</span> NewObject<span style="color:#f92672">&lt;</span>UJavascriptIsolate<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>                Isolate<span style="color:#f92672">-&gt;</span>Init(false);
</span></span><span style="display:flex;"><span>                Isolate<span style="color:#f92672">-&gt;</span>AddToRoot();
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">auto</span><span style="color:#f92672">*</span> Context <span style="color:#f92672">=</span> Isolate<span style="color:#f92672">-&gt;</span>CreateContext();
</span></span><span style="display:flex;"><span>            JavascriptContext <span style="color:#f92672">=</span> Context;
</span></span><span style="display:flex;"><span>            JavascriptIsolate <span style="color:#f92672">=</span> Isolate;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            Context<span style="color:#f92672">-&gt;</span>Expose(<span style="color:#e6db74">&#34;Root&#34;</span>, <span style="color:#66d9ef">this</span>);
</span></span><span style="display:flex;"><span>            Context<span style="color:#f92672">-&gt;</span>Expose(<span style="color:#e6db74">&#34;GWorld&#34;</span>, GetWorld());
</span></span><span style="display:flex;"><span>            Context<span style="color:#f92672">-&gt;</span>Expose(<span style="color:#e6db74">&#34;GEngine&#34;</span>, GEngine);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Super<span style="color:#f92672">::</span>OnRegister();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h4 id="loadjsfile">LoadJSFile</h4>
<p>Reads the js file, instantiates the class described within it, and holds the reference.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> UJSComponent<span style="color:#f92672">::</span>LoadJSFile()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (JavascriptContext <span style="color:#f92672">==</span> <span style="color:#66d9ef">nullptr</span>) <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// ScriptSourceFile contains the relative path from Content, so convert it to an absolute path
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">auto</span> scriptSourceFilePath <span style="color:#f92672">=</span> FPaths<span style="color:#f92672">::</span>Combine(FPaths<span style="color:#f92672">::</span>ProjectContentDir(), ScriptSourceFile);
</span></span><span style="display:flex;"><span>    scriptSourceFilePath <span style="color:#f92672">=</span> FPaths<span style="color:#f92672">::</span>ConvertRelativePathToFull(scriptSourceFilePath);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Read the content of the js file (don&#39;t execute yet)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    FString script;
</span></span><span style="display:flex;"><span>    FFileHelper<span style="color:#f92672">::</span>LoadFileToString(script, <span style="color:#f92672">*</span>scriptSourceFilePath);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Extract the class name written in js
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">const</span> FRegexPattern pattern <span style="color:#f92672">=</span> FRegexPattern(FString(TEXT(<span style="color:#e6db74">&#34;class</span><span style="color:#ae81ff">\\</span><span style="color:#e6db74">s+(.+)</span><span style="color:#ae81ff">\\</span><span style="color:#e6db74">s+extends</span><span style="color:#ae81ff">\\</span><span style="color:#e6db74">s+JSObject&#34;</span>)));
</span></span><span style="display:flex;"><span>    FRegexMatcher <span style="color:#a6e22e">matcher</span>(pattern, script);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (matcher.FindNext())
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">auto</span> className <span style="color:#f92672">=</span> matcher.GetCaptureGroup(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Add code to the script for class instantiation and reference holding
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        script <span style="color:#f92672">=</span> TEXT(<span style="color:#e6db74">&#34;(function (global) {</span><span style="color:#ae81ff">\r\n</span><span style="color:#e6db74">&#34;</span>) <span style="color:#f92672">+</span> script;
</span></span><span style="display:flex;"><span>        script <span style="color:#f92672">+=</span> TEXT(<span style="color:#e6db74">&#34;let MyUObject_C = require(&#39;uclass&#39;)()(global,&#34;</span>) <span style="color:#f92672">+</span> className <span style="color:#f92672">+</span> TEXT(<span style="color:#e6db74">&#34;)</span><span style="color:#ae81ff">\r\n</span><span style="color:#e6db74">&#34;</span>);
</span></span><span style="display:flex;"><span>        script <span style="color:#f92672">+=</span> TEXT(<span style="color:#e6db74">&#34;let instance = new MyUObject_C()</span><span style="color:#ae81ff">\r\n</span><span style="color:#e6db74">&#34;</span>);
</span></span><span style="display:flex;"><span>        script <span style="color:#f92672">+=</span> TEXT(<span style="color:#e6db74">&#34;Root.SetJsObject(instance)</span><span style="color:#ae81ff">\r\n</span><span style="color:#e6db74">&#34;</span>);
</span></span><span style="display:flex;"><span>        script <span style="color:#f92672">+=</span> TEXT(<span style="color:#e6db74">&#34;})(this)&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Execute the script
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        JavascriptContext<span style="color:#f92672">-&gt;</span>RunScript(script);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The point is not to execute the js file directly as a script, but to add script lines above and below the js content to perform class instantiation and reference holding.</p>
<p>The part <code>script += TEXT(&quot;Root.SetJsObject(instance)\r\n&quot;);</code> uses the mechanism associated during <code>OnRegister()</code> to call the Component&rsquo;s function from within the script.
This allows the JavaScript class instance to be held as a property of the Component implemented in C++.</p>
<h3 id="notifytrigger">NotifyTrigger</h3>
<p>This is a function for calling the function of the class implemented in JavaScript via the Component from Blueprint.
Since the reference to the js class is held in <code>JsObject</code>, it&rsquo;s called via that.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>FString UJSComponent<span style="color:#f92672">::</span>NotifyTrigger()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (JsObject <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nullptr</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> JsObject<span style="color:#f92672">-&gt;</span>NotifyTrigger();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">FString</span>();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="blueprint-implementation-sampleactor">Blueprint Implementation (SampleActor)</h2>
<p>Add the previously created JSComponent and TextRender to an empty Actor.</p>
<figure>
    <img loading="lazy" src="/images/2018/11/20/000000/20181219092505.png"/> 
</figure>

<p>Also, create a function to call the method <code>NotifyTrigger</code> implemented in js.
Make it so that the string of TextRender is rewritten based on the result of <code>NotifyTrigger</code>.</p>
<figure>
    <img loading="lazy" src="/images/2018/11/20/000000/20181219092514.png"/> 
</figure>

<p>Next, create a function to reload the js file.
<figure>
    <img loading="lazy" src="/images/2018/11/20/000000/20181219092734.png"/> 
</figure>
</p>
<h2 id="blueprint-implementation-sampleumg">Blueprint Implementation (SampleUMG)</h2>
<p>Create two buttons in a Widget. Make one call the SampleActor&rsquo;s NotifyEvent method, and the other call the UpdateJS method.</p>
<p><figure>
    <img loading="lazy" src="/images/2018/11/20/000000/20181219092755.png"/> 
</figure>

<figure>
    <img loading="lazy" src="/images/2018/11/20/000000/20181219092807.png"/> 
</figure>
</p>
<h2 id="create-js-file">Create js File</h2>
<p>Create the js file to be used as a script.
The created file can be placed anywhere, but this time, save it in the same hierarchy as the Content folder.<br/>
Here, define a class that inherits the UJSObject class previously implemented in C++.
Since the application calls UJSObject&rsquo;s <code>NotifyTrigger</code>, override that part&rsquo;s implementation within the script.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MyUObject</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">JSObject</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">NotifyTrigger</span>(){
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">prop1</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">prop2</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;ABC&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">prop1</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">prop2</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="register-js-file-path-to-jscomponent">Register js File Path to JSComponent</h2>
<p>Place SampleActor in the level, and input the path to the js file as a relative path from Content into the <code>ScriptSourceFile</code> of the JSComponent already added to SampleActor.</p>
<p>It&rsquo;s okay even if it&rsquo;s in a higher hierarchy than Content.</p>
<h2 id="execution">Execution</h2>
<p>Create a Win64 package from the Editor.</p>
<p>Copy the following directory to the Content directory of the created package:</p>
<p><code>[Engine Install Path]\Engine\Plugins\Marketplace\UnrealJS\Content\Scripts</code></p>
<p>Also, copy the created js file to the same hierarchy as the package&rsquo;s Content folder.</p>
<p>Once the above preparations are complete, run the application.</p>
<p>TextRender displays the initial value.</p>
<p><figure>
    <img loading="lazy" src="/images/2018/11/20/000000/20181219092834.png"/> 
</figure>

Pressing the Trigger button calls the function implemented in JavaScript, and the display of TextRender changes.</p>
<p><figure>
    <img loading="lazy" src="/images/2018/11/20/000000/20181219092856.png"/> 
</figure>

Now, without closing the application, rewrite the content of the js file and save it by overwriting.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MyUObject</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">JSObject</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">NotifyTrigger</span>(){
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">prop1</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">3</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">prop2</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">4</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;ZZZ&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">prop1</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">prop2</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Press the application&rsquo;s UpdateJS button, then press Trigger. The display of TextRender changes to the result of the rewritten script.</p>
<figure>
    <img loading="lazy" src="/images/2018/11/20/000000/20181219092921.png"/> 
</figure>

<h2 id="summary">Summary</h2>
<p>Using Unreal.js, we were able to use scripting functionality dynamically even after package creation.</p>
<p>The advantage of this implementation is that by entrusting only the bare minimum to JavaScript, it&rsquo;s somewhat advantageous in terms of speed, and once the logic solidifies, performance can be further improved by replacing it with a C++ class.</p>
<p>Please give it a try if you like.</p>
<p>Tomorrow&rsquo;s article is by <a href="https://qiita.com/fukusuke8gou">fukusuke8gou</a> about UMG.</p>
<h2 id="references">References</h2>
<ul>
<li>Unreal.js Wiki<br/>
<a href="https://github.com/ncsoft/Unreal.js/wiki">https://github.com/ncsoft/Unreal.js/wiki</a></li>
<li>Introduction to Unreal.js<br/>
<a href="https://qiita.com/ConquestArrow/items/bb81ad5e63cf6bc4e549">https://qiita.com/ConquestArrow/items/bb81ad5e63cf6bc4e549</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Attended Center CLR Try! Development #2</title>
      <link>https://ayumax.net/entry/2018/11/12/222234/</link>
      <pubDate>Mon, 12 Nov 2018 22:22:34 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/11/12/222234/</guid>
      <description>&lt;h1 id=&#34;attended-center-clr-try-development-2&#34;&gt;Attended Center CLR Try! Development #2&lt;/h1&gt;
&lt;p&gt;I recently attended &amp;ldquo;Center CLR Try! Development #2&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;The venue was different from #1, right in front of Kanayama Station, making it easily accessible.
However, the target building was under construction, making the entrance hard to find, and I wandered around for a few minutes&amp;hellip; (Being directionally challenged, I initially went to the wrong building).&lt;/p&gt;
&lt;p&gt;There were three participants that day (Mr. Matsui, Mr. Matsuoka, and myself). Being alongside two amazing individuals made me a little, no, quite nervous. But thanks to the small group size, I was able to talk about various things, making it a meaningful day.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="attended-center-clr-try-development-2">Attended Center CLR Try! Development #2</h1>
<p>I recently attended &ldquo;Center CLR Try! Development #2&rdquo;.</p>
<p>The venue was different from #1, right in front of Kanayama Station, making it easily accessible.
However, the target building was under construction, making the entrance hard to find, and I wandered around for a few minutes&hellip; (Being directionally challenged, I initially went to the wrong building).</p>
<p>There were three participants that day (Mr. Matsui, Mr. Matsuoka, and myself). Being alongside two amazing individuals made me a little, no, quite nervous. But thanks to the small group size, I was able to talk about various things, making it a meaningful day.</p>
<h1 id="what-i-did">What I Did</h1>
<p>I had originally planned to spend the day working on an app I was developing in Unity, so that&rsquo;s what I did.</p>
<p>I&rsquo;m creating a prize lottery app to be used at my department&rsquo;s year-end party.</p>
<p>I&rsquo;ve been using Unreal Engine as my game development tool for a long time, but I had no experience with Unity, so I decided to give Unity a try starting this month.
(* Although I use Unreal Engine a lot, I&rsquo;ve never actually made a game.)</p>
<p>By the way, the deadline I set for myself is the end of November, so the duration is one month.</p>
<h1 id="a-bit-more-detail">A Bit More Detail</h1>
<p>Using Unity&rsquo;s UI features (equivalent to UMG in Unreal), I was creating the participant registration screen for the year-end party and implementing a feature to register photos taken with a smartphone camera.</p>
<p>I was worried I might have to use OS-dependent APIs for camera shooting, but it was surprisingly easy to achieve using only Unity&rsquo;s features!</p>
<p>(I&rsquo;m requesting camera usage permission in the app beforehand.)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#75715e">// Get the camera attached to the execution device (the first one if there are multiple)</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> cameraDevice = WebCamTexture.devices[<span style="color:#ae81ff">0</span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Create a texture to project the camera feed onto</span>
</span></span><span style="display:flex;"><span>cameraTexture = <span style="color:#66d9ef">new</span> WebCamTexture(cameraDevice.name, <span style="color:#ae81ff">1280</span>, <span style="color:#ae81ff">720</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Start shooting</span>
</span></span><span style="display:flex;"><span>cameraTexture.Play();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Display the camera feed on the UI (targetImage is a reference to a RawImage on the UI)</span>
</span></span><span style="display:flex;"><span>targetImage.texture = cameraTexture;
</span></span></code></pre></div><p>Running the code above displays the camera feed in real-time on the RawImage in the UI.
I assume it&rsquo;s transferring the camera feed to the RawImage&rsquo;s texture every frame.</p>
<p>This time, I wanted to save a still image, so I executed the following code when a UI button was pressed to save the image data.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cs" data-lang="cs"><span style="display:flex;"><span><span style="color:#75715e">// Get the pixel buffer of the camera image at that moment</span>
</span></span><span style="display:flex;"><span>Color32[] color32 = cameraTexture.GetPixels32();
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Create a texture to display the camera image</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> cameraImage = <span style="color:#66d9ef">new</span> Texture2D(cameraTexture.width, cameraTexture.height);
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Copy the pixel buffer to the texture</span>
</span></span><span style="display:flex;"><span>cameraImage.SetPixels32(color32);
</span></span><span style="display:flex;"><span>cameraImage.Apply();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Stop the camera shooting</span>
</span></span><span style="display:flex;"><span>cameraTexture.Stop();
</span></span></code></pre></div><p>Now, <code>cameraImage</code> contains the image captured by the camera as a texture. By inserting this into the UI&rsquo;s RawImage, I achieved the desired functionality.</p>
<p>That&rsquo;s what I did today. In the future, I plan to shrink and crop this captured image for thumbnails and serialize it so it can be used on the next launch.</p>
<h1 id="summary">Summary</h1>
<ul>
<li>Managed to capture smartphone camera images in Unity.</li>
<li>Small-group events are very meaningful as you get to talk with amazing people.</li>
<li>Might take the first step towards being able to read IL soon.</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Setting up FBX SDK in Qt Creator</title>
      <link>https://ayumax.net/entry/2018/10/17/221110/</link>
      <pubDate>Wed, 17 Oct 2018 22:11:10 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/10/17/221110/</guid>
      <description>&lt;h1 id=&#34;loading-fbx-in-qt&#34;&gt;Loading FBX in Qt&lt;/h1&gt;
&lt;p&gt;Lately, I&amp;rsquo;ve been mostly using Qt3D in Qt, but I wanted to try loading FBX files directly, so I set it up.&lt;/p&gt;
&lt;p&gt;Here are the notes.&lt;/p&gt;
&lt;h1 id=&#34;installing-fbx-sdk&#34;&gt;Installing FBX SDK&lt;/h1&gt;
&lt;p&gt;Download the SDK from the Autodesk download page.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.autodesk.com/developer-network/platform-technologies/fbx-sdk-2019-0&#34;&gt;FBX Software Developer Kit 2019.0 | Autodesk Developer Network&lt;/a&gt;&lt;/p&gt;
&lt;figure&gt;
    &lt;img loading=&#34;lazy&#34; src=&#34;https://ayumax.net/images/2018/10/17/221110/20181017213923.jpg&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;The latest SDK is for Visual Studio 2015; there isn&amp;rsquo;t one for 2017.
However, since VC++ 2015 and 2017 are said to be compatible, I&amp;rsquo;ll try using the 2015 version.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="loading-fbx-in-qt">Loading FBX in Qt</h1>
<p>Lately, I&rsquo;ve been mostly using Qt3D in Qt, but I wanted to try loading FBX files directly, so I set it up.</p>
<p>Here are the notes.</p>
<h1 id="installing-fbx-sdk">Installing FBX SDK</h1>
<p>Download the SDK from the Autodesk download page.</p>
<p><a href="https://www.autodesk.com/developer-network/platform-technologies/fbx-sdk-2019-0">FBX Software Developer Kit 2019.0 | Autodesk Developer Network</a></p>
<figure>
    <img loading="lazy" src="/images/2018/10/17/221110/20181017213923.jpg"/> 
</figure>

<p>The latest SDK is for Visual Studio 2015; there isn&rsquo;t one for 2017.
However, since VC++ 2015 and 2017 are said to be compatible, I&rsquo;ll try using the 2015 version.</p>
<p>Information about VC++ 2015 and 2017 compatibility can be found here:</p>
<p><a href="https://docs.microsoft.com/en-us/cpp/porting/binary-compat-2015-2017?view=vs-2017">C++ Binary Compatibility between Visual Studio 2015 and Visual Studio 2017 | Microsoft Docs</a></p>
<h1 id="first-try-using-it-in-visual-studio">First, Try Using it in Visual Studio</h1>
<p>Referring to this site, I tried using it in a Visual Studio 2017 C++ project.</p>
<p><a href="https://codelabo.com/799/">FBX SDK Preparation – Get Data from File – Code Labo</a></p>
<p>However, building resulted in an error!!</p>
<p>This article described the exact issue:</p>
<p><a href="https://qiita.com/Egliss/items/64d8273034ec4bd3e6d0">Story about FbxSdk failing to build in VisualStudio2017 - Qiita</a></p>
<p>Apparently, it&rsquo;s because FBX SDK uses non-standard C++ syntax from Visual Studio. Hmm.</p>
<h1 id="setting-up-in-qt-creator">Setting up in Qt Creator</h1>
<p>Looking at the directory where FBX SDK was installed, it seems there are dynamically linked versions (libfbxsdk.lib) and statically linked versions (libfbxsdk-md.lib, libfbxsdk-mt.lib) based on size.</p>
<p>This time, I&rsquo;ll try static linking (libfbxsdk-md.lib).</p>
<p>The environment is Windows 10, and the compiler specified is Visual Studio 2017 64-bit.</p>
<ul>
<li>In the Qt Creator project, select "Add Library" and choose "External Library".
<figure>
    <img loading="lazy" src="/images/2018/10/17/221110/20181017214944.jpg"/> 
</figure>
</li>
<li>Enter the path to libfbxsdk-md.lib in "Library file".</li>
<li>Enter the path to the fbxsdk "include" folder in "Include path".</li>
<li>For platform, select Windows Only for now.</li>
<li>Select "Static" for the linking method.</li>
</ul>
<figure>
    <img loading="lazy" src="/images/2018/10/17/221110/20181017215309.jpg"/> 
</figure>

<p>Pressing &ldquo;Next&rdquo; and proceeding writes the link information for FBX SDK into the ~.pro file.</p>
<p>Then, write the following code in main.cpp, build, and run. If no errors occur, it&rsquo;s OK.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;fbxsdk.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>(<span style="color:#66d9ef">int</span> argc, <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>argv[])
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    QGuiApplication app(argc, argv);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    FbxManager<span style="color:#f92672">*</span> manager <span style="color:#f92672">=</span> FbxManager<span style="color:#f92672">::</span>Create();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (manager)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        qDebug() <span style="color:#f92672">&lt;&lt;</span> <span style="color:#e6db74">&#34;FBX Manager created successfully.&#34;</span>;
</span></span><span style="display:flex;"><span>        manager<span style="color:#f92672">-&gt;</span>Destroy();
</span></span><span style="display:flex;"><span>        qDebug() <span style="color:#f92672">&lt;&lt;</span> <span style="color:#e6db74">&#34;FBX Manager destroyed.&#34;</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        qDebug() <span style="color:#f92672">&lt;&lt;</span> <span style="color:#e6db74">&#34;Failed to create FBX Manager.&#34;</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// ... rest of your Qt application setup ...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> app.exec();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Running it worked normally. The errors seen in Visual Studio 2017 did not occur in Qt Creator.</p>
<h1 id="summary">Summary</h1>
<p>I was able to set up the FBX SDK in Qt Creator.
I&rsquo;ll use this to play around with FBX files.</p>
<h1 id="bonus">Bonus</h1>
<p>It seems that FBX SDK is used internally within Qt3D in Qt Creator.
(Source code confirmed)</p>
<p>So, even without performing the steps in this article, FBX loading is possible with the default functionality.</p>
<p>This time, I specifically wanted to try using the FBX SDK directly myself, which is why I tried the steps in this article.</p>
]]></content:encoded>
    </item>
    <item>
      <title>View Scaling in Xamarin Forms</title>
      <link>https://ayumax.net/entry/2018/10/16/221237/</link>
      <pubDate>Tue, 16 Oct 2018 22:12:37 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/10/16/221237/</guid>
      <description>&lt;h1 id=&#34;view-scaling&#34;&gt;View Scaling&lt;/h1&gt;
&lt;p&gt;In the app I&amp;rsquo;m currently building, I wanted to create a virtual-sized canvas within the Window and change the overall scale according to the window size without breaking the layout inside. I explored various options.&lt;/p&gt;
&lt;p&gt;In WPF, it was convenient because you could adjust the scaling of the content display instantly by writing something like the below&amp;hellip; I wondered if Xamarin had something similar, but&amp;hellip; it doesn&amp;rsquo;t.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;DockPanel&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;DockPanel.RenderTransform&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;ScaleTransform&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ScaleX=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{Binding Scale}&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ScaleY=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{Binding Scale}&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/DockPanel.RenderTransform&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/DockPanel&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;about-visualelements-scale-property&#34;&gt;About VisualElement&amp;rsquo;s Scale Property&lt;/h1&gt;
&lt;p&gt;So, I wondered if controls have a property to set their own scale, and I found a property called &amp;ldquo;Scale&amp;rdquo;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="view-scaling">View Scaling</h1>
<p>In the app I&rsquo;m currently building, I wanted to create a virtual-sized canvas within the Window and change the overall scale according to the window size without breaking the layout inside. I explored various options.</p>
<p>In WPF, it was convenient because you could adjust the scaling of the content display instantly by writing something like the below&hellip; I wondered if Xamarin had something similar, but&hellip; it doesn&rsquo;t.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;DockPanel&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;DockPanel.RenderTransform&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&lt;ScaleTransform</span> <span style="color:#a6e22e">ScaleX=</span><span style="color:#e6db74">&#34;{Binding Scale}&#34;</span> <span style="color:#a6e22e">ScaleY=</span><span style="color:#e6db74">&#34;{Binding Scale}&#34;</span> <span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/DockPanel.RenderTransform&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/DockPanel&gt;</span>
</span></span></code></pre></div><h1 id="about-visualelements-scale-property">About VisualElement&rsquo;s Scale Property</h1>
<p>So, I wondered if controls have a property to set their own scale, and I found a property called &ldquo;Scale&rdquo;.</p>
<p>I tried setting the value to 0.5, expecting the size to become half.</p>
<p>But, the appearance didn&rsquo;t change.
It also feels strange that the Scale property isn&rsquo;t split into x and y. Is its purpose different?</p>
<p>I decided not to pursue this further and look for another approach.</p>
<h1 id="alternative-adjust-size-manually-the-gritty-way">Alternative: Adjust Size Manually (The Gritty Way)</h1>
<p>After considering various options, I decided to simply capture the ContentView&rsquo;s SizeChanged event, calculate the change rate from the original size (1x scale), and adjust accordingly.</p>
<p>I receive SizeChanged within a Behavior attached to the View and pass it to the ViewModel via a Command.</p>
<p>At that time, I tried connecting it to the ViewModel using Prism&rsquo;s EventToCommandBehavior, but it didn&rsquo;t work (EventArgs had no value, and I couldn&rsquo;t pass the sender to EventArgsConverter, so I gave up). I created a new Behavior specifically for SizeChanged to handle it.</p>
<p>So far, this method achieves the desired behavior.</p>
<h1 id="yet-another-method">Yet Another Method</h1>
<p>I haven&rsquo;t actually tried this, but instead of drawing directly on the screen as Xamarin Forms controls, I think scaling could be easily achieved by first drawing everything onto a Bitmap.</p>
<p>(I don&rsquo;t plan to try this for a while because the scope of change is large, and it would prevent UI creation using Xaml.)</p>
]]></content:encoded>
    </item>
    <item>
      <title>Displaying Niconi Solid Chan (Alicia Solid) with Qt3D</title>
      <link>https://ayumax.net/entry/2018/09/16/214810/</link>
      <pubDate>Sun, 16 Sep 2018 21:48:10 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/09/16/214810/</guid>
      <description>&lt;h1 id=&#34;niconi-solid-chan-alicia-solid&#34;&gt;Niconi Solid Chan (Alicia Solid)&lt;/h1&gt;
&lt;p&gt;While looking for a 3D model to use for learning Qt3D, I found a very promising one.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://3d.nicovideo.jp/alicia/&#34;&gt;Niconi Solid Chan Special Site - Niconi Solid&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We are releasing the 3D model &amp;lsquo;Alicia Solid&amp;rsquo;, which can be used for free without attribution in various situations such as video productions, self-made games, technical demos, and doujin activities.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;It&amp;rsquo;s a very user-friendly license, allowing free use and secondary processing.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="niconi-solid-chan-alicia-solid">Niconi Solid Chan (Alicia Solid)</h1>
<p>While looking for a 3D model to use for learning Qt3D, I found a very promising one.</p>
<p><a href="http://3d.nicovideo.jp/alicia/">Niconi Solid Chan Special Site - Niconi Solid</a></p>
<blockquote>
<p>We are releasing the 3D model &lsquo;Alicia Solid&rsquo;, which can be used for free without attribution in various situations such as video productions, self-made games, technical demos, and doujin activities.</p></blockquote>
<p>It&rsquo;s a very user-friendly license, allowing free use and secondary processing.</p>
<p>The 3D model is distributed in the following three formats:</p>
<ul>
<li>FBX</li>
<li>MMD</li>
<li>Unity Package</li>
</ul>
<p>This time, I will use the FBX format from these options.</p>
<p>MMD can be used in Blender by adding an add-on, but it has drawbacks for future use, such as Japanese characters in object names, so I won&rsquo;t use it this time.<br/>
Unity Package is exclusive to Unity, so I won&rsquo;t use this either.</p>
<h1 id="loading-with-qt3d-fbx-edition">Loading with Qt3D (FBX Edition)</h1>
<p>First, I tried loading the fbx like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-qml" data-lang="qml"><span style="display:flex;"><span><span style="color:#a6e22e">Entity</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">components:</span> [
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">SceneLoader</span> {
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">source:</span> <span style="color:#e6db74">&#34;/FBX/Alicia_solid_MMD.FBX&#34;</span>
</span></span><span style="display:flex;"><span>             },
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">Transform</span> {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">translation:</span> <span style="color:#a6e22e">Qt</span>.<span style="color:#a6e22e">vector3d</span>(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As a result, nothing was displayed on the screen, and <del>it seems fbx cannot be loaded.</del><br/>
(Upon closer inspection, it was just taking too long, and loading was actually happening. However, the raw downloaded fbx encountered texture loading errors and ultimately wasn&rsquo;t displayed.)</p>
<h1 id="loading-with-blender">Loading with Blender</h1>
<p>Next, since loading it directly in Qt3D didn&rsquo;t work, I tried processing it first by loading it into Blender.</p>
<p>Then&hellip;</p>
<blockquote>
<p>ASCII FBX files are not supported.</p></blockquote>
<p>Hmm, are there different types of FBX?</p>
<p>Research revealed that FBX has ASCII and binary types.<br/>
(I had never paid attention to that before.)</p>
<h1 id="fbx-conversion">FBX Conversion</h1>
<p>Since I wanted to read FBX in Blender, I found that Autodesk provides an FBX converter.
Besides converting from ASCII to binary format, it seems you can also choose whether resource files like textures are external or embedded.</p>
<p><a href="https://www.autodesk.com/developer-network/platform-technologies/fbx-converter-archives">FBX Converter Archives | Autodesk Developer Network</a></p>
<figure>
    <img loading="lazy" src="/images/2018/09/16/214810/20180916213037.jpg"/> 
</figure>

<p>Usage is simple: add the target file, set FBX Save Mode to Binary, and press Convert.</p>
<h1 id="loading-with-blender-attempt-2">Loading with Blender (Attempt 2)</h1>
<p>Importing the FBX converted to binary format completed without errors this time.</p>
<figure>
    <img loading="lazy" src="/images/2018/09/16/214810/20180916213051.jpg"/> 
</figure>

<h1 id="exporting-in-a-format-loadable-by-qt3d">Exporting in a Format Loadable by Qt3D</h1>
<p>I tried exporting in obj format, which I have previously successfully loaded in Qt3D.</p>
<p>As expected, there seemed to be errors loading textures.
Texture information for obj files is apparently written in the mtl file. Looking inside the mtl, I found two patterns for image file references: *.tga and *.psd.</p>
<p>Looking at the Qt documentation (<a href="http://doc.qt.io/qt-5/qtimageformats-index.html"><a href="http://doc.qt.io/qt-5/qtimageformats-index.html">http://doc.qt.io/qt-5/qtimageformats-index.html</a></a>), it seems tga files are supported, so I imagined psd couldn&rsquo;t be read and replaced *.psd with *.tga.<br/>
(This isn&rsquo;t a fundamental solution, but since there were the same number of *.tga and *.psd files, it was a temporary measure.)</p>
<p>After applying this change and running it in Qt:</p>
<figure>
    <img loading="lazy" src="/images/2018/09/16/214810/20180916213105.jpg"/> 
</figure>

<p>It displayed!! But the overall display is rough, and there&rsquo;s something on the forehead area.</p>
<p>Compared to the original FBX (Binary) file size of 6MB, the obj (text) file is 2.7MB, significantly smaller, so the roughness of the display might be unavoidable.
Is the thing on the forehead perhaps due to changing the psd file to tga?</p>
<p>As a temporary measure, I deleted the forehead part in Blender and exported the obj file again. The something on the forehead disappeared.</p>
<figure>
    <img loading="lazy" src="/images/2018/09/16/214810/20180916213118.jpg"/> 
</figure>

<h1 id="embedding-the-3d-model-in-qml">Embedding the 3D Model in QML</h1>
<p>Exporting the obj file from Blender allowed loading in Qt3D, but the rendering quality decreased (probably due to reduced vertex count?).</p>
<p>Also, loading models using SceneLoader seems to happen dynamically after the application starts, so it takes a little time for the model to appear.<br/>
(This is why I initially thought the text-format fbx wasn&rsquo;t loading.)</p>
<p>Amidst this, I found a page published by KDAB:</p>
<p><a href="https://www.kdab.com/exporting-3d-content-qt-3d-blender/">Exporting 3D content for Qt 3D with Blender - KDAB</a></p>
<p>The article mentions that using the Blender Exporter Addon described here allows saving the model in binary format and using it without parsing time.</p>
<p>I tried it immediately.</p>
<p>Copy the files from this repository, paste them into Blender&rsquo;s addons directory, and enable the addon in Blender&rsquo;s settings to make qml export available.</p>
<div class="github-card" data-user="KDAB/qt3d-examples/tree/master" data-repo="blender-qt3d-export" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<figure>
    <img loading="lazy" src="/images/2018/09/16/214810/20180916213142.jpg"/> 
</figure>

<p>Exporting using this generated a complete set of Qt project files.</p>
<p>Launching the exported project and displaying it:</p>
<figure>
    <img loading="lazy" src="/images/2018/09/16/214810/20180916213451.jpg"/> 
</figure>

<p>The shape is cleaner than the previously loaded obj format.<br/>
There&rsquo;s almost no difference from how it looks in Blender.
Also, there&rsquo;s almost no delay between the window appearing and the 3D model being displayed.<br/>
The effect of binary embedding seems significant.</p>
<p>However, as you can see at a glance, it&rsquo;s not colored.<br/>
Looking at Blender&rsquo;s qml export script (which is Python inside), the information for materials using textures was not exported.</p>
<p>I found that the material information in the exported project is written in MaterialCollection.qml, so I decided to manually redefine the materials using textures (*.tga) here.</p>
<h3 id="original-material-definition">Original Material Definition</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-qml" data-lang="qml"><span style="display:flex;"><span><span style="color:#a6e22e">readonly</span> <span style="color:#a6e22e">property</span> <span style="color:#a6e22e">Material</span> <span style="color:#66d9ef">wearPsd:</span> <span style="color:#a6e22e">PhongMaterial</span> {
</span></span><span style="display:flex;"><span>   <span style="color:#66d9ef">ambient:</span> <span style="color:#a6e22e">Qt</span>.<span style="color:#a6e22e">rgba</span>(<span style="color:#ae81ff">0.2</span>, <span style="color:#ae81ff">0.2</span>, <span style="color:#ae81ff">0.2</span>, <span style="color:#ae81ff">1.0</span>)
</span></span><span style="display:flex;"><span>   <span style="color:#66d9ef">diffuse:</span> <span style="color:#a6e22e">Qt</span>.<span style="color:#a6e22e">rgba</span>(<span style="color:#ae81ff">1.0</span>, <span style="color:#ae81ff">1.0</span>, <span style="color:#ae81ff">1.0</span>, <span style="color:#ae81ff">1.0</span>)
</span></span><span style="display:flex;"><span>   <span style="color:#66d9ef">specular:</span> <span style="color:#a6e22e">Qt</span>.<span style="color:#a6e22e">rgba</span>(<span style="color:#ae81ff">1.0</span>, <span style="color:#ae81ff">1.0</span>, <span style="color:#ae81ff">1.0</span>, <span style="color:#ae81ff">1.0</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="modified-material-definition">Modified Material Definition</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-qml" data-lang="qml"><span style="display:flex;"><span><span style="color:#a6e22e">readonly</span> <span style="color:#a6e22e">property</span> <span style="color:#a6e22e">Material</span> <span style="color:#66d9ef">wearPsd:</span> <span style="color:#a6e22e">NormalDiffuseSpecularMapMaterial</span>  {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">ambient:</span> <span style="color:#e6db74">&#34;white&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">diffuse:</span> <span style="color:#a6e22e">TextureLoader</span> { <span style="color:#66d9ef">source:</span> <span style="color:#e6db74">&#34;matarial/Alicia_wear.tga&#34;</span>}
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">normal:</span> <span style="color:#a6e22e">TextureLoader</span> { <span style="color:#66d9ef">source :</span> <span style="color:#e6db74">&#34;matarial/Alicia_wear.tga&#34;</span> }
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">specular:</span> <span style="color:#a6e22e">TextureLoader</span> { <span style="color:#66d9ef">source:</span> <span style="color:#e6db74">&#34;matarial/Alicia_wear.tga&#34;</span> }
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">shininess:</span> <span style="color:#ae81ff">1.0</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">textureScale:</span> <span style="color:#ae81ff">1.0</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Since the property type is Material both before and after the change, I hoped modifying this would make everything work.
Figuring out which texture to assign to which material was inferable from the property names, so it wasn&rsquo;t too much trouble.</p>
<p>After implementing this change and launching again:</p>
<figure>
    <img loading="lazy" src="/images/2018/09/16/214810/20180916213205.jpg"/> 
</figure>

<p>It got colored properly!!</p>
<p>However, because I used TextureLoader for texture loading, the image file loading occurs dynamically, causing a slight delay after startup.
To resolve this, I think the textures also need to be embedded in binary (RGB format?) like the 3D model.</p>
<h1 id="summary">Summary</h1>
<p>It&rsquo;s not perfect yet, and challenges remain, but I was able to use Alicia-chan&rsquo;s 3D model in Qt3D.</p>
<p>However, this time I only displayed it, so it&rsquo;s not moving.<br/>
The FBX file also defines bones and motions using them, so next I want to investigate if motion animation can be done from Qt3D.</p>
<p>The complete project set with Alicia-chan&rsquo;s information embedded is published in the following repository:</p>
<div class="github-card" data-user="ayumax" data-repo="AliciaForQt3D" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<h1 id="bonus">Bonus</h1>
<p>Since it&rsquo;s 3D, I tried rotating it for now.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">やっとQt3D上にアリシアちゃんを降臨させる事ができた。<a href="https://twitter.com/hashtag/AliciaForQt3D?src=hash&amp;ref_src=twsrc%5Etfw">#AliciaForQt3D</a> <a href="https://t.co/ungDBLLqBj">pic.twitter.com/ungDBLLqBj</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1041239713078640640?ref_src=twsrc%5Etfw">September 16, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


]]></content:encoded>
    </item>
    <item>
      <title>Qt Study Group Achievement: Tried Using Qt3D</title>
      <link>https://ayumax.net/entry/2018/08/26/010012/</link>
      <pubDate>Sun, 26 Aug 2018 01:00:12 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/08/26/010012/</guid>
      <description>&lt;h1 id=&#34;qt3d-studio-and-qt3d&#34;&gt;Qt3D Studio and Qt3D&lt;/h1&gt;
&lt;p&gt;I had previously tried expressing 3D using Qt3D Studio, but today I tried using Qt3D with Qt Creator.&lt;/p&gt;
&lt;p&gt;Qt3D Studio gave me the impression of a sequencer that moves 3D models using a timeline, whereas Qt3D feels more like something programmers implement hardcore.&lt;/p&gt;
&lt;p&gt;Qt3D Studio seems suitable for quickly creating 3D expressions, but for doing various things within a single application, I currently think using Qt3D with QML might be better.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="qt3d-studio-and-qt3d">Qt3D Studio and Qt3D</h1>
<p>I had previously tried expressing 3D using Qt3D Studio, but today I tried using Qt3D with Qt Creator.</p>
<p>Qt3D Studio gave me the impression of a sequencer that moves 3D models using a timeline, whereas Qt3D feels more like something programmers implement hardcore.</p>
<p>Qt3D Studio seems suitable for quickly creating 3D expressions, but for doing various things within a single application, I currently think using Qt3D with QML might be better.</p>
<p>The implemented project is here:</p>
<div class="github-card" data-user="ayumax" data-repo="Qt3DSample" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<h1 id="what-i-made">What I Made</h1>
<p>Since I can&rsquo;t do modeling myself, I used free assets.
To create an atmosphere, I placed buildings, and it features a car driving straight down a road.</p>
<p>Just driving straight isn&rsquo;t interesting, so I added an animation where the car jumps when the mouse is clicked.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">今日のQt勉強会で作ったもの。<br>Qt3Dとフリー素材でサンプルを作ってみた。<br>少し味付けでマウスクリックでジャンプする仕組みを足してみた。<a href="https://twitter.com/hashtag/qtjp?src=hash&amp;ref_src=twsrc%5Etfw">#qtjp</a> <a href="https://t.co/onGR5UpqQ6">pic.twitter.com/onGR5UpqQ6</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1033362618197524480?ref_src=twsrc%5Etfw">August 25, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<h1 id="implementation-details">Implementation Details</h1>
<p>This time, I didn&rsquo;t use C++ and wrote everything in QML.</p>
<h2 id="3d-models-of-cars-and-buildings">3D Models of Cars and Buildings</h2>
<p>All I did was specify the file in the SceneLoader&rsquo;s source, and Qt automatically loaded it. Convenient!</p>
<p>For the car, since I want to move it, I made the Transform&rsquo;s translation value a property so it can be accessed from outside.</p>
<p>I also specified rotation because the 3D model faced sideways when loaded normally, so I rotated it 90 degrees. If the coordinate system is properly aligned with Qt in a modeling tool like Blender, this shouldn&rsquo;t be necessary.</p>
<p>As an aside, since I usually use Unreal Engine, I was confused by the different X, Y, Z coordinate system. Y and Z are reversed between Unreal and Qt.</p>
<ul><li>Part that loads the car's 3D model</li></ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-qml" data-lang="qml"><span style="display:flex;"><span> <span style="color:#a6e22e">Entity</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">components:</span> [
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">SceneLoader</span> {
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">source :</span> <span style="color:#e6db74">&#34;/model3d/track.obj&#34;</span>
</span></span><span style="display:flex;"><span>            },
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">Transform</span> {
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">id: myCarTransform</span>
</span></span><span style="display:flex;"><span>                <span style="color:#a6e22e">property</span> <span style="color:#a6e22e">real</span> <span style="color:#66d9ef">locationX:</span> <span style="color:#ae81ff">0.0</span>
</span></span><span style="display:flex;"><span>                <span style="color:#a6e22e">property</span> <span style="color:#a6e22e">real</span> <span style="color:#66d9ef">locationY:</span> <span style="color:#ae81ff">0.0</span>
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">rotation:</span> <span style="color:#a6e22e">fromAxisAndAngle</span>(<span style="color:#a6e22e">Qt</span>.<span style="color:#a6e22e">vector3d</span>(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">0</span>), <span style="color:#ae81ff">90</span>)
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">translation :</span> <span style="color:#a6e22e">Qt</span>.<span style="color:#a6e22e">vector3d</span>(<span style="color:#a6e22e">locationX</span>, <span style="color:#a6e22e">locationY</span>, <span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        ]
</span></span><span style="display:flex;"><span>    }
</span></span></code></pre></div><h2 id="road">Road</h2>
<p>The ground, road, and white lines are represented by applying colored materials to flat polygons.</p>
<p>CuboidMesh represents a cuboid, and its size is specified using xExtent, yExtent, and zExtent.</p>
<p>For the material, I used PhongMaterial and just specified the color (ambient) for now. It looks quite shiny, but I think using other properties might allow for different expressions, though I haven&rsquo;t confirmed this today.</p>
<ul><li>Ground</li></ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-qml" data-lang="qml"><span style="display:flex;"><span><span style="color:#a6e22e">Entity</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">components:</span> [
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">CuboidMesh</span> {
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">xExtent:</span> <span style="color:#ae81ff">2000</span>
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">yExtent:</span> <span style="color:#ae81ff">0.1</span>
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">zExtent:</span> <span style="color:#ae81ff">500</span>
</span></span><span style="display:flex;"><span>            },
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">PhongMaterial</span> {
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">ambient:</span><span style="color:#e6db74">&#34;dimgray&#34;</span>
</span></span><span style="display:flex;"><span>            },
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">Transform</span> {
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">translation:</span> <span style="color:#a6e22e">Qt</span>.<span style="color:#a6e22e">vector3d</span>(<span style="color:#ae81ff">0</span>, <span style="color:#f92672">-</span><span style="color:#ae81ff">0.01</span>, <span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>        ]
</span></span><span style="display:flex;"><span>    }
</span></span></code></pre></div><h2 id="car-driving-part">Car Driving Part</h2>
<p>I&rsquo;m using NumberAnimation to move the car&rsquo;s X coordinate.
It&rsquo;s set to repeat from -20m to 1000m.
The relationship between these from, to values and the duration allows setting the desired car speed.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-qml" data-lang="qml"><span style="display:flex;"><span><span style="color:#a6e22e">QQ2</span>.<span style="color:#a6e22e">NumberAnimation</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">id:moveAnimation</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">target:</span> <span style="color:#a6e22e">myCarTransform</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">property:</span> <span style="color:#e6db74">&#34;locationX&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">duration:</span> <span style="color:#ae81ff">30000</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">from:</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">20</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">to:</span> <span style="color:#ae81ff">1000</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">loops:</span> <span style="color:#a6e22e">QQ2</span>.<span style="color:#a6e22e">Animation</span>.<span style="color:#a6e22e">Infinite</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">running:</span> <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>    }
</span></span></code></pre></div><h2 id="jump">Jump</h2>
<p>Regarding the part where the car jumps on mouse click, I actually struggled to implement the &ldquo;on click&rdquo; part initially.</p>
<p>In normal 2D cases, I used MouseArea, but it couldn&rsquo;t be used within a Qt3D Entity, so I&rsquo;m using ObjectPicker now.</p>
<p>However, I still don&rsquo;t fully understand why mouse events can be captured with this ObjectPicker, so I&rsquo;ll investigate it properly in the future.</p>
<p>After capturing the mouse event, I connect it to start the animation.
The animation of jumping up and coming down is expressed by connecting them using SequentialAnimation.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-qml" data-lang="qml"><span style="display:flex;"><span><span style="color:#a6e22e">ObjectPicker</span>{
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">onPressed:</span>{
</span></span><span style="display:flex;"><span>             <span style="color:#a6e22e">myCar</span>.<span style="color:#a6e22e">notifyClick</span>()
</span></span><span style="display:flex;"><span>          }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">notifyClick</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">jumpAnimation</span>.<span style="color:#a6e22e">start</span>()
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">QQ2</span>.<span style="color:#a6e22e">SequentialAnimation</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">id:jumpAnimation</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">QQ2</span>.<span style="color:#a6e22e">NumberAnimation</span> {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">target:</span> <span style="color:#a6e22e">myCarTransform</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">property:</span> <span style="color:#e6db74">&#34;locationY&#34;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">duration:</span> <span style="color:#ae81ff">500</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">from:</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">to:</span> <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">easing.type:</span> <span style="color:#a6e22e">Easing</span>.<span style="color:#a6e22e">InSine</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">QQ2</span>.<span style="color:#a6e22e">NumberAnimation</span> {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">target:</span> <span style="color:#a6e22e">myCarTransform</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">property:</span> <span style="color:#e6db74">&#34;locationY&#34;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">duration:</span> <span style="color:#ae81ff">500</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">from:</span> <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">to:</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">easing.type:</span> <span style="color:#a6e22e">Easing</span>.<span style="color:#a6e22e">OutSine</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">onStopped:</span> <span style="color:#a6e22e">myCarTransform</span>.<span style="color:#a6e22e">locationY</span><span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span></code></pre></div><h1 id="summary">Summary</h1>
<p>I was able to achieve simple 3D model manipulation using Qt3D.</p>
<p>I ran out of time today, but I&rsquo;d also like to try these things:</p>
<ul>
<li>Change material parameters to vary the texture</li>
<li>Since CuboidMesh can only create straight roads, investigate how to create curved road meshes (Maybe touch OpenGL?)</li>
<li>Adjust lighting to change shadows, etc.</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>F# Study Today (Pattern Matching)</title>
      <link>https://ayumax.net/entry/2018/08/22/005059/</link>
      <pubDate>Wed, 22 Aug 2018 00:50:59 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/08/22/005059/</guid>
      <description>&lt;h1 id=&#34;f-review&#34;&gt;F# Review&lt;/h1&gt;
&lt;p&gt;Today I encountered pattern matching for the first time.&lt;/p&gt;
&lt;p&gt;C# has it too, but I felt this is a feature characteristic of F#.&lt;/p&gt;
&lt;h1 id=&#34;f-pattern-matching&#34;&gt;F# Pattern Matching&lt;/h1&gt;
&lt;p&gt;This is amazing. I thought C#’s switch expression pattern matching was similar, but this feature probably went from F# to C#.&lt;/p&gt;
&lt;h2 id=&#34;match-expression&#34;&gt;match Expression&lt;/h2&gt;
&lt;p&gt;I think the match expression will be used often, so I need to remember it well.&lt;/p&gt;
&lt;p&gt;Also, it seems there are different kinds of patterns like &lt;code&gt;or&lt;/code&gt; patterns and &lt;code&gt;as&lt;/code&gt; patterns, so I need to memorize these properly too.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="f-review">F# Review</h1>
<p>Today I encountered pattern matching for the first time.</p>
<p>C# has it too, but I felt this is a feature characteristic of F#.</p>
<h1 id="f-pattern-matching">F# Pattern Matching</h1>
<p>This is amazing. I thought C#’s switch expression pattern matching was similar, but this feature probably went from F# to C#.</p>
<h2 id="match-expression">match Expression</h2>
<p>I think the match expression will be used often, so I need to remember it well.</p>
<p>Also, it seems there are different kinds of patterns like <code>or</code> patterns and <code>as</code> patterns, so I need to memorize these properly too.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fsharp" data-lang="fsharp"><span style="display:flex;"><span><span style="color:#66d9ef">let</span> testFunc param <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">match</span> param <span style="color:#66d9ef">with</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">|</span> <span style="color:#e6db74">&#39;a&#39;</span> <span style="color:#f92672">-&gt;</span> 0
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">|</span> <span style="color:#e6db74">&#39;b&#39;</span> <span style="color:#f92672">-&gt;</span> 1
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">|</span> <span style="color:#f92672">_</span> <span style="color:#f92672">-&gt;</span> <span style="color:#f92672">-</span>1
</span></span><span style="display:flex;"><span>       
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> ret <span style="color:#f92672">=</span> testFunc <span style="color:#e6db74">&#39;b&#39;</span>
</span></span><span style="display:flex;"><span>printfn <span style="color:#e6db74">&#34;%A&#34;</span> ret
</span></span></code></pre></div><h2 id="function-expression">function Expression</h2>
<p>Simply put, it seems to be a combination of the <code>fun</code> expression and the <code>match</code> expression.</p>
<p>I thought it could be created with <code>if</code> statements even without <code>function</code>, but how is it really??</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fsharp" data-lang="fsharp"><span style="display:flex;"><span><span style="color:#66d9ef">let</span> testFunc <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span> 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">|</span> value <span style="color:#66d9ef">when</span> value <span style="color:#f92672">&gt;</span> 0 <span style="color:#f92672">-&gt;</span> 1
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">|</span> value <span style="color:#66d9ef">when</span> value <span style="color:#f92672">&lt;</span> 0 <span style="color:#f92672">-&gt;</span> <span style="color:#f92672">-</span>1
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">|</span> <span style="color:#f92672">_</span> <span style="color:#f92672">-&gt;</span> 0
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> ret <span style="color:#f92672">=</span> testFunc 2
</span></span><span style="display:flex;"><span>printfn <span style="color:#e6db74">&#34;%A&#34;</span> ret
</span></span></code></pre></div><h1 id="records">Records</h1>
<p>Is this equivalent to <code>class</code> in C#?</p>
<p>It doesn&rsquo;t seem to have functions though.</p>
<p>But to avoid side effects, is it better to create it by passing a record type as an argument?</p>
<p>Like C# extension methods.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fsharp" data-lang="fsharp"><span style="display:flex;"><span><span style="color:#75715e">// Define the record type first
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">Favorite</span> <span style="color:#f92672">=</span> <span style="color:#f92672">{</span> color<span style="color:#f92672">:</span> <span style="color:#66d9ef">string</span><span style="color:#f92672">;</span> number<span style="color:#f92672">:</span> int<span style="color:#f92672">;</span> music<span style="color:#f92672">:</span> <span style="color:#66d9ef">string</span> <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> favorite <span style="color:#f92672">=</span> <span style="color:#f92672">{</span> color <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;red&#34;</span><span style="color:#f92672">;</span> number <span style="color:#f92672">=</span> 7<span style="color:#f92672">;</span> music <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Jazz&#34;</span> <span style="color:#f92672">}</span> 
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#f92672">{</span> color <span style="color:#f92672">=</span> favoriteColor<span style="color:#f92672">;</span> number <span style="color:#f92672">=</span> favoriteNumber<span style="color:#f92672">;</span> music <span style="color:#f92672">=</span> favoriteMusic<span style="color:#f92672">}</span> <span style="color:#f92672">=</span> favorite 
</span></span><span style="display:flex;"><span>printfn <span style="color:#e6db74">&#34;%s, %d, %s&#34;</span> favoriteColor favoriteNumber favoriteMusic
</span></span></code></pre></div><h1 id="discriminated-unions">Discriminated Unions</h1>
<p>My understanding of this is really low right now.</p>
<p>It&rsquo;s said to be close to <code>enum</code>, but since it can have associated values, it seems difficult to master.</p>
<p>But it feels like it would be satisfying if used well.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fsharp" data-lang="fsharp"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">Fruits</span> <span style="color:#f92672">=</span> 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">|</span> Apple
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">|</span> Orange
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">|</span> Grape
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> favoriteFruits <span style="color:#f92672">=</span> Apple
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>printfn <span style="color:#e6db74">&#34;%A&#34;</span> favoriteFruits
</span></span></code></pre></div><p>I&rsquo;m taking it slow, so that&rsquo;s all for today. I haven&rsquo;t even read half of the book yet, when will I finish&mdash;.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Ordered an Essential Phone</title>
      <link>https://ayumax.net/entry/2018/08/20/224900/</link>
      <pubDate>Mon, 20 Aug 2018 22:49:00 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/08/20/224900/</guid>
      <description>&lt;h1 id=&#34;essential-phone&#34;&gt;Essential Phone&lt;/h1&gt;
&lt;p&gt;During the Amazon Prime Day sale a little while ago, the Essential Phone (PH-1) was being sold at a super low price on Amazon.com. At that time, I hesitated and the sale ended before I could buy it.&lt;/p&gt;
&lt;p&gt;This device has acquired the technical conformity mark (Giteki) and supports Android 9 Pie, making its specs very appealing.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.dream-seed.com/weblog/us-amazon-essential-phone-280&#34;&gt;(Update) Essential Phone on sale for $223.99 on US Amazon&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Today, while browsing Twitter, I saw information that it was being sold for $279.99. I hesitated, but when I checked again in the evening, the price had dropped to $223.99.&lt;br/&gt;
Including shipping costs, it comes out to about 30,000 yen, which is incredibly cheap considering the specs.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="essential-phone">Essential Phone</h1>
<p>During the Amazon Prime Day sale a little while ago, the Essential Phone (PH-1) was being sold at a super low price on Amazon.com. At that time, I hesitated and the sale ended before I could buy it.</p>
<p>This device has acquired the technical conformity mark (Giteki) and supports Android 9 Pie, making its specs very appealing.</p>
<p><a href="https://www.dream-seed.com/weblog/us-amazon-essential-phone-280">(Update) Essential Phone on sale for $223.99 on US Amazon</a></p>
<p>Today, while browsing Twitter, I saw information that it was being sold for $279.99. I hesitated, but when I checked again in the evening, the price had dropped to $223.99.<br/>
Including shipping costs, it comes out to about 30,000 yen, which is incredibly cheap considering the specs.</p>
<p>I immediately clicked &ldquo;buy&rdquo;.</p>
<p>I was just thinking that I wanted an Android device to test the Xamarin app I&rsquo;m currently building, so the timing was perfect.
If I hadn&rsquo;t found this, I might have bought something like the HUAWEI P20 lite. I think that&rsquo;s a very good device too, though.</p>
<p>I chose the fastest shipping option, so I should be able to get my hands on it by the weekend.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Upgraded to Hatena Blog Pro</title>
      <link>https://ayumax.net/entry/2018/08/19/223654/</link>
      <pubDate>Sun, 19 Aug 2018 22:36:54 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/08/19/223654/</guid>
      <description>&lt;h1 id=&#34;upgraded-to-pro&#34;&gt;Upgraded to Pro&lt;/h1&gt;
&lt;p&gt;I started this blog at the end of last year and have finally managed to write 10 articles. &lt;br/&gt;
I&amp;rsquo;m not very good at keeping up with things that require continuity, so I think I&amp;rsquo;m doing quite well for myself.&lt;br/&gt;
To mark this occasion and as a declaration of my intention to &amp;ldquo;keep writing properly from now on,&amp;rdquo; I upgraded the blog to the paid version and set up a custom domain.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="upgraded-to-pro">Upgraded to Pro</h1>
<p>I started this blog at the end of last year and have finally managed to write 10 articles. <br/>
I&rsquo;m not very good at keeping up with things that require continuity, so I think I&rsquo;m doing quite well for myself.<br/>
To mark this occasion and as a declaration of my intention to &ldquo;keep writing properly from now on,&rdquo; I upgraded the blog to the paid version and set up a custom domain.</p>
<p>I acquired a domain name several years ago, but it&rsquo;s been so long that I had to look up various things again.</p>
<p>While I was at it, I also changed the design slightly for a fresh start.</p>
<p>So far, it&rsquo;s been 10 articles in 8 months, so I&rsquo;d like to pick up the pace and write more articles from now on.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Started Learning F#</title>
      <link>https://ayumax.net/entry/2018/08/17/002530/</link>
      <pubDate>Fri, 17 Aug 2018 00:25:30 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/08/17/002530/</guid>
      <description>&lt;h1 id=&#34;functional-programming&#34;&gt;Functional Programming&lt;/h1&gt;
&lt;p&gt;Honestly, I still don&amp;rsquo;t understand it well.&lt;br/&gt;
When should I choose it?&lt;br/&gt;
What are its advantages? To be honest, I don&amp;rsquo;t know.&lt;br/&gt;
Searching the web brings up things like &amp;ldquo;can write logic without side effects,&amp;rdquo; &amp;ldquo;code is easier to understand,&amp;rdquo; &amp;ldquo;testing is easier,&amp;rdquo; but I feel like I haven&amp;rsquo;t grasped the essence yet.&lt;br/&gt;
My image was that it&amp;rsquo;s a &amp;ldquo;language with a completely different way of thinking and usage from procedural languages,&amp;rdquo; and even if I memorized the meaning of arbitrary corresponding programming grammar, it wouldn&amp;rsquo;t mean I could actually use it. &lt;br/&gt;
That&amp;rsquo;s the strong impression I had – something in a realm I couldn&amp;rsquo;t touch.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="functional-programming">Functional Programming</h1>
<p>Honestly, I still don&rsquo;t understand it well.<br/>
When should I choose it?<br/>
What are its advantages? To be honest, I don&rsquo;t know.<br/>
Searching the web brings up things like &ldquo;can write logic without side effects,&rdquo; &ldquo;code is easier to understand,&rdquo; &ldquo;testing is easier,&rdquo; but I feel like I haven&rsquo;t grasped the essence yet.<br/>
My image was that it&rsquo;s a &ldquo;language with a completely different way of thinking and usage from procedural languages,&rdquo; and even if I memorized the meaning of arbitrary corresponding programming grammar, it wouldn&rsquo;t mean I could actually use it. <br/>
That&rsquo;s the strong impression I had – something in a realm I couldn&rsquo;t touch.</p>
<h1 id="f">F#</h1>
<p>Despite using C# for a long time, embarrassingly, I only learned about its existence recently.<br/>
I first learned about it at the Center CLR .Net600 study group I attended last year.<br/>
At that time, I was impressed that &ldquo;you can use a functional language with .Net&rdquo; and prepared my VS environment to use it, but I haven&rsquo;t touched it since then.</p>
<p>I think the main reason I didn&rsquo;t touch it was probably because I thought I needed to understand the underlying philosophy to use a functional language.</p>
<h1 id="reference-book">Reference Book</h1>
<p>Wanting to study F# properly, I was looking for books. Although it was published a little while ago, I found and purchased a book written by Mr. Arai, who also spoke at the aforementioned .Net600 event.<br/>
(I really wanted to buy it new, but couldn&rsquo;t find it, so I reluctantly bought it used.)</p>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="https://rcm-fe.amazon-adsystem.com/e/cm?ref=tf_til&t=theotoku-22&m=amazon&o=9&p=8&l=as1&IS2=1&detail=1&asins=4774145165&linkId=92b183d41e10fbe7fac5da1f31494cf2&bc1=ffffff&lt1=_blank&fc1=333333&lc1=0066c0&bg1=ffffff&f=ifr">
    </iframe>
<p>I haven&rsquo;t finished reading it all yet, but as the book title suggests, it&rsquo;s written for beginners, so for now, it feels like the information is sinking in properly!</p>
<p>I wonder if it will get more difficult in the latter half, but I intend to read it through without giving up.
Lately, most information can be found online, but personally, I prefer having a book because I can concentrate better and absorb the information.</p>
<h1 id="just-try-it">Just Try It</h1>
<p>Because the fixed idea that &ldquo;functional languages are quite difficult&rdquo; occupied my mind, I was hesitant to start. However, I realized that if I stay like this, I&rsquo;ll never be able to use it, so I decided to just try touching it.<br/>
Fortunately, I&rsquo;ve been using C# for a long time, so I think F#, which uses the same .Net, will be easier to approach.
And I won&rsquo;t know what it&rsquo;s like unless I try.</p>
<p>If I hit a wall after trying, I&rsquo;ll think about what to do then!</p>
]]></content:encoded>
    </item>
    <item>
      <title>Gave an LT at CenterCLR Study Group</title>
      <link>https://ayumax.net/entry/2018/08/13/014523/</link>
      <pubDate>Mon, 13 Aug 2018 01:45:23 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/08/13/014523/</guid>
      <description>&lt;h1 id=&#34;attended-study-group&#34;&gt;Attended Study Group&lt;/h1&gt;
&lt;p&gt;I attended the CenterCLR study group on 8/11.&lt;/p&gt;
&lt;h2 id=&#34;signed-up-for-lt&#34;&gt;Signed Up for LT&lt;/h2&gt;
&lt;p&gt;Initially, I signed up for the regular participation slot, but one day I happened to check and saw an LT (Lightning Talk) slot was open, so I signed up for it.
At that point, I hadn&amp;rsquo;t decided what to talk about yet, but I started deciding on the topic and preparing the presentation materials for the day (this was about 2 weeks prior).&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="attended-study-group">Attended Study Group</h1>
<p>I attended the CenterCLR study group on 8/11.</p>
<h2 id="signed-up-for-lt">Signed Up for LT</h2>
<p>Initially, I signed up for the regular participation slot, but one day I happened to check and saw an LT (Lightning Talk) slot was open, so I signed up for it.
At that point, I hadn&rsquo;t decided what to talk about yet, but I started deciding on the topic and preparing the presentation materials for the day (this was about 2 weeks prior).</p>
<h2 id="day-of-the-study-group">Day of the Study Group</h2>
<p>After the sponsor session, the speakers&rsquo; sessions began.
I was really looking forward to Mr. Ueda&rsquo;s introduction of lessons using HoloLens. I thought it was amazing, and the biggest thing I felt was that I wished something like this existed when I was in middle or high school.</p>
<p>Mr. Matsui&rsquo;s talk was also about something I was thinking of starting myself, so I listened with great interest.</p>
<h2 id="my-turn">My Turn</h2>
<p>There was one break during the study group, and the LT time was after the break.
I got extremely nervous right before, so much so that I couldn&rsquo;t even go see the HoloLens during the break as I had planned&hellip;
Since it was my first LT, I managed to stick to the 5-minute time limit as practiced beforehand.</p>
<p>However, I was too nervous. I remember thinking, &ldquo;Oh no, I&rsquo;m stumbling over my words&rdquo; at the beginning, and when I did the demo, my hands were shaking so much I couldn&rsquo;t use the mouse properly, which made me panic a bit.</p>
<p>Also, I ended up speaking while looking at the display the whole time. If I get a chance to be more composed next time, I thought I need to make sure I look at the audience while speaking.</p>
<h3 id="here-are-the-slides-i-presented-today">Here are the slides I presented today</h3>
<iframe src="https://www.slideshare.net/slideshow/embed_code/key/hU4pCU1T35YVxL" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen=""> </iframe> <div style="margin-bottom:5px"> <strong> <a href="https://www.slideshare.net/AyumaKaminosono/markdown-109489085" title="Create PowerPoint documents with Markdown" target="_blank">Create PowerPoint documents with Markdown</a> </strong> from <strong><a href="https://www.slideshare.net/AyumaKaminosono" target="_blank">AyumaKaminosono</a></strong> </div><cite class="hatena-citation"><a href="https://www.slideshare.net/AyumaKaminosono/markdown-109489085">www.slideshare.net</a></cite>
<h2 id="after-party">After-Party</h2>
<p>I participated in the after-party following the study group and got to hear various stories.<br/>
There were some high-level discussions I couldn&rsquo;t understand, but it turned out to be a fun day.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Outputting PowerPoint Files (*.pptx) Using OpenXML SDK in C#</title>
      <link>https://ayumax.net/entry/2018/09/04/021745/</link>
      <pubDate>Wed, 08 Aug 2018 02:17:45 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/09/04/021745/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;This article is a continuation of &lt;a href=&#34;https://www.ayumax.net/entry/2018/09/04/021905&#34;&gt;Parsing Markdown and Performing Custom Output in C# (Using markdig)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The tool mentioned in the above article, which converts Markdown to PPTX, creates PPTX files using the OpenXML SDK.
I initially struggled greatly with using this OpenXML SDK, so this article will focus on that part.&lt;/p&gt;
&lt;p&gt;The tool that converts Markdown to PPTX is available on GitHub.&lt;/p&gt;
&lt;div class=&#34;github-card&#34; data-user=&#34;ayumax&#34; data-repo=&#34;MDToPPTX&#34; data-width=&#34;400&#34; data-height=&#34;&#34; data-theme=&#34;default&#34;&gt;&lt;/div&gt;
&lt;script src=&#34;https://cdn.jsdelivr.net/github-cards/latest/widget.js&#34;&gt;&lt;/script&gt;
&lt;h2 id=&#34;what-is-openxml&#34;&gt;What is OpenXML?&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s a file format used since Office 2007, consisting of XML files bundled into a zip archive.&lt;br/&gt;
Therefore, by changing the file extension to .zip and then unzipping it, you can view the XML files inside.
Unlike the previous binary format, it allows creation even in environments where Office is not installed.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="introduction">Introduction</h1>
<p>This article is a continuation of <a href="https://www.ayumax.net/entry/2018/09/04/021905">Parsing Markdown and Performing Custom Output in C# (Using markdig)</a>.</p>
<p>The tool mentioned in the above article, which converts Markdown to PPTX, creates PPTX files using the OpenXML SDK.
I initially struggled greatly with using this OpenXML SDK, so this article will focus on that part.</p>
<p>The tool that converts Markdown to PPTX is available on GitHub.</p>
<div class="github-card" data-user="ayumax" data-repo="MDToPPTX" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<h2 id="what-is-openxml">What is OpenXML?</h2>
<p>It&rsquo;s a file format used since Office 2007, consisting of XML files bundled into a zip archive.<br/>
Therefore, by changing the file extension to .zip and then unzipping it, you can view the XML files inside.
Unlike the previous binary format, it allows creation even in environments where Office is not installed.</p>
<h1 id="development-environment">Development Environment</h1>
<p>Here&rsquo;s the setup:</p>
<ul>
<li>Windows 10</li>
<li>Visual Studio 2017</li>
<li>C#</li>
<li>.NET Standard 2.0 Class library</li>
</ul>
<h1 id="about-openxml-sdk">About OpenXML SDK</h1>
<p>I referred to the following official website for the OpenXML description method:
<a href="https://docs.microsoft.com/en-us/office/open-xml/open-xml-sdk"><a href="https://docs.microsoft.com/en-us/office/open-xml/open-xml-sdk">https://docs.microsoft.com/en-us/office/open-xml/open-xml-sdk</a></a></p>
<p>However, understanding it solely from the explanations on the above site likely takes considerable time. Therefore, if you plan to use the OpenXML SDK from now on, I recommend the following method.</p>
<h2 id="open-xml-sdk-productivity-tool">Open XML SDK Productivity Tool</h2>
<p><a href="https://www.microsoft.com/en-us/download/details.aspx?id=30425"><a href="https://www.microsoft.com/en-us/download/details.aspx?id=30425">https://www.microsoft.com/en-us/download/details.aspx?id=30425</a></a></p>
<img src="https://qiita-image-store.s3.amazonaws.com/0/119290/1b6be7d5-dc58-e1e1-400d-e28644a61c1d.jpeg" alt="openxmlsdktool.JPG"/>
<p>Using this tool, you can inspect the internal structure of a specified OpenXML format file (like xlsx or pptx).<br/>
What&rsquo;s also helpful for tool creation is the feature that displays the necessary C# code to create the loaded file in the right-hand pane.</p>
<p>So, by creating a file with the content you want to implement, loading it, and examining the C# code, the possibility of creating something functional, even without 100% understanding, increases significantly.</p>
<p>I used this to find the code I needed by looking at small differences.</p>
<h2 id="example-how-to-find-out-how-to-make-text-bold">Example: How to find out how to make text bold</h2>
<ol>
<li>Place only one text element in a newly created pptx file and check the C# code.</li>
<li>Copy the above pptx file, make the text part Bold, and check the C# code.</li>
<li>Compare 1. and 2.</li>
</ol>
<h1 id="explanation-of-powerpoints-openxml-class-structure">Explanation of PowerPoint&rsquo;s OpenXML Class Structure</h1>
<p>Basically, using the method described above with the Open XML SDK Productivity Tool allows you to create the functionality you want, so the discussion could end here. However, I will write down the class structure I investigated below, partly as a personal memo.</p>
<p>The class structure of OpenXML files is quite large, so I&rsquo;m focusing only on the important parts.</p>
<h2 id="overall-structure">Overall Structure</h2>
<p>First, the overall structure.</p>
<img src="http://www.plantuml.com/plantuml/png/SoWkIImgAStDuU8goIp9ILK820Y9UBQy-sN30YuWICv9B2vM2Cx9J4aD0Af35V5DB2v9BGA9GqL3Cb9pKTKf1HIb5gVcbIIMPERdWMIK51AB5T055Qgv51GKk6g1sZ2ab0oL57HrxHIKj9GGxb2mKb22SugL2EX2k1Mk5o64omIGTeY7O9hW72MildF9JoxD1NAWFiIKKAW6-H2B3DGo32TOeLe0jTeXDIy565y0" alt=""/>
<p>To create a PPTX, you&rsquo;ll mostly interact with SlidePart and SlideMasterPart at the bottom of the diagram.<br/>
The division of responsibilities is roughly: SlideMasterPart for overall slide settings (like slide size), and SlidePart for individual slides.
ThemePart is manipulated when changing the visual design. Although not shown in the diagram, if you use slide layouts, you&rsquo;ll also touch SlideLayout.
(The feature I created uses the Blank style sheet for all slides except the first title sheet, so I haven&rsquo;t touched slide layouts.)</p>
<h2 id="slide">Slide</h2>
<p>Next is the slide. Since it corresponds to a single slide in PowerPoint, the number of SlidePart class instances equals the number of pages.</p>
<img src="http://www.plantuml.com/plantuml/png/TPA_JiCm4CRtUugJfnQf0si7L0d4dosY7LXDQXgB98xiwy06pSY040y0bP1036LWOO2dCI1u2nm7JEYVB3b_ztq_NwBh6UAQnbcA_LGE1G19IWL6qU3Wu-xyw_IcvVKs0CGfDmRPZkP58kDjpJFH-fpUjnboWqtrrzfFU246MWW85MAdi-7CQbnuBTAg49gaC0qFMsVUnjPOpLZHQzw9OS1DbMKgzrDlSU8mTwud-0DsaOK32vFN_yA_V62UMiNcfF_XY6i22AM3Q3bAo96yLkLzmHgUvhVjdXH2fp8_tXSf9wboayYYIYrjc5MOlOoFlDfbeNHco1K9F5H4AaDrjFmsGFVOyi9ERcrvQSiNMpxOyibE7ktPx7rs_VPw1I8VOiLQ88RRFCKZfXLYyhmO3giLoPZ6MhIQzdgzVZgmOXD2k-UORfc_0G00" alt=""/>
<p>The diagram above extracts only the classes that become important when implementing the following features:</p>
<ul>
<li>Placing text boxes</li>
<li>Inserting images</li>
<li>Inserting tables</li>
</ul>
<p>Basically, all objects placed within a slide seem to hang under ShapeTree.<br/>
The most frequently used text box corresponds to Shape under ShapeTree in this diagram.<br/>
Picture represents images, and GraphicFrame represents tables.</p>
<p>ImagePart and HyperlinkRelationship, which hang under SlidePart, are not under ShapeTree. This is meaningful because, in OpenXML, images and hyperlinks have their actual substance embedded separately from the drawing objects. When used, the substance&rsquo;s ID is referenced to paste the image, etc.<br/>
Therefore, if the same image file is used in multiple places, there will be multiple Pictures referencing a single ImagePart.<br/>
However, since these are all under SlidePart, it seems necessary to add another ImagePart when adding an image to a different sheet (can references span across sheets&hellip;?).</p>
<h2 id="shape">Shape</h2>
<p>Next is Shape. Although I only used text boxes this time, judging by the name, I assume other shapes are handled in this part as well.</p>
<img src="http://www.plantuml.com/plantuml/png/TL9FQnGn5B_dKuISgj237WSftQrR5AGjRlKUTzvsmsQI8N-WYope34W5FNhe9r0H5VIas4yJhVqOpYITcEcqUvWalpylUMz_szfGPMp1qOnJhV5qGKiuKB84PHXeT0cJGpWsOvclDbpzobMVNVN3rIUt2AOQTrIdFQ2A7YbQBb37uCtDhGGU2F_VznpXvZVYx4WK80pEVFLuFboLy9Ho2zhhzkJOSWwDB6uz7hQxqXU8Xy3jBAYYCmCgMgyWQ6IDtBF5Cr2G1oWRGcYD48eDz1iSZk-n5OcOt27UG6wJbi4uaLqTnLZol6r2IWvK-Duz_j1GpcRNCKz43eep0Gqv4RRmpBrsZ9498zpoygbHR3dK1hWJhb7pjFRD_ISsBj83IDV98sgOy3Fl6zeIaUl44whDI3DwWo7XeocaBhwgFU0if9IWDCh8VwEeJMCMmqmIziRWAohqNAhYxlsDtsTl_vvzSIzU_ldv_lp3QOX_8i3XFzkVppMOB2mUcHmR44PdbojQXulxVQQLkklnL7AMxpBEhtL4DYCNzPlpqwyNhxyHD1nXAdJrErTzTFLtLv-uwfEhc_slEBG7gz9dPBalTfg0BOUrXf9j4Baj-3y0" alt=""/>
<p>The features I wanted to achieve with the text box this time are as follows:</p>
<ul>
<li>Place text at an arbitrary position</li>
<li>Allow setting bullet points</li>
<li>Allow specifying fonts</li>
<li>Allow specifying Bold, Italic, Underline, Strikethrough for fonts</li>
<li>Allow specifying font color</li>
<li>Allow changing font settings for only arbitrary strings within the text box</li>
<li>Allow setting hyperlinks</li>
</ul>
<p>Position and size are handled by Transform2D. There&rsquo;s a very similar class called Transform, which seems to be used for tables that appear later.<br/>
The text settings themselves are done under TextBody.<br/>
ParagraphProperties handle horizontal alignment (Left, Center, Right) and bullet point settings.
For regular bullet points, BulletFont and CharacterBullet are used. For numbered incrementing bullet points, BulletFont and AutoNumberedBullet are used.
If no bullet points are needed, NoBullet is set.</p>
<p>Settings for the text within the text box are done using Run. By creating multiple Runs, you can mix strings with different font settings within a single text box.</p>
<p>Hyperlinks can be set on RunProperties. When used, the ID of the pre-embedded HyperlinkRelationship is specified in HyperlinkOnClick&rsquo;s Id.</p>
<p>The background color of the text box and the foreground color of the font can be specified with SolidFill, allowing specification by predefined colors or RGB values. (Gradients might be represented by a different class than SolidFill).</p>
<h2 id="image">Image</h2>
<p>Next is images.
An ImagePart object needs to be created beforehand.
Since a Stream can be specified for the ImagePart object, you can read an image file using System.IO.FileStream and then create the object directly.</p>
<img src="http://www.plantuml.com/plantuml/png/SoWkIImgAStDKV3CJKnFvU9ApaaiBbO8o4mkAIs2SvroCWlSCdDoaBWArLmAGE2QcvIQOXLSKfIPbnwMc5EQobNBnGLJhg2hQmTHRAMW1AALO0O2DQIM96T0p00f3KfDBadCIyz9jKBcOPW6qmWpHocaA36lE2s_ADV8HUF9tjxdUzSzRcXykclvinKpDPKK4eiLa1H0dUoVbbQSMc85eI2Ug2X9pIifjeBINBLmPsOa5gG65EKNf1QLPAOMSt6X2O2SX6m35nSqu83Y69eHKeZmv798pKi1XZu0" alt=""/>
<p>Similar to text boxes, position and size are specified using Transform2D.
The image itself is specified by setting the Embed property of Blip to the ID of the pre-created ImagePart.
If necessary, the stretching method can be specified in Stretch. (I didn&rsquo;t use this, so I haven&rsquo;t investigated it in detail).</p>
<h2 id="table">Table</h2>
<p>Finally, tables. It&rsquo;s long, but some parts are the same as text boxes, so there aren&rsquo;t that many new objects.</p>
<img src="http://www.plantuml.com/plantuml/png/TLJDRXCn4BxFKrW-5QGUa12725NjXgHKGg8g0Sv3raail7PaUqKhL0bQ2N7X0NW2kC0Tf3xDylCQx7XZrviikMmyty_tpSRAeVDeVLqfDiDNIW3C5Jh7ZYskLt8-jLW9Y4C-iwZTmjXgxzVDfxyttvjtxt___FBdw-SxdA5Z2MPlWRMVfuk54txKFS9aSkw5zcwqUS8bG9x4zlSFRbsskcmT7w77f2PX3h0HuzcHxwRqJUFocOPOSPnnJgrP2-kbS9ibfz8wVsRUi3QpC4O9r2zGrIA01Ufo0AEzWriAoNnxSSTMbZat3IEBle-DgYkzwVDIbdxLvfre_-1-Iaiwnk_nuCJlyapS2wN6dTbZ8PShF-oMEoLTpsSib0A8KCxFyNIvnBalJ7cnrrn_QAw-DLS_ckkFtSMA443IaLEQHuzJjBYadn0YaeTcy8xWzlLtYnyfkTILqBGxUQNpx68jmdi8bnUI0OKCsSMairfdvAmL8InZRJSfZ2g7hjQ9HoNdGyXpNGghf1OjED5r5P27j4L2kWqE0lsPj_BrBZUC4_4Ig2PLxbLiLRmtu76J9-YbdXhjeOS7YuH5yWITFt8I_oT8U2wYagaL7QWCFJa070fTqfyQWty0" alt=""/>
<p>Position and size are handled by the Transform object (not Transform2D).
Whether there&rsquo;s a title row or not can be set in TableProperties.</p>
<p>To actually create the table, first add GridColumns to TableGrid for the number of columns. The column width can also be specified at this time.
Next, add TableRows to Table for the number of rows. The row height can be specified in TableRow.
Table cells are implemented by adding TableCells to TableRow.
The content of TableCell is almost the same as TextBody and below from the text box section.</p>
<h1 id="afterword">Afterword</h1>
<p>This time, I wrote about what I learned regarding how to create PowerPoint files using the OpenXML SDK.
Although I haven&rsquo;t tried adding animations or various shapes, which weren&rsquo;t covered this time, I believe it can be done similarly by analyzing with the Open XML SDK Productivity Tool. This tool is truly convenient.</p>
<p>Please refer to this if you want to add PowerPoint file output functionality to your C# application.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Parsing Markdown and Performing Custom Output in C# (Using markdig)</title>
      <link>https://ayumax.net/entry/2018/09/04/021905/</link>
      <pubDate>Tue, 07 Aug 2018 02:19:05 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/09/04/021905/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;I recently created a tool to convert Markdown files into PowerPoint format (*.pptx).&lt;br/&gt;
I&amp;rsquo;ll summarize the technical notes from that process here.
This article focuses on Markdown parsing.&lt;/p&gt;
&lt;p&gt;The created tool is available on GitHub.
&lt;a href=&#34;https://github.com/ayumax/MDToPPTX&#34;&gt;&lt;a href=&#34;https://github.com/ayumax/MDToPPTX&#34;&gt;https://github.com/ayumax/MDToPPTX&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Also, for the article about the pptx creation tool itself, please refer to &lt;a href=&#34;http://www.ayumax.net/entry/2018/06/06/005349&#34;&gt;this article&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;development-environment&#34;&gt;Development Environment&lt;/h1&gt;
&lt;p&gt;Considering future integration into a tool using Xamarin, I created the project as a .NET Standard 2.0 C# library.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="introduction">Introduction</h1>
<p>I recently created a tool to convert Markdown files into PowerPoint format (*.pptx).<br/>
I&rsquo;ll summarize the technical notes from that process here.
This article focuses on Markdown parsing.</p>
<p>The created tool is available on GitHub.
<a href="https://github.com/ayumax/MDToPPTX"><a href="https://github.com/ayumax/MDToPPTX">https://github.com/ayumax/MDToPPTX</a></a></p>
<p>Also, for the article about the pptx creation tool itself, please refer to <a href="http://www.ayumax.net/entry/2018/06/06/005349">this article</a>.</p>
<h1 id="development-environment">Development Environment</h1>
<p>Considering future integration into a tool using Xamarin, I created the project as a .NET Standard 2.0 C# library.</p>
<p>The overall environment is as follows:</p>
<ul>
<li>Windows 10</li>
<li>Visual Studio 2017</li>
<li>C#</li>
<li>.NET Standard 2.0 Class library</li>
</ul>
<h1 id="how-to-parse-markdown">How to Parse Markdown</h1>
<p>Initially, I considered parsing it myself using regular expressions or something similar. However, the Markdown format has surprisingly many variations, so I searched for a convenient library and found the following.</p>
<h2 id="markdig">markdig</h2>
<div class="github-card" data-user="lunet-io" data-repo="markdig" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<p>This library is available on GitHub under the BSD-Clause 2 license and can be obtained via NuGet.
If you just want to convert Markdown to HTML, you can use it as is. It&rsquo;s also designed so that you can create your own output part for formats other than HTML.</p>
<h2 id="standard-usage-of-markdig">Standard Usage of markdig</h2>
<p>To convert Markdown to HTML, only the following description is needed (excerpt from GitHub&rsquo;s README.md):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> result = Markdown.ToHtml(<span style="color:#e6db74">&#34;This is a text with some *emphasis*&#34;</span>);
</span></span><span style="display:flex;"><span>Console.WriteLine(result);   <span style="color:#75715e">// prints: &lt;p&gt;This is a text with some &lt;em&gt;emphasis&lt;/em&gt;&lt;/p&gt;</span>
</span></span></code></pre></div><h1 id="using-markdig-as-a-parser">Using markdig as a Parser</h1>
<p>My goal this time was to parse Markdown and output a PowerPoint file, so I investigated whether I could use only markdig&rsquo;s parser functionality and create custom output.</p>
<h2 id="how-markdigs-processing-works">How markdig&rsquo;s Processing Works</h2>
<p>To find out how to perform custom output using markdig, I examined how the preset HtmlRenderer is implemented. The diagram below simplifies this.</p>
<img src="http://www.plantuml.com/plantuml/png/SoWkIImgAStDuU9ApaaiBbO8IirBIIrABN9AB4wjvk9I00F_fApKv1AOLB4Lce1pVauEa9kPdmTL3wKWyXgQNBKmqprASdDWkg128QaL9SYMSd4XynHiQdHrCTM0132KePhk06G0_GK0" alt="markdig rendering part"/>
<p>Tracing the inheritance of HtmlRenderer leads to RendererBase, which defines the Render() method used during conversion and the ObjectRenderers property for handling Markdown blocks and inlines.</p>
<h2 id="renderer">Renderer</h2>
<p>It&rsquo;s designed to define a Renderer class for each output file type. The default implementation includes HtmlRenderer for outputting HTML files and NormalizeRenderer for outputting normalized Markdown text.<br/>
TextRendererBase in the middle of the class diagram above is a class that bundles the functionality of Renderers that output to text files.</p>
<h2 id="objectrenderers">ObjectRenderers</h2>
<p>This part defines how the parsed Markdown objects should be output.
In the HtmlRenderer constructor, it&rsquo;s implemented like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#75715e">// Default block renderers</span>
</span></span><span style="display:flex;"><span>ObjectRenderers.Add(<span style="color:#66d9ef">new</span> CodeBlockRenderer());
</span></span><span style="display:flex;"><span>ObjectRenderers.Add(<span style="color:#66d9ef">new</span> ListRenderer());
</span></span><span style="display:flex;"><span>ObjectRenderers.Add(<span style="color:#66d9ef">new</span> HeadingRenderer());
</span></span><span style="display:flex;"><span>ObjectRenderers.Add(<span style="color:#66d9ef">new</span> HtmlBlockRenderer());
</span></span><span style="display:flex;"><span>ObjectRenderers.Add(<span style="color:#66d9ef">new</span> ParagraphRenderer());
</span></span><span style="display:flex;"><span>ObjectRenderers.Add(<span style="color:#66d9ef">new</span> QuoteBlockRenderer());
</span></span><span style="display:flex;"><span>ObjectRenderers.Add(<span style="color:#66d9ef">new</span> ThematicBreakRenderer());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Default inline renderers</span>
</span></span><span style="display:flex;"><span>ObjectRenderers.Add(<span style="color:#66d9ef">new</span> AutolinkInlineRenderer());
</span></span><span style="display:flex;"><span>ObjectRenderers.Add(<span style="color:#66d9ef">new</span> CodeInlineRenderer());
</span></span><span style="display:flex;"><span>ObjectRenderers.Add(<span style="color:#66d9ef">new</span> DelimiterInlineRenderer());
</span></span><span style="display:flex;"><span>ObjectRenderers.Add(<span style="color:#66d9ef">new</span> EmphasisInlineRenderer());
</span></span><span style="display:flex;"><span>ObjectRenderers.Add(<span style="color:#66d9ef">new</span> LineBreakInlineRenderer());
</span></span><span style="display:flex;"><span>ObjectRenderers.Add(<span style="color:#66d9ef">new</span> HtmlInlineRenderer());
</span></span><span style="display:flex;"><span>ObjectRenderers.Add(<span style="color:#66d9ef">new</span> HtmlEntityInlineRenderer());            
</span></span><span style="display:flex;"><span>ObjectRenderers.Add(<span style="color:#66d9ef">new</span> LinkInlineRenderer());
</span></span><span style="display:flex;"><span>ObjectRenderers.Add(<span style="color:#66d9ef">new</span> LiteralInlineRenderer());
</span></span></code></pre></div><p>The first half of the definition adds objects that define block-level output, and the second half adds objects with output definitions for inline parts within blocks.
Since parsed MarkdownBlock objects contain further Inline objects internally, separating the Renderer into Block and Inline makes implementation easier.</p>
<p>When implementing a custom Renderer, you just need to create and add an ObjectRenderer for your target parse object.
When the Renderer class&rsquo;s Render() method is called, the Write() method of the ObjectRenderer corresponding to the Block object is called. Then, recursively, the Write() method of the ObjectRenderer corresponding to the Inline object is called, producing the output.</p>
<h2 id="objectrenderer-creation-example">ObjectRenderer Creation Example</h2>
<p>The first argument of the ObjectRenderer&rsquo;s Write() method receives a reference to the Renderer class, and the second argument receives a reference to the parsed block.</p>
<p>Methods related to file output are grouped in the Renderer class and called from within the Write() method.</p>
<h3 id="example-1-headingblock">Example 1: HeadingBlock</h3>
<p>In the example below, the output options are changed only if the header block level is H1 or H2.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">HeadingRenderer</span> : PPTXObjectRenderer&lt;HeadingBlock&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> Write(PPTXRenderer renderer, HeadingBlock obj)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Change output options for each header level</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> _block = renderer.Options.Normal;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">switch</span> (obj.Level)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">case</span> <span style="color:#ae81ff">1</span>:
</span></span><span style="display:flex;"><span>                _block = renderer.Options.Header1;
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">case</span> <span style="color:#ae81ff">2</span>:
</span></span><span style="display:flex;"><span>                _block = renderer.Options.Header2;
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        renderer.PushBlockSetting(_block);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        renderer.StartTextArea();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        renderer.WriteLeafInline(obj);
</span></span><span style="display:flex;"><span>        renderer.PopBlockSetting();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        renderer.EndTextArea();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="example-2-listblock">Example 2: ListBlock</h3>
<p>ListBlock provides a list of bullet points, so it loops through the list items and processes the internal objects further.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ListRenderer</span> : PPTXObjectRenderer&lt;ListBlock&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> Write(PPTXRenderer renderer, ListBlock listBlock)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Apply list writing settings</span>
</span></span><span style="display:flex;"><span>        renderer.PushBlockSetting(renderer.Options.List);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        renderer.StartTextArea();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Loop through list items</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">var</span> i = <span style="color:#ae81ff">0</span>; i &lt; listBlock.Count; i++)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">var</span> item = listBlock[i];
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">var</span> listItem = (ListItemBlock)item;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            renderer.AddTextRow(<span style="color:#66d9ef">new</span> PPTXText()
</span></span><span style="display:flex;"><span>            {
</span></span><span style="display:flex;"><span>                <span style="color:#75715e">// Set whether it&#39;s a numbered or symbol bullet point</span>
</span></span><span style="display:flex;"><span>                Bullet = listBlock.IsOrdered ? PPTXBullet.Number : PPTXBullet.Circle
</span></span><span style="display:flex;"><span>            });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// Process the content of one list item</span>
</span></span><span style="display:flex;"><span>            renderer.WriteChildren(listItem);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            renderer.WriteReturn();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        renderer.EndTextArea();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Restore list writing settings</span>
</span></span><span style="display:flex;"><span>        renderer.PopBlockSetting();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="example-3-codeinline">Example 3: CodeInline</h3>
<p>Unlike the previous two examples, CodeInline is an Inline, not a Block. Therefore, the key point is to be aware that you are processing part of a sentence (it feels like you need to avoid line breaks within the InlineRenderer&rsquo;s Write).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">CodeInlineRenderer</span> : PPTXObjectRenderer&lt;CodeInline&gt;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>   <span style="color:#66d9ef">protected</span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">void</span> Write(PPTXRenderer renderer, CodeInline obj)
</span></span><span style="display:flex;"><span>   {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Change font settings only for the inline code part</span>
</span></span><span style="display:flex;"><span>        renderer.PushInlineSetting(renderer.Options.InlineCode);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Write the inline code part</span>
</span></span><span style="display:flex;"><span>        renderer.Write(obj.Content);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Restore font settings</span>
</span></span><span style="display:flex;"><span>        renderer.PopBlockSetting();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="extensions">Extensions</h2>
<p>When I first created it and tested the operation, table notation and strikethrough notation were not parsed. I thought they might not be supported, but they were handled as extensions.</p>
<p>I was able to parse with table notation and text decoration symbol extensions enabled using the following description:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> pipeline = <span style="color:#66d9ef">new</span> MarkdownPipelineBuilder()
</span></span><span style="display:flex;"><span>                <span style="color:#75715e">// Enable table extension</span>
</span></span><span style="display:flex;"><span>                .UsePipeTables()
</span></span><span style="display:flex;"><span>                <span style="color:#75715e">// Enable text decoration symbol extension</span>
</span></span><span style="display:flex;"><span>                .UseEmphasisExtras()
</span></span><span style="display:flex;"><span>                .Build();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> document = Markdig.Markdown.Parse(markdown, pipeline);
</span></span></code></pre></div><ul>
<li>Using <code>UseAdvancedExtensions()</code> seems to allow parsing with all extensions enabled.</li>
</ul>
<h1 id="summary">Summary</h1>
<p>By implementing using markdig, I could focus my thoughts on how to format the output for each Block and Inline unit, without worrying about parsing the Markdown string or complex nested object structures, which significantly reduced implementation time.</p>
<p>If I need to support more Blocks in the future, it seems I can do so with minimal impact on the current implementation.</p>
<p>Although my implementation this time was to output a PowerPoint file, I believe the content of this article can be applied in various other ways.</p>
]]></content:encoded>
    </item>
    <item>
      <title>MDToPPTX Image Handling</title>
      <link>https://ayumax.net/entry/2018/08/05/005358/</link>
      <pubDate>Sun, 05 Aug 2018 00:53:58 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/08/05/005358/</guid>
      <description>&lt;h2 id=&#34;long-time-no-update&#34;&gt;Long Time No Update&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s been quite a while since I last wrote an article about MDToPPTX.&lt;br/&gt;
I&amp;rsquo;m scheduled to give a talk about creating this tool for my first-ever LT (Lightning Talk), so I&amp;rsquo;m reviewing the code again.&lt;/p&gt;
&lt;div class=&#34;github-card&#34; data-user=&#34;ayumax&#34; data-repo=&#34;MDToPPTX&#34; data-width=&#34;400&#34; data-height=&#34;&#34; data-theme=&#34;default&#34;&gt;&lt;/div&gt;
&lt;script src=&#34;https://cdn.jsdelivr.net/github-cards/latest/widget.js&#34;&gt;&lt;/script&gt;
&lt;h2 id=&#34;image-implementation&#34;&gt;Image Implementation&lt;/h2&gt;
&lt;p&gt;At the time of the previous article, I had tentatively implemented images assuming 1px to 1mm, but&amp;hellip; the implementation was strange and incorrect.
With that, the width of a 1000px image was being converted to 1cm.&lt;br/&gt;
(The physical width (cm) was set by dividing the pixel count by 1000).&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="long-time-no-update">Long Time No Update</h2>
<p>It&rsquo;s been quite a while since I last wrote an article about MDToPPTX.<br/>
I&rsquo;m scheduled to give a talk about creating this tool for my first-ever LT (Lightning Talk), so I&rsquo;m reviewing the code again.</p>
<div class="github-card" data-user="ayumax" data-repo="MDToPPTX" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<h2 id="image-implementation">Image Implementation</h2>
<p>At the time of the previous article, I had tentatively implemented images assuming 1px to 1mm, but&hellip; the implementation was strange and incorrect.
With that, the width of a 1000px image was being converted to 1cm.<br/>
(The physical width (cm) was set by dividing the pixel count by 1000).</p>
<h2 id="solution">Solution</h2>
<p>Ideally, I&rsquo;d like to specify the width and height in the Markdown itself, but I haven&rsquo;t found a good solution for that yet. So, I decided to determine the image size using DPI-based calculations, similar to font sizes.
Apparently, the default setting in PowerPoint is 96dpi, so,</p>
<pre tabindex="0"><code>96dpi =&gt; 96px/inch =&gt; 96px/25.4mm, therefore
imageSize(cm) = imageSize(px) / 96 * 2.54
</code></pre><p><em>Correction: The calculation was slightly off. It should be:</em></p>
<pre tabindex="0"><code>imageSize(cm) = imageSize(px) / 96 * 2.54
</code></pre><p><em>Let&rsquo;s recalculate based on 96px/inch = 96px/2.54cm:</em></p>
<pre tabindex="0"><code>imageSize(cm) = imageSize(px) / 96 * 2.54 
</code></pre><p><em>Wait, 1 inch = 2.54 cm. So 96 px = 2.54 cm. Therefore, 1 px = 2.54 / 96 cm.</em></p>
<pre tabindex="0"><code>imageSize(cm) = imageSize(px) * (2.54 / 96)
</code></pre><p><em>Let&rsquo;s use this calculation.</em></p>
<pre tabindex="0"><code>imageSize(cm) = imageSize(px) * 2.54 / 96
</code></pre><p>I set it like this.</p>
<p>With this, I still can&rsquo;t achieve the exact size I intended,
but I think the images can be pasted onto PowerPoint slides at a size that doesn&rsquo;t feel out of place.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Qt Study Group Achievement: Created a TCP/IP Sample</title>
      <link>https://ayumax.net/entry/2018/07/28/215239/</link>
      <pubDate>Sat, 28 Jul 2018 21:52:39 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/07/28/215239/</guid>
      <description>&lt;h2 id=&#34;attended-qt-nagoya-study-group&#34;&gt;Attended Qt Nagoya Study Group&lt;/h2&gt;
&lt;p&gt;Although a week has passed, I attended the Qt study group in Nagoya last week.&lt;/p&gt;
&lt;p&gt;Last time, I mainly focused on QML, so this time I decided to focus on C++.&lt;br/&gt;
I decided to implement a TCP/IP communication feature, which seems like it could be useful later on.&lt;/p&gt;
&lt;h2 id=&#34;software-created&#34;&gt;Software Created&lt;/h2&gt;
&lt;p&gt;The resulting software looks like this.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;ja&#34; dir=&#34;ltr&#34;&gt;先週のQt勉強会で作ったTCPIPのサンプル。マウスの軌跡を飛ばしてる。 &lt;a href=&#34;https://t.co/jmbTxED2gd&#34;&gt;pic.twitter.com/jmbTxED2gd&lt;/a&gt;&lt;/p&gt;&amp;mdash; ayuma (@ayuma_x) &lt;a href=&#34;https://twitter.com/ayuma_x/status/1023149422077562880?ref_src=twsrc%5Etfw&#34;&gt;July 28, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;


&lt;p&gt;What it does is simple: when you drag the mouse on the Client-side View, it sends the mouse coordinates to the Server side and displays them on the Server-side View.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="attended-qt-nagoya-study-group">Attended Qt Nagoya Study Group</h2>
<p>Although a week has passed, I attended the Qt study group in Nagoya last week.</p>
<p>Last time, I mainly focused on QML, so this time I decided to focus on C++.<br/>
I decided to implement a TCP/IP communication feature, which seems like it could be useful later on.</p>
<h2 id="software-created">Software Created</h2>
<p>The resulting software looks like this.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">先週のQt勉強会で作ったTCPIPのサンプル。マウスの軌跡を飛ばしてる。 <a href="https://t.co/jmbTxED2gd">pic.twitter.com/jmbTxED2gd</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1023149422077562880?ref_src=twsrc%5Etfw">July 28, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>What it does is simple: when you drag the mouse on the Client-side View, it sends the mouse coordinates to the Server side and displays them on the Server-side View.</p>
<p>The complete project is here:</p>
<div class="github-card" data-user="ayumax" data-repo="QtTcpIpSample" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<h2 id="code-snippets">Code Snippets</h2>
<p>There were several sample codes available on the web, so I was able to write it without much confusion.</p>
<p>The socket sending side looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> TCPClientModel<span style="color:#f92672">::</span>SendMessage(QString message)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (tcpClient <span style="color:#f92672">==</span> <span style="color:#66d9ef">nullptr</span>) <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    QByteArray messageBytes <span style="color:#f92672">=</span> message.toUtf8();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> messageSize <span style="color:#f92672">=</span> messageBytes.length();
</span></span><span style="display:flex;"><span>    QByteArray sizeBytes;
</span></span><span style="display:flex;"><span>    QDataStream <span style="color:#a6e22e">stream</span>(<span style="color:#f92672">&amp;</span>sizeBytes, QIODevice<span style="color:#f92672">::</span>WriteOnly);
</span></span><span style="display:flex;"><span>    stream <span style="color:#f92672">&lt;&lt;</span> messageSize;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    tcpClient<span style="color:#f92672">-&gt;</span>write(sizeBytes, sizeBytes.length());
</span></span><span style="display:flex;"><span>    tcpClient<span style="color:#f92672">-&gt;</span>write(messageBytes, messageBytes.length());
</span></span><span style="display:flex;"><span>    tcpClient<span style="color:#f92672">-&gt;</span>flush();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The TCP/IP data part is simply divided into two sections: a size area and a message area. The message follows for the number of bytes stored in the size section.<br/>
Writing this size into a byte array was surprisingly tricky. I eventually found QDataStream and decided to use it.</p>
<p>Also, to reduce communication latency, I flush after each send. I couldn&rsquo;t find how to set the NoDelay option with a quick search&hellip;<br/>
I&rsquo;ll look for it properly next time.</p>
<p>Next, the receiving part looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> TCPClientModel<span style="color:#f92672">::</span>OnReceived()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">while</span> (tcpClient<span style="color:#f92672">-&gt;</span>bytesAvailable() <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        tempBuffer.append(tcpClient<span style="color:#f92672">-&gt;</span>readAll());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">while</span> ((bodySize <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span> <span style="color:#f92672">&amp;&amp;</span> tempBuffer.size() <span style="color:#f92672">&gt;=</span> <span style="color:#ae81ff">4</span>)
</span></span><span style="display:flex;"><span>               <span style="color:#f92672">||</span> (bodySize <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0</span> <span style="color:#f92672">&amp;&amp;</span> tempBuffer.size() <span style="color:#f92672">&gt;=</span> bodySize))
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (bodySize <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span> <span style="color:#f92672">&amp;&amp;</span> tempBuffer.size() <span style="color:#f92672">&gt;=</span> <span style="color:#ae81ff">4</span>)
</span></span><span style="display:flex;"><span>            {
</span></span><span style="display:flex;"><span>                QByteArray numArray <span style="color:#f92672">=</span> tempBuffer.mid(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">4</span>);
</span></span><span style="display:flex;"><span>                QDataStream <span style="color:#a6e22e">stream</span>(<span style="color:#f92672">&amp;</span>numArray, QIODevice<span style="color:#f92672">::</span>ReadOnly);
</span></span><span style="display:flex;"><span>                stream <span style="color:#f92672">&gt;&gt;</span> bodySize;
</span></span><span style="display:flex;"><span>                tempBuffer.remove(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">4</span>);
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (bodySize <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0</span> <span style="color:#f92672">&amp;&amp;</span> tempBuffer.size() <span style="color:#f92672">&gt;=</span> bodySize)
</span></span><span style="display:flex;"><span>            {
</span></span><span style="display:flex;"><span>                QByteArray bodyArray <span style="color:#f92672">=</span> tempBuffer.mid(<span style="color:#ae81ff">0</span>, bodySize);
</span></span><span style="display:flex;"><span>                tempBuffer.remove(<span style="color:#ae81ff">0</span>, bodySize);
</span></span><span style="display:flex;"><span>                bodySize <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>               emit <span style="color:#a6e22e">dataReceived</span>(QString<span style="color:#f92672">::</span>fromUtf8(bodyArray));
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Receiving TCP/IP data is more troublesome than sending because sometimes the data might be incomplete, or the current data might be concatenated with the next data packet.</p>
<p>First, I wait until the buffer accumulates 4 bytes to know the size, then remember the message size, and wait until the buffer accumulates that many bytes to reconstruct the message.</p>
<p>However, with this implementation, I suspect that frequent use of QByteArray&rsquo;s <code>mid</code> and <code>remove</code> might cause many memory reallocations&hellip; If the message size increases or the sending interval shortens, more optimization might be necessary.</p>
<h2 id="summary">Summary</h2>
<p>I&rsquo;m satisfied that I was able to create software that integrates QML and C++ with more C++ code than last time.<br/>
Code of this level can be written entirely using Qt classes, so it should be multi-platform compatible.<br/>
I&rsquo;d like to create a few more samples like this and then connect them to a small application.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Attended a Qt Study Group</title>
      <link>https://ayumax.net/entry/2018/06/16/232917/</link>
      <pubDate>Sat, 16 Jun 2018 23:29:17 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/06/16/232917/</guid>
      <description>&lt;p&gt;Today, I participated in the Qt Nagoya study group.&lt;br/&gt;
It was my first time attending last time, so today was my second time.&lt;/p&gt;
&lt;p&gt;Last time, due to [first time attending] + [first time seeing Qt (excuse)] + [setup failures causing many errors], I mostly just panicked and it ended. So today, I decided what I wanted to achieve and participated.&lt;/p&gt;
&lt;p&gt;The result of the day is this.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;ja&#34; dir=&#34;ltr&#34;&gt;今日のQt勉強会で作ったソフト。&lt;br&gt;C++使った開発環境でこんなにスムーズに作れるとは感動した。Qt Quickすげー。 &lt;a href=&#34;https://t.co/UpbV1nQKXx&#34;&gt;pic.twitter.com/UpbV1nQKXx&lt;/a&gt;&lt;/p&gt;&amp;mdash; ayuma (@ayuma_x) &lt;a href=&#34;https://twitter.com/ayuma_x/status/1007984519561875456?ref_src=twsrc%5Etfw&#34;&gt;June 16, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;


&lt;p&gt;By the way, the image shown in the video is borrowed from &lt;a href=&#34;http://www.image-net.org/&#34;&gt;ImageNet&lt;/a&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Today, I participated in the Qt Nagoya study group.<br/>
It was my first time attending last time, so today was my second time.</p>
<p>Last time, due to [first time attending] + [first time seeing Qt (excuse)] + [setup failures causing many errors], I mostly just panicked and it ended. So today, I decided what I wanted to achieve and participated.</p>
<p>The result of the day is this.</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">今日のQt勉強会で作ったソフト。<br>C++使った開発環境でこんなにスムーズに作れるとは感動した。Qt Quickすげー。 <a href="https://t.co/UpbV1nQKXx">pic.twitter.com/UpbV1nQKXx</a></p>&mdash; ayuma (@ayuma_x) <a href="https://twitter.com/ayuma_x/status/1007984519561875456?ref_src=twsrc%5Etfw">June 16, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>By the way, the image shown in the video is borrowed from <a href="http://www.image-net.org/">ImageNet</a>.</p>
<p>I wanted to try implementing MVVM in Qt like in WPF,
so I tried creating a mechanism to bind list-formatted model data to the View.</p>
<p>On the C++ side, I gathered image files from an arbitrary directory, created a list-formatted property using QQmlListProperty, and bound it to the View.</p>
<p>For the View, I set the left side as a ListView and the right side as a GridView, and plugged the same QQmlListProperty mentioned above into the model for each.
I also deliberately synchronized the selection state of the ListView and GridView via a C++ property.<br/>
Putting aside the appearance, functionally, I think it turned out quite well for me.</p>
<p>Since I went through a lot of trial and error, the source code is too messy to publish, but I plan to rewrite it all and upload it to GitHub eventually.</p>
<p>Today was fun.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Created a Tool to Convert Markdown to PowerPoint Files</title>
      <link>https://ayumax.net/entry/2018/06/06/005349/</link>
      <pubDate>Wed, 06 Jun 2018 00:53:49 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/06/06/005349/</guid>
      <description>&lt;h1 id=&#34;mdtopptx&#34;&gt;MDToPPTX&lt;/h1&gt;
&lt;p&gt;The beta version of MDToPPTX, a tool I&amp;rsquo;ve been creating to convert Markdown files to PowerPoint files (*.pptx), is now ready.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s written in C#, and the library part is built with .NET Standard 2.0.&lt;br/&gt;
So, although I haven&amp;rsquo;t tested it, it should also work with .NET Core and Xamarin.&lt;/p&gt;
&lt;div class=&#34;github-card&#34; data-user=&#34;ayuma0913&#34; data-repo=&#34;MDToPPTX&#34; data-width=&#34;400&#34; data-height=&#34;&#34; data-theme=&#34;default&#34;&gt;&lt;/div&gt;
&lt;script src=&#34;https://cdn.jsdelivr.net/github-cards/latest/widget.js&#34;&gt;&lt;/script&gt;
&lt;p&gt;Using this, you can create PowerPoint files from Markdown.&lt;/p&gt;
&lt;h1 id=&#34;markdig&#34;&gt;markdig&lt;/h1&gt;
&lt;p&gt;For Markdown parsing, I used &lt;a href=&#34;https://github.com/lunet-io/markdig&#34;&gt;markdig&lt;/a&gt;.
Thanks to this, writing the code was very easy.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="mdtopptx">MDToPPTX</h1>
<p>The beta version of MDToPPTX, a tool I&rsquo;ve been creating to convert Markdown files to PowerPoint files (*.pptx), is now ready.</p>
<p>It&rsquo;s written in C#, and the library part is built with .NET Standard 2.0.<br/>
So, although I haven&rsquo;t tested it, it should also work with .NET Core and Xamarin.</p>
<div class="github-card" data-user="ayuma0913" data-repo="MDToPPTX" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<p>Using this, you can create PowerPoint files from Markdown.</p>
<h1 id="markdig">markdig</h1>
<p>For Markdown parsing, I used <a href="https://github.com/lunet-io/markdig">markdig</a>.
Thanks to this, writing the code was very easy.</p>
<h1 id="openxml">openxml</h1>
<p>PowerPoint file creation uses <a href="https://github.com/OfficeDev/Open-XML-SDK">openxml</a>.<br/>
This allows creating pptx files even on machines without PowerPoint installed.<br/>
However, even using the SDK, the difficulty level was high.</p>
<h1 id="executable-exe">Executable exe</h1>
<p>The MarkPP.exe file within the project on GitHub can be used with the following command:</p>
<pre tabindex="0"><code>MarkPP.exe &#34;markdownfile path&#34; &#34;title&#34; &#34;subtitle&#34;
</code></pre><p>The file will be output by converting the markdown file path (.md) to (.pptx).</p>
<p>The following is also described in the GitHub README:</p>
<h1 id="supported-syntax">Supported Syntax</h1>
<p>The following syntax is supported.<br/>
HTML notation within Markdown is not supported.</p>
<ul>
<li>HEADERS (Supports Level 1 or Level 2; Level 3 and beyond are probably unnecessary for PowerPoint)</li>
<li>BLOCKQUOTES</li>
<li>LISTS</li>
<li>CODE BLOCKS (Inline code is also OK)</li>
<li>LINKS</li>
<li>EMPHASIS (Bold, Italic, Strike)</li>
<li>Images (Placed at 1 pixel -> 1mm)</li>
<li>Table</li>
</ul>
<p>Use &mdash; to denote slide breaks.</p>
<h1 id="example-usage">Example Usage</h1>
<h2 id="input-markdown-example">Input Markdown Example</h2>
<ul>
<li>Since three backticks cannot be written inside a code block, they are replaced with ```</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span># Test Slide 1
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>This is a test slide.  
</span></span><span style="display:flex;"><span><span style="font-weight:bold">**Bold**</span> text.  
</span></span><span style="display:flex;"><span><span style="font-style:italic">*Italic*</span> is also supported.  
</span></span><span style="display:flex;"><span><span style="color:#f92672">~~Strikethrough is possible too~~</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#f92672">Hyperlink Example</span>](<span style="color:#a6e22e">http://ayumax.hatenablog.com/</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>↓ Code block
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>```csharp
</span></span><span style="display:flex;"><span>class ClassA  
</span></span><span style="display:flex;"><span>{  
</span></span><span style="display:flex;"><span>    public ClassA()  
</span></span><span style="display:flex;"><span>    { 
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    public void Func()
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}  
</span></span></code></pre></div><hr>
<h1 id="test-slide-2">Test Slide 2</h1>
<p>This is the second test slide.</p>
<p>Bullet points are also supported.</p>
<ul>
<li>This is a bullet point.</li>
<li>Inline code is also <code>supported</code>.</li>
</ul>
<p>Image insertion is also possible.
<img alt="image1" loading="lazy" src="ayumax.jpg"></p>
<p>Blockquote is here:</p>
<blockquote>
<p>Quote sample
text</p></blockquote>
<hr>
<h1 id="test-slide-3">Test Slide 3</h1>
<h2 id="subtitle">Subtitle</h2>
<p>This is the third test slide.</p>
<ol>
<li>Numbered list item</li>
<li>Second item in numbered list</li>
<li>Third item in numbered list</li>
</ol>
<p>Tables can also be written.</p>
<table>
  <thead>
      <tr>
          <th style="text-align: left">Left align</th>
          <th style="text-align: right">Right align</th>
          <th style="text-align: center">Center align</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: left">Row 1 Left</td>
          <td style="text-align: right">Row 1</td>
          <td style="text-align: center">Row 1 Right</td>
      </tr>
      <tr>
          <td style="text-align: left">Row 2 Left</td>
          <td style="text-align: right">Row 2</td>
          <td style="text-align: center">Row 2 Right</td>
      </tr>
      <tr>
          <td style="text-align: left">Row 3 Left</td>
          <td style="text-align: right">Row 3</td>
          <td style="text-align: center">Row 3 Right</td>
      </tr>
  </tbody>
</table>
<pre tabindex="0"><code>

## Output PPTX

It will be output like this.

<figure>
    <img loading="lazy" src="/images/2018/06/06/005349/20180606002603.jpg"/> 
</figure>
<figure>
    <img loading="lazy" src="/images/2018/06/06/005349/20180606002607.jpg"/> 
</figure>
<figure>
    <img loading="lazy" src="/images/2018/06/06/005349/20180606002609.jpg"/> 
</figure>


# Future Plans

Since the source is Markdown, the layout is only a straight vertical line, which feels a bit... hmm.&lt;br/&gt;
I&#39;m debating whether to utilize PowerPoint&#39;s slide layouts or extend the Markdown syntax to include position information, but I&#39;m hesitant to add strange original notation.

Also, for each Markdown block type, font size and area margins can be set from the code, so I need to externalize those settings in the future.

Furthermore, since this library is written in .NET Standard 2.0, I&#39;m thinking of writing a Xamarin app that directly takes Markdown input and outputs pptx.
If my motivation continues, I want to release it for both iOS and Android!
</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>PPTX Creation Feature: Image Insertion and Bullet Points</title>
      <link>https://ayumax.net/entry/2018/05/13/223819/</link>
      <pubDate>Sun, 13 May 2018 22:38:19 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/05/13/223819/</guid>
      <description>&lt;h1 id=&#34;issues-from-the-previous-version&#34;&gt;Issues from the Previous Version&lt;/h1&gt;
&lt;p&gt;In the previous article (&lt;a href=&#34;http://ayumax.hatenablog.com/entry/2018/05/06/231645&#34;&gt;&lt;a href=&#34;http://ayumax.hatenablog.com/entry/2018/05/06/231645&#34;&gt;http://ayumax.hatenablog.com/entry/2018/05/06/231645&lt;/a&gt;&lt;/a&gt;), there were the following issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cannot freely change the position of text&lt;/li&gt;
&lt;li&gt;No image insertion feature&lt;/li&gt;
&lt;li&gt;All text becomes bullet points&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, this time I addressed these issues.&lt;/p&gt;
&lt;div class=&#34;github-card&#34; data-user=&#34;ayuma0913&#34; data-repo=&#34;MDToPPTX&#34; data-width=&#34;400&#34; data-height=&#34;&#34; data-theme=&#34;default&#34;&gt;&lt;/div&gt;
&lt;script src=&#34;https://cdn.jsdelivr.net/github-cards/latest/widget.js&#34;&gt;&lt;/script&gt;
&lt;h2 id=&#34;text-position-setting&#34;&gt;Text Position Setting&lt;/h2&gt;
&lt;p&gt;Created a new PPTXTextArea class, allowing Position(x,y) and Size(width, height) to be set.
In the PowerPoint world, settings seem to be in cm, so I made it possible to input values in cm (internal conversion is performed).&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="issues-from-the-previous-version">Issues from the Previous Version</h1>
<p>In the previous article (<a href="http://ayumax.hatenablog.com/entry/2018/05/06/231645"><a href="http://ayumax.hatenablog.com/entry/2018/05/06/231645">http://ayumax.hatenablog.com/entry/2018/05/06/231645</a></a>), there were the following issues:</p>
<ul>
<li>Cannot freely change the position of text</li>
<li>No image insertion feature</li>
<li>All text becomes bullet points</li>
</ul>
<p>So, this time I addressed these issues.</p>
<div class="github-card" data-user="ayuma0913" data-repo="MDToPPTX" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<h2 id="text-position-setting">Text Position Setting</h2>
<p>Created a new PPTXTextArea class, allowing Position(x,y) and Size(width, height) to be set.
In the PowerPoint world, settings seem to be in cm, so I made it possible to input values in cm (internal conversion is performed).</p>
<h2 id="image-insertion">Image Insertion</h2>
<p>Again, created a new PPTXImage class to handle this.<br/>
Similar to PPTXTextArea, position can also be specified.<br/>
However, there&rsquo;s an issue: scaling while maintaining the original image&rsquo;s aspect ratio is not possible&hellip; To do this, you need to manually input Size values that maintain the aspect ratio, which is a bit inconvenient.</p>
<h2 id="text-bullet-point-setting">Text Bullet Point Setting</h2>
<p>Created a new PPTXBullet. An enum allows setting the bullet point style for text.</p>
<h1 id="result">Result</h1>
<h2 id="input-source">Input Source</h2>
<pre><code>        using (PPTXDocument document = new PPTXDocument(PPTXFilePath, settings))
        {
            document.Slides = new List<PPTXSlide>()
            {
                new PPTXSlide()
                {
                    SlideLayout = settings.SlideLayouts[EPPTXSlideLayoutType.TitleAndContents],
                    Title = new PPTXTextArea("Content Page 1"),
                    TextAreas = new List<PPTXTextArea>()
                    {
                        new PPTXTextArea("This is the body text.\n\\nAlso allows line breaks")
                    }
                },
                new PPTXSlide()
                {
                    SlideLayout = settings.SlideLayouts[EPPTXSlideLayoutType.TitleOnly],
                    Title = new PPTXTextArea("Content Page 2"),
                    TextAreas = new List<PPTXTextArea>()
                    {
                        new PPTXTextArea("Text 1 for the second PowerPoint slide", 1, 5, 20, 2),
                        new PPTXTextArea(1, 7, 20, 7)
                        {
                            Texts = new List<PPTXText>()
                            {
                                new PPTXText("Second slide, line 1", PPTXBullet.Circle),
                                new PPTXText("Second slide, line 2", PPTXBullet.Circle),
                                new PPTXText("Second slide, line 3", PPTXBullet.Rectangle),
                                new PPTXText("Second slide, line 4 - Bullet point removed")
                            }
                        }
                    },
                    Images = new List<PPTXImage>()
                    {
                        new PPTXImage(@"C:\temp\sample.jpg", 1, 15, 5, 3),
                        new PPTXImage(@"C:\temp\sample.jpg", 7, 15, 5, 3)
                    }
                }
            };
        }   
</code></pre>
<h2 id="output">Output</h2>
<figure>
    <img loading="lazy" src="/images/2018/05/13/223819/20180513221724.jpg"/> 
</figure>

<figure>
    <img loading="lazy" src="/images/2018/05/13/223819/20180513221738.jpg"/> 
</figure>

<figure>
    <img loading="lazy" src="/images/2018/05/13/223819/20180513222106.jpg"/> 
</figure>

<h1 id="next-steps">Next Steps</h1>
<p>This concludes the main part of the pptx creation feature for now.<br/>
I think having a font setting feature would be good too, but if I get too caught up in details, I won&rsquo;t make progress, so I&rsquo;ll stick to the bare minimum.<br/>
I plan to consider it again if I feel it&rsquo;s necessary later.</p>
<p>Next, I&rsquo;ll move on to Markdown parsing.</p>
]]></content:encoded>
    </item>
    <item>
      <title>PPTX Creation Feature - Tentative Version</title>
      <link>https://ayumax.net/entry/2018/05/06/231645/</link>
      <pubDate>Sun, 06 May 2018 23:16:45 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/05/06/231645/</guid>
      <description>&lt;h1 id=&#34;progress&#34;&gt;Progress&lt;/h1&gt;
&lt;p&gt;Regarding the development of the C# library that reads Markdown and creates PowerPoint files,&lt;br/&gt;
I&amp;rsquo;ve managed to implement the minimum required features for now.&lt;/p&gt;
&lt;div class=&#34;github-card&#34; data-user=&#34;ayuma0913&#34; data-repo=&#34;MDToPPTX&#34; data-width=&#34;400&#34; data-height=&#34;&#34; data-theme=&#34;default&#34;&gt;&lt;/div&gt;
&lt;script src=&#34;https://cdn.jsdelivr.net/github-cards/latest/widget.js&#34;&gt;&lt;/script&gt;
&lt;p&gt;The current features are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Slide size is fixed at 4x3 (I want to support 16:9 as well)&lt;/li&gt;
&lt;li&gt;The first slide is always a title page&lt;/li&gt;
&lt;li&gt;Slides from the second one onwards can be added freely&lt;/li&gt;
&lt;li&gt;It&#39;s possible to specify the slide layout for added slides&lt;/li&gt;
&lt;li&gt;Only text can be added to slides; images and shapes are not supported&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Writing code like the following creates a *.pptx file.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="progress">Progress</h1>
<p>Regarding the development of the C# library that reads Markdown and creates PowerPoint files,<br/>
I&rsquo;ve managed to implement the minimum required features for now.</p>
<div class="github-card" data-user="ayuma0913" data-repo="MDToPPTX" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<p>The current features are as follows:</p>
<ul>
<li>Slide size is fixed at 4x3 (I want to support 16:9 as well)</li>
<li>The first slide is always a title page</li>
<li>Slides from the second one onwards can be added freely</li>
<li>It's possible to specify the slide layout for added slides</li>
<li>Only text can be added to slides; images and shapes are not supported</li>
</ul>
<p>Writing code like the following creates a *.pptx file.</p>
<pre><code>    public void Run(string PPTXFilePath)
    {
        var settings = new PPTXSetting()
        {
            SlideSize = EPPTXSlideSizeValues.Screen4x3,
            Title = "Sample File Title",
            SubTitle = "2018/5/3 ayumax"
        };

        using (PPTXDocument document = new PPTXDocument(PPTXFilePath, settings))
        {
            document.Slides = new List<PPTXSlide>()
            {
                new PPTXSlide()
                {
                    SlideLayout = settings.SlideLayouts[EPPTXSlideLayoutType.TitleAndContents],
                    Title = new PPTXText("Content Page 1"),
                    Bodys = new List<PPTXText>()
                    {
                        new PPTXText("This is the body text.\nWrite here")
                    }
                },
                new PPTXSlide()
                {
                    SlideLayout = settings.SlideLayouts[EPPTXSlideLayoutType.TwoContents],
                    Title = new PPTXText("Content Page 2"),
                    Bodys = new List<PPTXText>()
                    {
                        new PPTXText("Text 1 for the second PowerPoint slide")
                        new PPTXText("Text 2\r\nSecond line")
                    }
                }
            };
        }               
    }   
</code></pre>
<figure>
    <img loading="lazy" src="/images/2018/05/06/231645/20180506230903.jpg"/> 
</figure>

<h1 id="current-issues">Current Issues</h1>
<p>It&rsquo;s still far from complete, but the issues I see right now are the following three:</p>
<ul>
<li>Cannot freely position text when the slide layout is set to blank</li>
<li>No feature to insert image files</li>
<li>The layout and theme are the PowerPoint defaults, which look uncool</li>
</ul>
<h1 id="next-steps">Next Steps</h1>
<p>For now, I want to prioritize building the whole thing,<br/>
so for the PowerPoint creation feature, I&rsquo;ll implement up to image insertion,<br/>
and then move on to the Markdown reading part.</p>
]]></content:encoded>
    </item>
    <item>
      <title>I Want to Create PowerPoint Files from Markdown</title>
      <link>https://ayumax.net/entry/2018/05/05/001506/</link>
      <pubDate>Sat, 05 May 2018 00:15:06 +0000</pubDate>
      <guid>https://ayumax.net/entry/2018/05/05/001506/</guid>
      <description>&lt;h1 id=&#34;i-want-to-create-pptx-files&#34;&gt;I Want to Create PPTX Files&lt;/h1&gt;
&lt;p&gt;Lately, I have too many things I want to do and I&amp;rsquo;m working on various projects in parallel.&lt;br/&gt;
Among them, for some reason, the desire to create PowerPoint documents from Markdown is strong,&lt;br/&gt;
and I&amp;rsquo;m putting the most effort into it.&lt;/p&gt;
&lt;h1 id=&#34;first-i-looked-for-existing-tools&#34;&gt;First, I Looked for Existing Tools&lt;/h1&gt;
&lt;p&gt;I haven&amp;rsquo;t searched for super niche tools, but
it feels like there isn&amp;rsquo;t anything I want to use right away.&lt;br/&gt;
There are many tools that can convert to PDF, but few for PowerPoint, right?&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="i-want-to-create-pptx-files">I Want to Create PPTX Files</h1>
<p>Lately, I have too many things I want to do and I&rsquo;m working on various projects in parallel.<br/>
Among them, for some reason, the desire to create PowerPoint documents from Markdown is strong,<br/>
and I&rsquo;m putting the most effort into it.</p>
<h1 id="first-i-looked-for-existing-tools">First, I Looked for Existing Tools</h1>
<p>I haven&rsquo;t searched for super niche tools, but
it feels like there isn&rsquo;t anything I want to use right away.<br/>
There are many tools that can convert to PDF, but few for PowerPoint, right?</p>
<p>Then I found this page.</p>
<p><a href="https://qiita.com/sky_y/items/f38db5dd69720e5ca0cf"><a href="https://qiita.com/sky_y/items/f38db5dd69720e5ca0cf">https://qiita.com/sky_y/items/f38db5dd69720e5ca0cf</a></a><cite class="hatena-citation"><a href="https://qiita.com/sky_y/items/f38db5dd69720e5ca0cf">qiita.com</a></cite></p>
<p>Apparently, using something called Pandoc can already do what I want.
However, it seems like it doesn&rsquo;t quite scratch the itch for PowerPoint features right now.</p>
<h1 id="so-should-i-make-it-myself">So, Should I Make It Myself?</h1>
<p>For now, I want to build it in an environment I&rsquo;m comfortable with, so I&rsquo;ll use Visual Studio + C#.
I plan to write the library in .NET Standard so it can be reused later.</p>
<p>The main features I probably need to create are the following two.</p>
<h2 id="markdown-parsing">Markdown Parsing</h2>
<p>I searched for several tools for this too, but many of them convert to HTML.
You can understand why based on how they are used.
So, I haven&rsquo;t started on this yet, but I&rsquo;m thinking of either tackling it with regular expressions,<br/>
or trying out a text parser library called &ldquo;Sprache&rdquo; that I learned about in a previous job
to see if it&rsquo;s possible.</p>
<h2 id="creating-pptx-files">Creating pptx Files</h2>
<p>For this, in my usual work, I frequently use a library called ClosedXML, which wraps OpenXML for Excel&rsquo;s xlsx files.<br/>
So I looked for a similar sibling library for PowerPoint, but couldn&rsquo;t find one.
Therefore, I&rsquo;ll use only the OpenXML library and build the rest myself.<br/>
This part is progressing reasonably well, and I&rsquo;ve already succeeded in writing out sample files!
The implementation is still not refined, so I&rsquo;m proceeding while refactoring.
However, since it&rsquo;s only intended for outputting from Markdown, I&rsquo;m not planning to wrap the full functionality.</p>
<p>This is a very HOT development project for me personally,<br/>
so I want to push it forward until it takes some shape.</p>
<p>And if it goes well, I want to use Xamarin to turn it into iOS and Android apps.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Starting My Blog</title>
      <link>https://ayumax.net/entry/2017/12/28/235922/</link>
      <pubDate>Thu, 28 Dec 2017 23:59:22 +0000</pubDate>
      <guid>https://ayumax.net/entry/2017/12/28/235922/</guid>
      <description>&lt;h1 id=&#34;why-i-started-this-blog&#34;&gt;Why I Started This Blog&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ve been working as a programmer for quite a while now, but looking back, I haven&amp;rsquo;t really shared much information with the outside world.
In 2018, I want to start sharing more by posting on my blog and Qiita. I&amp;rsquo;d also like to participate in study groups and meetups.&lt;/p&gt;
&lt;h1 id=&#34;motivation&#34;&gt;Motivation&lt;/h1&gt;
&lt;p&gt;Recently, I&amp;rsquo;ve realized that I&amp;rsquo;ve spent most of my time in a closed environment, rarely interacting with other engineers. I now feel that it&amp;rsquo;s important to connect with people outside my usual circles.
Doing the same kind of work for a long time has made me feel a bit stagnant.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="why-i-started-this-blog">Why I Started This Blog</h1>
<p>I&rsquo;ve been working as a programmer for quite a while now, but looking back, I haven&rsquo;t really shared much information with the outside world.
In 2018, I want to start sharing more by posting on my blog and Qiita. I&rsquo;d also like to participate in study groups and meetups.</p>
<h1 id="motivation">Motivation</h1>
<p>Recently, I&rsquo;ve realized that I&rsquo;ve spent most of my time in a closed environment, rarely interacting with other engineers. I now feel that it&rsquo;s important to connect with people outside my usual circles.
Doing the same kind of work for a long time has made me feel a bit stagnant.</p>
<p>I want to learn things I don&rsquo;t know by being exposed to the knowledge of others, and I want to be inspired by new ideas.</p>
<h1 id="what-ill-write-about">What I&rsquo;ll Write About</h1>
<p>I&rsquo;ll use this blog mainly for my personal thoughts and ideas.
For technical topics, I&rsquo;ll post on Qiita.
Since writing about my work could violate confidentiality, I&rsquo;ll focus on things I do outside of work.</p>
<p><em>It took me about four months from deciding to start writing to actually publishing this blog. From now on, I&rsquo;ll try to post more regularly!</em></p>
]]></content:encoded>
    </item>
    <item>
      <title>Alexa Custom Skill 2 with Visual Studio &#43; C#: Conversation with Session</title>
      <link>https://ayumax.net/entry/2017/12/28/010000/</link>
      <pubDate>Thu, 28 Dec 2017 01:00:00 +0000</pubDate>
      <guid>https://ayumax.net/entry/2017/12/28/010000/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;This article is a continuation of &lt;a href=&#34;https://www.ayumax.net/entry/2017/12/24/003000&#34;&gt;Alexa Custom Skill 1 with Visual Studio + C#: Greeting on Twitter&lt;/a&gt;.
The content of the previous article serves as the foundation here.&lt;/p&gt;
&lt;p&gt;For writing Lambda functions, I chose C#, which is a minor language for this purpose (at least in my opinion), to create a custom skill.&lt;/p&gt;
&lt;h1 id=&#34;overview&#34;&gt;Overview&lt;/h1&gt;
&lt;p&gt;In the previous implementation, the process was completed with a single round of conversation like this:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="introduction">Introduction</h1>
<p>This article is a continuation of <a href="https://www.ayumax.net/entry/2017/12/24/003000">Alexa Custom Skill 1 with Visual Studio + C#: Greeting on Twitter</a>.
The content of the previous article serves as the foundation here.</p>
<p>For writing Lambda functions, I chose C#, which is a minor language for this purpose (at least in my opinion), to create a custom skill.</p>
<h1 id="overview">Overview</h1>
<p>In the previous implementation, the process was completed with a single round of conversation like this:</p>
<p><a href="http://www.plantuml.com/plantuml/uml/JOun2i9044NxESLSm0kaa7YK9QO8n1YI3LWwisbjBBGK94GBmK9C9NeN_qNSDON2PvZFF1uJrzPKjbdaP1Axh1YkXtj01p_PrDpKQKMbHx8aAqrXUPQdAnCk9Yn40U39TAmSCVG8Tu5UeNUi1Qw5Td0E-WfYERrtjp7GBQI33D0MujFJAF6shpNY7oldFtO3UKBsa0DHd1Pp__u7"><img src="http://www.plantuml.com/plantuml/svg/JOun2i9044NxESLSm0kaa7YK9QO8n1YI3LWwisbjBBGK94GBmK9C9NeN_qNSDON2PvZFF1uJrzPKjbdaP1Axh1YkXtj01p_PrDpKQKMbHx8aAqrXUPQdAnCk9Yn40U39TAmSCVG8Tu5UeNUi1Qw5Td0E-WfYERrtjp7GBQI33D0MujFJAF6shpNY7oldFtO3UKBsa0DHd1Pp__u7" alt=""/></a></p>
<p>This time, I improved it a bit so that the conversation continues as follows, and the process branches depending on the user&rsquo;s response:
<a href="http://www.plantuml.com/plantuml/uml/ZP0nQa9148RxESLS81Um47E1z2aNtK9uwkFj2YcTNOj0i3LO2SdZcKAm4AqatiN_05x1sRTDI2m2FpyxpB_V3DDptbH-EYh8zFsaOiG6yOHmL6VZUEfiHQL6XlrXQSQU7mlxObB7f0TH2l13DvVSOOGFn2t23k60cI3E4Mh4Y71EODbSbliio2UaWTIG8y8SeceeSnJOWZly8_xrAzkwQWDPGTwkfpNfTy_FrX7pdyLafsbj_7F20l8DUOUioHREyjFaBZIly7g7cmUc6oWkI8jRaHqFY7hgUlCR"><img src="http://www.plantuml.com/plantuml/svg/ZP0nQa9148RxESLS81Um47E1z2aNtK9uwkFj2YcTNOj0i3LO2SdZcKAm4AqatiN_05x1sRTDI2m2FpyxpB_V3DDptbH-EYh8zFsaOiG6yOHmL6VZUEfiHQL6XlrXQSQU7mlxObB7f0TH2l13DvVSOOGFn2t23k60cI3E4Mh4Y71EODbSbliio2UaWTIG8y8SeceeSnJOWZly8_xrAzkwQWDPGTwkfpNfTy_FrX7pdyLafsbj_7F20l8DUOUioHREyjFaBZIly7g7cmUc6oWkI8jRaHqFY7hgUlCR" alt=""/></a></p>
<h1 id="implementation">Implementation</h1>
<p>For this implementation, I changed almost only the Lambda function from the previous version.
(The conversation model was also slightly modified.)
To continue the conversation with Alexa, you need to use sessions, so I implemented that part. For details on session management, I referred to <a href="https://developer.amazon.com/ja/blogs/alexa/post/cddf2434-42ee-422f-886d-5be9c36dba14/jp-training-chapter3">Alexa Skill Development Training Series Chapter 3: Designing Voice User Interfaces</a>.
This time, I created the C# code based on the Node.js sample here.</p>
<p>The Lambda project is available here.</p>
<div class="github-card" data-user="ayumax" data-repo="AlexaToTwitter" data-width="400" data-height="" data-theme="default"></div>
<script src="https://cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
<h2 id="conversation-model">Conversation Model</h2>
<p>I only changed the intent schema a little.
*Added AMAZON.NoIntent and AMAZON.YesIntent to accept Yes and No responses.</p>
<p>Custom slot types and sample utterances are the same as in the <a href="https://qiita.com/ayuma0913/items/d02d6ddf03761bffe20a">previous article</a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;intents&#34;</span>: [
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;slots&#34;</span>: [
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;Word&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">&#34;type&#34;</span>: <span style="color:#e6db74">&#34;GREETING_WORD&#34;</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>      ],
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;intent&#34;</span>: <span style="color:#e6db74">&#34;TwitterIntent&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;intent&#34;</span>: <span style="color:#e6db74">&#34;AMAZON.NoIntent&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;intent&#34;</span>: <span style="color:#e6db74">&#34;AMAZON.YesIntent&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;intent&#34;</span>: <span style="color:#e6db74">&#34;AMAZON.HelpIntent&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;intent&#34;</span>: <span style="color:#e6db74">&#34;AMAZON.StopIntent&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="lambda">lambda</h2>
<p>As before, I coded in an environment with <a href="https://aws.amazon.com/visualstudio/">AWS Toolkit for Visual Studio</a> installed.</p>
<p>I added the following two libraries via NuGet:</p>
<ul>
<li>Alexa.Net</li>
<li>CoreTweet</li>
</ul>
<h3 id="initialization">Initialization</h3>
<p>As before, Twitter access information is obtained from environment variables.
This time, I also implemented state management, with a different function called for each state.</p>
<p>Although you could branch with if statements, I cached delegates in anticipation of the number of states increasing in the future.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span> <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> <span style="color:#66d9ef">string</span> APIKey;
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> <span style="color:#66d9ef">string</span> APISecret;
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> <span style="color:#66d9ef">string</span> AccessToken;
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> <span style="color:#66d9ef">string</span> AccessTokenSecret;
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">readonly</span> Dictionary&lt;<span style="color:#66d9ef">string</span>, Func&lt;IntentRequest, Session, SkillResponse&gt;&gt; stateHandlers;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span> Function()
</span></span><span style="display:flex;"><span> {
</span></span><span style="display:flex;"><span>     APIKey = Environment.GetEnvironmentVariable(<span style="color:#e6db74">&#34;API_KEY&#34;</span>);
</span></span><span style="display:flex;"><span>     APISecret = Environment.GetEnvironmentVariable(<span style="color:#e6db74">&#34;API_KEY_SECRET&#34;</span>);
</span></span><span style="display:flex;"><span>     AccessToken = Environment.GetEnvironmentVariable(<span style="color:#e6db74">&#34;ACCESS_TOKEN&#34;</span>);
</span></span><span style="display:flex;"><span>     AccessTokenSecret = Environment.GetEnvironmentVariable(<span style="color:#e6db74">&#34;ACCESS_TOKEN_SECRET&#34;</span>);
</span></span><span style="display:flex;"><span>     stateHandlers = <span style="color:#66d9ef">new</span> Dictionary&lt;<span style="color:#66d9ef">string</span>, Func&lt;IntentRequest, Session, SkillResponse&gt;&gt;
</span></span><span style="display:flex;"><span>     {
</span></span><span style="display:flex;"><span>         { EConversationState.StartState.ToString(), FunctionHandler_StartState },
</span></span><span style="display:flex;"><span>         { EConversationState.ConfirmState.ToString(), FunctionHandler_ConfirmState }
</span></span><span style="display:flex;"><span>     };
</span></span><span style="display:flex;"><span> }
</span></span></code></pre></div><p>This mechanism changes the function called for each state, and the state is stored in the session attributes.
(See <code>input.Session.Attributes[&ldquo;STATE&rdquo;]</code> in the code below.)</p>
<p>In this function, the state is read from the session attributes, and the cached delegate is retrieved to handle processing for each state.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span> <span style="color:#66d9ef">public</span> SkillResponse FunctionHandler(SkillRequest input, ILambdaContext context)
</span></span><span style="display:flex;"><span> {
</span></span><span style="display:flex;"><span>     <span style="color:#66d9ef">var</span> requestType = input.GetRequestType();
</span></span><span style="display:flex;"><span>     <span style="color:#66d9ef">if</span> (requestType != <span style="color:#66d9ef">typeof</span>(IntentRequest)) <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">null</span>;
</span></span><span style="display:flex;"><span>     <span style="color:#66d9ef">var</span> intentRequest = input.Request <span style="color:#66d9ef">as</span> IntentRequest;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>     <span style="color:#66d9ef">var</span> state = input.Session.Attributes.ContainsKey(<span style="color:#e6db74">&#34;STATE&#34;</span>) ? input.Session.Attributes[<span style="color:#e6db74">&#34;STATE&#34;</span>] <span style="color:#66d9ef">as</span> <span style="color:#66d9ef">string</span> : EConversationState.StartState.ToString();
</span></span><span style="display:flex;"><span>     <span style="color:#66d9ef">var</span> handler = stateHandlers[state];
</span></span><span style="display:flex;"><span>     <span style="color:#66d9ef">return</span> handler(intentRequest, input.Session);
</span></span><span style="display:flex;"><span> }
</span></span></code></pre></div><h3 id="functionhandler_startstate">FunctionHandler_StartState</h3>
<p>StartState processing.
The user is expected to say &ldquo;Tweet △△△&rdquo;, so I first get △△△.
The obtained content needs to be remembered, so it is registered in the session attributes with the key &ldquo;Word&rdquo;.
Next, Alexa responds, but here I use Ask instead of Tell.
Using Ask keeps the session open, and Alexa immediately waits for the next utterance.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">private</span> SkillResponse FunctionHandler_StartState(IntentRequest intentRequest, Session Session)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Ignore intents other than TwitterIntent</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (intentRequest.Intent.Name.Equals(<span style="color:#e6db74">&#34;TwitterIntent&#34;</span>) == <span style="color:#66d9ef">false</span>) <span style="color:#66d9ef">return</span> ResponseBuilder.Tell(<span style="color:#e6db74">&#34;Unexpected request. Cancelling.&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Get the value of the Word slot</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> wordSlotValue = intentRequest.Intent.Slots[<span style="color:#e6db74">&#34;Word&#34;</span>].Value;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Response from Alexa</span>
</span></span><span style="display:flex;"><span>    Reprompt rep = <span style="color:#66d9ef">new</span> Reprompt();
</span></span><span style="display:flex;"><span>    rep.OutputSpeech = <span style="color:#66d9ef">new</span> PlainTextOutputSpeech() { Text = <span style="color:#e6db74">&#34;Is it okay to tweet this?&#34;</span> };
</span></span><span style="display:flex;"><span>    Session.Attributes = <span style="color:#66d9ef">new</span> Dictionary&lt;<span style="color:#66d9ef">string</span>, <span style="color:#66d9ef">object</span>&gt;();
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Remember the phrase to tweet</span>
</span></span><span style="display:flex;"><span>    Session.Attributes[<span style="color:#e6db74">&#34;Word&#34;</span>] = wordSlotValue;
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Change state to ConfirmState</span>
</span></span><span style="display:flex;"><span>    Session.Attributes[<span style="color:#e6db74">&#34;STATE&#34;</span>] = EConversationState.ConfirmState.ToString();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> ResponseBuilder.Ask(<span style="color:#e6db74">$&#34;Is it okay to tweet &#39;{wordSlotValue}&#39;?&#34;</span>, rep, Session);
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="functionhandler_confirmstate">FunctionHandler_ConfirmState</h3>
<p>This function handles the ConfirmState.
It expects the user to answer either &ldquo;Yes&rdquo; or &ldquo;No&rdquo;, and changes the behavior depending on the response.</p>
<p>Note: The built-in intents for &ldquo;Yes&rdquo; and &ldquo;No&rdquo; are used here. As expected, built-in intents have better recognition accuracy than custom ones.</p>
<h4 id="if-yes">If &ldquo;Yes&rdquo;</h4>
<p>Retrieve the remembered phrase from session attributes and post it to Twitter.</p>
<h4 id="if-no">If &ldquo;No&rdquo;</h4>
<p>Cancel the post.</p>
<p>Regardless of the answer, the session should end after this, so Alexa responds with Tell. To use the function again, start from the beginning.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-csharp" data-lang="csharp"><span style="display:flex;"><span><span style="color:#66d9ef">private</span> SkillResponse FunctionHandler_ConfirmState(IntentRequest intentRequest, Session Session)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// If NO is returned, cancel the process</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (intentRequest.Intent.Name.Equals(<span style="color:#e6db74">&#34;AMAZON.NoIntent&#34;</span>))
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> ResponseBuilder.Tell(<span style="color:#e6db74">&#34;Okay, I won&#39;t post it.&#34;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// If it is not YES, treat as unexpected and cancel</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (intentRequest.Intent.Name.Equals(<span style="color:#e6db74">&#34;AMAZON.YesIntent&#34;</span>) == <span style="color:#66d9ef">false</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> ResponseBuilder.Tell(<span style="color:#e6db74">&#34;Unexpected response. Cancelling.&#34;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Retrieve the remembered phrase from session attributes</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> wordSlotValue = Session.Attributes[<span style="color:#e6db74">&#34;Word&#34;</span>] <span style="color:#66d9ef">as</span> <span style="color:#66d9ef">string</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Generate required information for Twitter API</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> tokens = CoreTweet.Tokens.Create(<span style="color:#e6db74">$&#34;{APIKey}&#34;</span>, <span style="color:#e6db74">$&#34;{APISecret}&#34;</span>, <span style="color:#e6db74">$&#34;{AccessToken}&#34;</span>, <span style="color:#e6db74">$&#34;{AccessTokenSecret}&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Post to Twitter</span>
</span></span><span style="display:flex;"><span>    tokens.Statuses.UpdateAsync(<span style="color:#66d9ef">new</span> { status = wordSlotValue }).Wait();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Report the result</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> ResponseBuilder.Tell(<span style="color:#e6db74">$&#34;I posted &#39;{wordSlotValue}&#39; on Twitter.&#34;</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h1 id="testing-on-real-device">Testing on Real Device</h1>
<p>It didn&rsquo;t work perfectly at first, and I had to make several adjustments, but in the end, it worked as intended.
If you let Alexa handle everything in a single round, misrecognition can be a problem, but by adding a user confirmation step, accuracy improved.
However, if you always require confirmation, it can reduce usability, so in actual skill development, you should design according to the use case.</p>
<h1 id="summary">Summary</h1>
<p>By using sessions in a skill created with C# in Visual Studio, I was able to have a back-and-forth conversation with Alexa.
This greatly expands the range of possible features.</p>
<p>This time, there were only two states, so it wasn&rsquo;t a problem, but as the number of states increases or you need to handle nested states, you may need to be more creative with the code structure.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Alexa Custom Skill 1 with Visual Studio &#43; C#: Greeting on Twitter</title>
      <link>https://ayumax.net/entry/2017/12/24/003000/</link>
      <pubDate>Wed, 27 Dec 2017 00:30:00 +0000</pubDate>
      <guid>https://ayumax.net/entry/2017/12/24/003000/</guid>
      <description>&lt;h1 id=&#34;what-i-did&#34;&gt;What I Did&lt;/h1&gt;
&lt;p&gt;After waiting for over a month, I finally received my Amazon Echo and tried greeting on Twitter using it.&lt;/p&gt;
&lt;p&gt;Although it might be possible to do this without creating a skill by using IFTTT, my goal was to actually build a custom skill, so I decided to implement it from scratch.&lt;/p&gt;
&lt;p&gt;Most tutorials and samples use Node.js for Lambda methods, but since I love C#, I wrote it in C#.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="what-i-did">What I Did</h1>
<p>After waiting for over a month, I finally received my Amazon Echo and tried greeting on Twitter using it.</p>
<p>Although it might be possible to do this without creating a skill by using IFTTT, my goal was to actually build a custom skill, so I decided to implement it from scratch.</p>
<p>Most tutorials and samples use Node.js for Lambda methods, but since I love C#, I wrote it in C#.</p>
<h1 id="environment">Environment</h1>
<p>Here are the required environments for implementation:
Since C# uses .NET Core 1.0, I think development is possible even on Mac.
I used Visual Studio 2017 (Windows version), but it seems AWS Toolkit supports versions earlier than 2017 as well.</p>
<ul>
<li>Windows 10</li>
<li><a href="https://developer.amazon.com/">Amazon Developer</a> account</li>
<li><a href="https://aws.amazon.com/">AWS</a> account</li>
<li><a href="https://www.visualstudio.com/downloads/">Visual Studio 2017</a></li>
<li><a href="https://aws.amazon.com/visualstudio/">AWS Toolkit for Visual Studio</a></li>
<li>Amazon Echo</li>
<li>Twitter API</li>
</ul>
<h1 id="implementation-of-alexa-skill">Implementation of Alexa Skill</h1>
<p>I followed this <a href="https://developer.amazon.com/ja/alexa-skills-kit/training/building-a-skill">tutorial</a> almost exactly.
(By the way, this tutorial was in Japanese and very easy to understand.)</p>
<p>You need to register for an <a href="https://developer.amazon.com/">Amazon Developer</a> account beforehand.</p>
<p>This time, I did not use the Skill Builder.</p>
<h2 id="skill-name--invocation-name">Skill Name &amp; Invocation Name</h2>
<p>Both are set to &ldquo;Twitter&rdquo; (pronounced as &ldquo;Tsuittā&rdquo;).</p>
<h2 id="intent-schema">Intent Schema</h2>
<p>I defined an intent called TwitterIntent, with a slot named Word of type GREETING_WORD.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;intents&#34;</span>: [
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;slots&#34;</span>: [
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;Word&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">&#34;type&#34;</span>: <span style="color:#e6db74">&#34;GREETING_WORD&#34;</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>      ],
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;intent&#34;</span>: <span style="color:#e6db74">&#34;TwitterIntent&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;intent&#34;</span>: <span style="color:#e6db74">&#34;AMAZON.HelpIntent&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;intent&#34;</span>: <span style="color:#e6db74">&#34;AMAZON.StopIntent&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="custom-slot-type">Custom Slot Type</h2>
<p>The slot will contain greeting words.
It seemed that there was no suitable default slot type, so I created a custom slot.</p>
<p>Type: GREETING_WORD</p>
<p>Values:
Good morning
Hello
Good night
Good evening
Hey
Hey (casual)
Hi</p>
<h2 id="sample-utterances">Sample Utterances</h2>
<p>Ideally, you would register more patterns, but for now, I registered the following five:</p>
<p>TwitterIntent {Word} o-tsubuyai-te (say on Twitter)
TwitterIntent {Word} tte tsubuyai-te (say on Twitter)
TwitterIntent {Word} tte yatte (do it)
TwitterIntent {Word} te itte (say it)
TwitterIntent {Word} shite (do it)</p>
<h1 id="lambda-function-implementation-c">Lambda Function Implementation (C#)</h1>
<p>Register your AWS account in advance so you can use Lambda functions.</p>
<h2 id="installing-aws-toolkit-for-visual-studio">Installing AWS Toolkit for Visual Studio</h2>
<p>Download and install it from the AWS website.
With this, you can implement, publish, and test your function all within Visual Studio, making things much easier.</p>
<p>After installation, when you launch Visual Studio, a window will appear prompting you to enter your AWS user information. Enter it as needed.</p>
<h2 id="creating-a-project-for-lambda">Creating a Project for Lambda</h2>
<p>When creating the project, select &ldquo;AWS Lambda Project (.NET Core)&rdquo;.
For the function type, I chose Empty Function.
<img width="628" alt="2_projecttemplate.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/119290/ebf62214-666d-72bb-2eef-50ae7d4edeaf.png"/></p>
<h2 id="adding-libraries">Adding Libraries</h2>
<p>I added the following two libraries:</p>
<ul>
<li>Alexa.Net</li>
<li>CoreTweet</li>
</ul>
<h2 id="function-implementation">Function Implementation</h2>
<p>I opened Function.cs and implemented it as follows.</p>
<h3 id="twitterapi-information">TwitterAPI Information</h3>
<p>I was going to hard code it for confirmation, but I thought I could use the environment variable function of Lambda, so I used it.
*Note: I was not very familiar with Lambda, so if you find anything wrong, please let me know.</p>
<pre tabindex="0"><code>   private string APIKey;
   private string APISecret;
   private string AccessToken;
   private string AccessTokenSecret;
        
   public Function()
   {
       APIKey = Environment.GetEnvironmentVariable(&#34;API_KEY&#34;);
       APISecret = Environment.GetEnvironmentVariable(&#34;API_KEY_SECRET&#34;);
       AccessToken = Environment.GetEnvironmentVariable(&#34;ACCESS_TOKEN&#34;);
       AccessTokenSecret = Environment.GetEnvironmentVariable(&#34;ACCESS_TOKEN_SECRET&#34;);
   }
</code></pre><h3 id="request-sorting">Request Sorting</h3>
<p>I implemented it to ignore all requests other than TwitterIntent.</p>
<pre tabindex="0"><code>   // Get request type
   var requestType = input.GetRequestType();

   // Ignore requests other than IntentRequest
   if (requestType != typeof(IntentRequest)) return null;

   var intentRequest = input.Request as IntentRequest;

   // Ignore intents other than TwitterIntent
   if (!intentRequest.Intent.Name.Equals(&#34;TwitterIntent&#34;)) return null;
</code></pre><h3 id="response-implementation">Response Implementation</h3>
<p>I extracted the greeting words from the request and tweeted them to Twitter, then told Alexa that I had tweeted them.</p>
<pre tabindex="0"><code>   // Get the value of the Word slot
    var wordSlotValue = intentRequest.Intent.Slots[&#34;Word&#34;].Value;

   // Generate necessary information for Twitter API
   var tokens = CoreTweet.Tokens.Create($&#34;{APIKey}&#34;, $&#34;{APISecret}&#34;, $&#34;{AccessToken}&#34;, $&#34;{AccessTokenSecret}&#34;);

   // Execute tweet
   tokens.Statuses.UpdateAsync(new { status = wordSlotValue }).Wait();

   // Response from Alexa
   return ResponseBuilder.Tell($&#34;&lt;speak&gt;I tweeted {wordSlotValue}&lt;/speak&gt;&#34;);
```;
```


### Function.cs

```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

using Amazon.Lambda.Core;
using Alexa.NET;
using Alexa.NET.Request;
using Alexa.NET.Response;
using Alexa.NET.Request.Type;

// Assembly attribute to enable the Lambda function&amp;#39;s JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]

namespace AlexaToTwitter
{
    public class Function
    {
        private readonly string APIKey;
        private readonly string APISecret;
        private readonly string AccessToken;
        private readonly string AccessTokenSecret;

        public Function()
        {
            APIKey = Environment.GetEnvironmentVariable(&#34;API_KEY&#34;);
            APISecret = Environment.GetEnvironmentVariable(&#34;API_KEY_SECRET&#34;);
            AccessToken = Environment.GetEnvironmentVariable(&#34;ACCESS_TOKEN&#34;);
            AccessTokenSecret = Environment.GetEnvironmentVariable(&#34;ACCESS_TOKEN_SECRET&#34;);
        }

        public SkillResponse FunctionHandler(SkillRequest input, ILambdaContext context)
        {
            // Get request type
            var requestType = input.GetRequestType();

            // Ignore requests other than IntentRequest
            if (requestType != typeof(IntentRequest)) return null;

            var intentRequest = input.Request as IntentRequest;

            // Ignore intents other than TwitterIntent
            if (!intentRequest.Intent.Name.Equals(&#34;TwitterIntent&#34;)) return null;

            // Get the value of the Word slot
            var wordSlotValue = intentRequest.Intent.Slots[&#34;Word&#34;].Value;

            // Generate necessary information for Twitter API
            var tokens = CoreTweet.Tokens.Create($&#34;{APIKey}&#34;, $&#34;{APISecret}&#34;, $&#34;{AccessToken}&#34;, $&#34;{AccessTokenSecret}&#34;);

            // Execute tweet
            tokens.Statuses.UpdateAsync(new { status = wordSlotValue }).Wait();

            // Response from Alexa
            return ResponseBuilder.Tell($&#34;I tweeted {wordSlotValue}&#34;);
        }
    }
}

```


### Update Lambda

Right-click on the project and click &#34;Publish to AWS Lambda...&#34;.

Select the Function Name and Role, and upload.
You can also set environment variable values and test the function after publishing.

If there are no problems, add &#34;Alexa Skills Kit&#34; as a trigger from the AWS Web.
(Since I couldn&#39;t add the trigger directly from Visual Studio, I did it via the AWS Web console, which I thought might be more interesting anyway.)
&lt;img width=&#34;1009&#34; alt=&#34;3_skillkit.PNG&#34; src=&#34;https://qiita-image-store.s3.amazonaws.com/0/119290/d34522b9-9136-d6b1-8cf2-1ae826f8a348.png&#34;/&gt;

# Testing on Real Device

After connecting the Lambda function in the Alexa skill settings on Amazon Developer, fill in the required details and enable the skill for your own Amazon account using Skills Beta Testing.

Then, nervously, I said to Echo:
&#34;Alexa, tweet &#39;Good morning&#39; on Twitter.&#34;
And it was properly reflected on Twitter.

Even if you change the &#34;Good morning&#34; part to other words, it recognizes them most of the time.
It could even recognize words not defined in the list.

# Summary

I wanted to make some kind of skill using Amazon Echo, so I tried implementing it with C#, which I&#39;m familiar with.

Thanks to AWS Toolkit for Visual Studio and Alexa.Net, I could code without worrying much about Lambda or Alexa itself, so it was less difficult than I expected.

Alexa&#39;s recognition rate is also pretty good. I once tried automating daily life with Amazon Dash Button, but with Alexa, I feel like I can do even more depending on the ideas I come up with.
</code></pre>]]></content:encoded>
    </item>
  </channel>
</rss>
