❀ DoN's Dynamic Mesh Effects ❀

Is there a way to setup the render targets on specified layers on an Actor without first using one of the paint methods? I have code that exports all the render targets as PNGs and now I want to load them back in. The render targets on an Actor are only created when that specific layer is painted to but I need those render targets created without first painting to them so I can load my exported PNGs back into them.

It looks like I might be able to do this by manually calling UDonMeshPainterComponent::SetupPaintingPrerequisites() on each layer, but I would have to create a dummy FDonPaintStroke for each one. I don’t know if trying to do that would break anything else.

Any suggestions on how to do this?

@**DanimalsOnParade **- To clarify: You’re not using the in-built save system to export these because you want to edit the images in an external application or something like that?

If so, I was going to suggest using the LoadMeshPaintFromBytes function by.preparing a FDonMeshPaintSaveData structure, but you’ll need to understand the internals of that structure well for that. The brute-force option is to call SetupPaintingPrerequisites like you mentioned.

You’ll need to use dummy strokes with either approach (should be safe), but the first option will also take care of loading your PNGs onto the correct render targets for you, Maybe try the manual approach first and if you run into issues dive into Load function…

From my testing, the built-in save system of saving the strokes has an unbounded size to it. If the user is painting and just clicks in the same spot 20 times, each click adds more strokes (bytes) to the list even though the end result, the render target, doesn’t change at all. This doesn’t work for me where I’m uploading character customizations to a server. The users can and will be painting over the same locations as many times as they want. Saving the render targets as PNGs gives me a bounded file size and in some cases smaller file sizes than the in-built system of saving the strokes. The PNGs only store what’s on the render targets, regardless of how many strokes the user made. The downside to the PNG approach is that if you add the undo system, I wouldn’t be able to undo any strokes after loading from a PNG, but that is an acceptable tradeoff. If undoing gets added, it can be a per-editing session type thing. I think that’s how Photoshop handles undo also - once you save and close a PSD, you can no longer undo any of the history when loading that PSD back up.

Okay thanks! I’ll try the manual approach since I already have it loading into the correct render targets, as long as those render targets are created first by painting / stamping decals on the model. I’ll report back if I run into any trouble setting up the dummy stroke or anything else. :slight_smile:

To follow up, I got it working! I did have to make UDonMeshPainterComponent::SetupPaintingPrerequisites_AutoUv() a public function though as it was private originally. Any chance that you could make that function (probably all 3 of them for consistency) public in the next update?

Glad to hear! And sorry for the super-late response, been very busy of late and just got around to this now.

So you’re using DonExportPaintMasks function to save pngs directly? The SaveMeshPaintAsBytes’s function takes a bNeedsBakedTexturesForSkinnedMeshes param that should simply your workflow, but right now that function will save paint strokes too (even if you asked for only baked textures).

There is significant room for optimization in how paint strokes are stored as they were originally designed for one-off gameplay events like projectile impacts/etc. With some effort, the data structures can be redesigned to significantly reduce the size for full-on painting. The bAllowDuplicateStrokes flag will help reduce the bloat in some usecases, but is not well suited for repeated painting. I have some usecases coming up in this space within the next 6 months or so, so I might take this up at some point.

PS: SetupPaintingPrerequisites_AutoUv wasn’t meant to be public as its kind of an implementation detail. Using SetupPaintingPrerequisites should be equivalent other than the extraneous stroke/cell registration.

No, I never tested that function. I was under the impression that it wasn’t meant for this sort of thing and was for someone else’s needs. I manually get a reference to each of the render targets and call UTextureRenderTarget2D::ConstructTexture2D(). I actually have to call it twice per render target because the alpha channel is buggy with CTF_RemapAlphaAsMasked, but I eventually got it to work.

I use the _AutoUv version purposefully to avoid that registration. I didn’t know what that was for and I wasn’t sure if that would break anything.

It sounds like UE 4.18 will be released soon. I’m super excited for your plugin’s next update! :slight_smile:

4.18 Update ETA

Just a quick headsup that I’ll need around 3-4 weeks to submit the 4.18 version of this plugin.

This will allow for time to look at the various feature requests have come in from many of you as well. The exact list of new features hasn’t been prioritized yet, will publish the list towards the end of this month. Appreciate your patience in waiting :slight_smile:

Have you figured out how to get alpha with multi-colored text? I kind of got it working by creating a new temp render target that the canvas renders to as solid red and then rendering that render target to the final layer render target using that red channel as the alpha and supplying the actual text color in the material for copying the render targets, but it’s super buggy. By multi-colored text, I mean stamping a string in one color and then another one in a different color on the same actor / material.

The difference is

text_noalpha.png

vs

text_alpha.png

In the first one, I’m checking every pixel in my mesh’s material to see if it’s greater than absolute 0 and then counting that as alpha. It’s not a good solution but it lets me use multi-colored text. I believe this two render target solution is the correct solution, but I’m probably doing it wrong since I don’t really understand how canvases and render thread commands work.

