Allow loading material colors from texture - #3403
Conversation
There was a problem hiding this comment.
I think we should make a materials folder, so it doesn't clutter with the other item textures.
Though I guess @careeoki should probably make the decision here.
There was a problem hiding this comment.
Yes please, a separate folder.
| } else { | ||
| self.outlineColorLight = darken(self.colorPalette[self.colorPalette.len - 1], 0.7); | ||
| } | ||
| if (zon.get(u32, "outlineColorShadow")) |colorInt| { |
There was a problem hiding this comment.
Please remove these again, you removed their single use-case already, all new development should use the texture, eventually the other colors attribute can also be removed.
| } | ||
|
|
||
| pub fn init(self: *Material, allocator: NeverFailingAllocator, zon: ZonElement) void { | ||
| fn loadColorsFromTexture(self: *Material, allocator: NeverFailingAllocator, colorTexturePath: []const u8, colorReplacementTexturePath: []const u8) bool { |
There was a problem hiding this comment.
Please don't use bools in function arguments/return values. An enum is more readable.
| }; | ||
| defer image.deinit(main.stackAllocator); | ||
| if (image.width == 0 or image.height < 2) { | ||
| std.log.err("Material color texture '{s}' must be at least 1x2 pixels (got {}x{}).", .{colorTexturePath, image.width, image.height}); |
There was a problem hiding this comment.
Doesn't it need to be at least 2×2 so you have the two outline colors?
| self.colorPalette[x] = image.getRGB(x, 0); | ||
| } | ||
| const shadow = image.getRGB(0, 1); | ||
| self.outlineColorShadow = if (shadow.a != 0) shadow else darken(self.colorPalette[0], 0.5); |
There was a problem hiding this comment.
Instead of automatic behavior, I think it is often better to output an error.
Furthermore this should reject any alpha less than 100%.
|
Ok, now the color textures are loaded from |
|
@careeoki are you otherwise happy with how the image is structured? |
|
Yes, it looks good. |
IntegratedQuantum
left a comment
There was a problem hiding this comment.
Thanks for working on this, I think this is going to make adding new or tweaking existing materials a lot easier.
I can do so for all the other materials via a script once the specifics of this solution are accepted.
I have also made an issue for this #3451 to also track how to deal with the current fallback logic once that's done.
As suggested in PixelGuys#3366 (review), this allows materials to source their `colorPalette`, `outlineColorLight` and `outlineColorShadow` from a small PNG instead of hardcoded ARGB hex literals in the `.zig.zon` file. Adds a new optional zon field, `.colorTexture = "name.png"`, a sibling of the existing `.texture` field. It's resolved through the exact same `items/textures/<mod>/` + `assets/<mod>/items/textures/` fallback convention already used for item textures. I've defined the format as an N x 2 image, where the top row is the gradient palette, dark to light, and the bottom row's two pixels are `outlineColorShadow` (x=0) and `outlineColorLight` (x=1). A fully transparent pixel there means the color is not specified, falling back to the existing computed `darken()` default. For backward compatibility, it uses the old hex fields if `.colorTexture` is absent or fails to load. <img width="160" height="64" alt="image" src="https://github.com/user-attachments/assets/db58fa08-d40b-4e46-ac25-3e796f53733a" /> I've migrated `iron_ingot` as an example from its hex values and dropped the old `colors` and `outlineColor*` fields from `iron_ingot.zig.zon` in favor of `.colorTexture = "iron_ingot_palette.png"`. I can do so for all the other materials via a script once the specifics of this solution are accepted. Also includes a small fix in `graphics.zig`: `Image.readFromFile`'s `.asIs` orientation option wasn't actually resetting the vertical-flip flag, so once one image was flipped, all images loaded after would also get flipped, regardless of the selected orientation. It now resets the flag.
As suggested in #3366 (review), this allows materials to source their
colorPalette,outlineColorLightandoutlineColorShadowfrom a small PNG instead of hardcoded ARGB hex literals in the.zig.zonfile.Adds a new optional zon field,
.colorTexture = "name.png", a sibling of the existing.texturefield. It's resolved through the exact sameitems/textures/<mod>/+assets/<mod>/items/textures/fallback convention already used for item textures. I've defined the format as an N x 2 image, where the top row is the gradient palette, dark to light, and the bottom row's two pixels areoutlineColorShadow(x=0) andoutlineColorLight(x=1). A fully transparent pixel there means the color is not specified, falling back to the existing computeddarken()default. For backward compatibility, it uses the old hex fields if.colorTextureis absent or fails to load.I've migrated
iron_ingotas an example from its hex values and dropped the oldcolorsandoutlineColor*fields fromiron_ingot.zig.zonin favor of.colorTexture = "iron_ingot_palette.png". I can do so for all the other materials via a script once the specifics of this solution are accepted.Also includes a small fix in
graphics.zig:Image.readFromFile's.asIsorientation option wasn't actually resetting the vertical-flip flag, so once one image was flipped, all images loaded after would also get flipped, regardless of the selected orientation. It now resets the flag.