Vanilla-Expanded / VanillaExpandedFramework

Vanilla Expanded Framework for RimWorld
Other
69 stars 34 forks source link

Pipe Network: Dynamic Color Support #32

Open camperdave opened 1 year ago

camperdave commented 1 year ago

This PR implements support for recoloring the pipes themselves, as well as the deconstruction gizmo icon.

Most of the other buildings support this kind of dynamic texture palette swapping already - but these two places required additional support from the framework.

I have tested this successfully on my local machine, but I'm open to any suggestions on how to improve this code, as I'm very new to Unity graphics programming.

Taranchuk commented 1 year ago

Doesn't the game have an option to recolor command icons?

Taranchuk commented 1 year ago

I think I've used for that just a iconColorOverride field for commands. Alternatively, doing the GUI.color assignment manually should do the trick

camperdave commented 1 year ago

I definitely didn't know about iconColorOverride, so I'll have to do some poking around there later tonight. I do know that from my earlier testing, blasting the entire icon with a single color looks pretty bad - which is why I went down the route of the ComplexCutout / mask and color approach. The best answer may be to see if there's a way to combine the two!

Taranchuk commented 1 year ago

Doesn't the game use masks for item gismos? When you select an apparel, the game will have a gizmo with it already colored properly

KylianB commented 1 year ago

It's not that I'm against doing this, but why not simply modify the textures? Same things for the pipes?

camperdave commented 1 year ago

@KylianB - This is probably not the world's greatest reason, but I'm absolutely terrible at making art. My first drafts at making a pipe mod.... looked awful. Once I discovered that Rimworld already had support for palette swapping art, I realized that it would probably be faster, more visually consistent, and far more interesting to learn how to extend the palette swapping code. I'm probably not the only one out there with a better grasp of XML / C# than art, so I wanted to introduce this support at the framework level. By generating the textures once at runtime, we can sidestep any potential issues of distributing copyrighted Ludeon assets (or assets created by others), and make our mod packages smaller for our users. Especially for the pipes themselves - it's quite likely a single texture atlas could represent basically every pipe a user would need.

@Taranchuk - I've been looking into the game's existing code for generating gizmo icons. It does seem like there might be a better way to implement things, but even looking through the apparel items like smokepop packs, I mostly am finding places that assign the underlying Command.icon property to their parent Thing's UI icon. I'm not exactly sure how that would work in this case - though it does give me some ideas to potentially simplify the way I'm generating the texture (may be possible to avoid the RenderTexture). Do you happen to have an apparel or other item in mind that I could spawn in game to get a look at what you're talking about to confirm I'm looking at the right stuff here?

camperdave commented 1 year ago

Unfortunately, I haven't managed to avoid the RenderTexture yet. I'll keep digging, but the path I was originally investigation ended up being specific to ThingDef, I think? I'll keep looking...

Helixien commented 1 year ago

It's not that I'm against doing this, but why not simply modify the textures? Same things for the pipes? @KylianB Not that I have a horse in this race, but I wouldnt be me if I didnt give my opinion unasked, I can just bother Oskar for the pipe AI file if needed, but importing the texture, recolouring and exporting again will lower the quality. As OP is pointing out, handling pipes like, simply put, most armour is in the game, would be much easier. One white pipe texture and the game colours it as needed.

KylianB commented 1 year ago

I can definitely understand the appeal of a feature like that. I will review the code soon! One thing I'm not sure I understand though is that there is no pipe texture included in the framework (apart from the atlas texture)?

camperdave commented 1 year ago

I can definitely understand the appeal of a feature like that. I will review the code soon! One thing I'm not sure I understand though is that there is no pipe texture included in the framework (apart from the atlas texture)?

There is not currently a pipe texture in the framework. For my testing, I had created a mod with an explicit dependency on Vanilla Chemfuel Expanded, and this framework. It would probably be better if there were white pipe textures (and maybe even the drain / tap / valve textures?) in the framework itself... but I am not particularly good at that side of things.

Taranchuk commented 1 year ago

@camperdave hey, missed the response. As for the apparel gizmo, I must've misremembered or I had a mod which added gizmos with them. But basically in vanilla, just construct a stuffable building, for example table and the game will show you its gizmo with the building already shown in proper color. See this image

camperdave commented 1 year ago

@Taranchuk

Thanks for the pointer to the type of icon you were talking about. I dug into the code for build designators a bit more, and while I'm not an expert on Unity graphics programming, I think I see the difference between the method I was using and how the base game draws these colored designators.

I believe that the base game is handling the color override for building "stuff" color within the Verse.Widgets class - that is, only at the time the icon is drawn to the screen. I need to do some more investigation to determine if that's more performant than generating the icon once up front in the designator constructor and caching it as a separate game texture, as I had been doing. Again, I'm not a Unity graphics expert, but to my untrained eye, it seemed that one time caching would be superior - but there's obviously a memory cost involved.

Additionally, taking another look at these building textures, I may have made this problem more complex than is required. The existing building masks and textures use only a single color replacement, which seems to allow them to use the Verse.BuildableDef::GetColorForStuff function to select a single color for the building, and then apply that as an override at rendering time using GUI.Color? In my initial deconstruction icon mask, I took advantage of a two-color solution. This allows that little vertical bar to be colored independently from the primary pipe color, and still permits the main "deconstruction staircase icon" to remain the original green color. That's... a pretty small benefit, although it does look nice to me! So if it turns out that my assumptions on caching are wrong and I need to swap to the GUI.color method, I think the best path forward would be to change that mask to use a single color.