If you need just three colors you can pack them as masks into the R/G/B channels like one of the sample project examples. If you need full-blown support I’ll need to think about this. Your solution is certainly very creative and probably among the few/only options available here as Unreal’s canvas text rendering doesn’t seem to support alpha channel.

I ended up rendering the text to a rendertarget, constructing a Texture2D from that, fixing the alpha on the Texture2D, and then feeding the Texture2D into the decal system. It works quite nicely. You could probably skip the Texture2D step by directly editing the alpha on the rendertarget and writing a new paint function that accepts a UTexture instead of a UTexture2D to send the rendertarget in as the decal. I would have done that but I haven’t had much luck directly editing render target pixels.

hello.png

Hey, glad to hear you got it working :slight_smile: Sounds like you’ve built something quite elaborate, curious to see your systems in action at some point! :slight_smile:

4.18 New Features!

New features have been submitted along with the 418 update for this plugin. Here’s the list of goodies:

**Effect Templates - **Save a source actor’s paint/effects as a template that can be loaded onto multiple actors, even dynamically spawned ones!
This allows you to take your character customization screens or other user-generated paint effects and apply them onto hordes of A.I. and what not! :slight_smile:

**Erasure Support - **Erase paint with full support for brushes/decals/layers at no extra performance cost! No extra render targets need to be maintained per material because of a smart pooling system that picks the required read-texture (needed for erasure) from a reusbale pool. As a result you get full erasure support without any additional texture memory usage :slight_smile:

**Save Filters - **Instead of saving the entire world (of painted actors), now you can pass in filters that help you control what gets saved.

**Flushing Paint - **New Blueprint/API functions have been added to flush paint for an actor, for a specific material on an actor, or even the entire world.


With these powerful new features in addition to its existing repertoire, the plugin is arguably a must have in the FX toolkit of any practically any game or genre.

**Buy at 50% Discount!** The plugin will be **50% off** on tomorrow's sale, so there's never been a better time to pick up this powerful addition to your FX toolkit! :D

I'll update this thread when the 4.18 files have been approved and are live.

**Version 3.0 is Live! **(New Features!)

I’m pleased to report that the latest version is available for download with all the new features mentioned above :slight_smile:

Here’s the new sample project. A new demo room to show off Effect Templates and new HUD options for erase, flush, etc have been added!
4.18 Sample Project

Reminder:** You can buy at 50% Discount today for $37.5 USD. **Sale lasts only for today!

PS: Big thanks to Marketplace Team for such an incredibly rapid turnaround on this update.

I’m absolutely amazed to see an update which formerly used to take 8-10 weeks to process was now fulfilled in less than 12 hours :slight_smile: Absolutely amazing progress and great work by the marketplace staff, this is very encouraging to see :slight_smile:

Hi,
Is there any way to suppress/fix the byte array warnings on using the load onto multiple actors node? Each array element is flooding me with the following log warnings:

LogUObjectGlobals: Warning: Failed to find object ‘Object None.None’

This is when testing out the 4.18 sample project.

Thanks.

I’m trying to compile for 4.17 engine and get these compile errors. Any idea how I could fix this? Thanks.

That error relates to IWYU enforcement; the 4.17 version of the plugin is not IWYU-ready as it includes PCH files as the first header.

Is your project enforcing iwyu in the build.cs or elsewhere?

In any case, the 4.18 version of the plugin is iwyu compliant (all marketplace plugins are now required to do so) so you have two options:-

Option 1) Download the 4.18 version of the plugin. Look at the headers included in all the 4.18 version’s CPP files and simply apply those header changes to your 4.17 version’s cpp files. That will make the cpp files iwyu compliant. The first header included is now always the source file’s corresponding header file (as requested by the compiler in your error message).

OR option 2) Try adding “bEnforceIWYU = false;” in the 4.17 version’s DonMeshPainting.Build.cs file as described in the iwyu link above. This might be sufficient to suppress those errors.

Please let me know if you need any further help with this! :slight_smile:

Sorry for that, it slipped through the cracks. The deserialization code is apparently encountering a null/invalid reference string that is emitting that error. I’ve debugged this issue once before but it needed more time to identify the root cause.I’ll take a look at this once again.

**@rennsix - **In case you already you already my post, I’ve edited “Option 1” completely. I’m no longer advising reverse migration from 4.18 to fix your issue as that would induce uasset dependencies in the plugin’s Content assets (and uasset files can’t be migrated backwards).

Since there is more functionality in the 4.18 plugin I ended up downloading Launcher 4.18.1, added plugin to engine and then copied the plugin into my source 4.18 and built with vs17 just fine.

Glad to hear :slight_smile:

Try the 4.18 Plugin Demo!

Download the free 4.18 sample project and give the latest features a whirl!

Effect templates, Erasure, Save Filters, Flushing paint are the new features. See this post for more about each of them.

This is also a great chance to sample the various FX / Gameplay / Save-Load features that come with this plugin, so do check it out :slight_smile:


PS: [USER="4812"]Daniel Skipper Games[/USER] - Haven't yet had a chance to look at suppressing the verbose save logs yet, will keep this thread posted on that.