From 756c8c9a8b951a47ba4edd10fa93cc6c4764290e Mon Sep 17 00:00:00 2001 From: Zailer43 Date: Mon, 8 Jul 2024 18:30:15 -0300 Subject: [PATCH] Add `has_alpha` to Color Parameter in head generator * Add this to `colored_glasses` and `sunglasses3` --- .../head_generator/0.2.14_head_generator.md | 388 ++++++++++++++++++ docs/en/wiki/head_generator/README.md | 3 + .../components/HeadComponentOverlay.java | 10 +- .../head_generator/HeadResourcesLoader.java | 8 +- .../head_generator/model/HeadModelEntry.java | 14 +- .../logic/head_generator/model/ModelData.java | 20 +- .../model/parameters/ColorParameter.java | 9 + .../model/parameters/INestedParameters.java | 5 +- .../parameters/ResettableModelParameter.java | 2 +- .../model/steps/ModelFillColorStep.java | 6 +- .../model/steps/ModelFunctionStep.java | 11 +- .../steps/fill_color/FillColorDesaturate.java | 6 +- .../steps/fill_color/FillColorGrayscale.java | 6 +- .../steps/fill_color/FillColorInverse.java | 6 +- .../steps/fill_color/FillColorMultiply.java | 16 +- .../steps/fill_color/FillColorSolid.java | 8 +- .../steps/fill_color/IFillColorAlgorithm.java | 6 +- .../zailer/me/utils/FzmmWikiConstants.java | 2 +- .../fzmm_models/heads/colored_glasses.json | 3 +- .../fzmm/fzmm_models/heads/sunglasses3.json | 3 +- 20 files changed, 468 insertions(+), 64 deletions(-) create mode 100644 docs/en/wiki/head_generator/0.2.14_head_generator.md create mode 100644 src/main/java/fzmm/zailer/me/client/logic/head_generator/model/parameters/ColorParameter.java diff --git a/docs/en/wiki/head_generator/0.2.14_head_generator.md b/docs/en/wiki/head_generator/0.2.14_head_generator.md new file mode 100644 index 00000000..2f0fcee8 --- /dev/null +++ b/docs/en/wiki/head_generator/0.2.14_head_generator.md @@ -0,0 +1,388 @@ +## How to create a resource pack for Head Generator + +To add custom heads to Head Generator using a resource pack, there are two different ways to generate skins: using "textures" and "models". + +## Changes in 0.2.14 + +* Add `has_alpha` to [Color parameter](#colorobject), which allows to change the alpha of the color from the GUI, optional, default false + +--- + +### Textures + +**Head textures** involves adding a texture on top of the skin, so it has a __simple but limited__ functionality; a more comprehensive version would be [Head models](#models) + +1. Create a normal resource pack and place the head textures in the `assets/fzmm/textures/heads` folder. The textures should be 64x16 images or larger in the PNG format, with only the first 64x16 pixels being used. + +2. Use the resource pack like any other. When you go to the head generator screen, the heads will be added to the list and arranged alphabetically. + +3. To find the heads more easily, you can add them to your favorites. + +#### Skins +You can use 64x64 textures. If you select the texture in the head generator, you can save the skin using the `Save skin` button, which will be stored in `.minecraft/fzmm/skins/`, and can be used for simple skin edits. + +#### Example + +You can check out the resource pack [FZMM Head generator example.zip](https://github.com/Zailer43/FZMM-Mod/files/10303878/FZMM.Head.generator.example.zip) to see how it's done. + +This example resource pack adds the following textures: +- Blue mask +- Ocelot mask + +--- + +### Models + +**Head models** is the enhanced version of [Head textures](#textures), which **allows for greater control** when manipulating the head, but it can also be a bit more cumbersome to use. + +Prerequisites include: + +- Knowledge of JSON +- Having a basic image editor (to take reference pixel positions, which will be necessary for editing) + +To add custom heads to Head Generator using models, follow these steps: + +1. Create a JSON file in the following folder: `assets/fzmm/fzmm_models/heads`. The JSON files support the following structure: + +```json5 +{ + // If enabled, it will be added to the "Paintable" category + // optional, default false + "paintable": boolean, + + // If enabled, it will be added to the "Body" category and the preview of the entire skin will be displayed + // optional, default false + "is_editing_skin_body": boolean, + + // If it is to be displayed as the first result in the list of heads + // optional, default false + "first_result": boolean, + + // If enabled, then the offsets will be internally switched from right to left, for example: LEFT_LEG -> RIGHT_LEG + // optional, default false + "inverted_left_and_right": boolean, + + // optional + // default: `base_skin`, `destination_skin` + "textures": TextureObject[], + + // optional + "colors": ColorObject[], + + // optional + "offsets" OffsetObject[], + + "steps": StepObject[] +} +``` +2. Use the resource pack like any other. When you go to the head generator screen, the heads will be added to the list and arranged alphabetically. + +3. To find the heads more easily, you can add them to your favorites. + + +#### Structure of objects and their possible values + + +#### Base objects + +
+Objects JSON structure + +##### TextureObject + +```json5 +{ + "path": String, // The path of the texture in the resource pack, for example: "fzmm:textures/model_textures/texture.png" + + "id": String, // The id used to identify the texture for use + + "requested": boolean, // Whether a image field will be displayed to the user to change the value, optional, by default true +} +``` + +##### ColorObject + +```json5 +{ + "color_hex": String, // default color, format is #AARRGGBB or #RRGGBB + // Example: #FFFFFF or #80FF00FF + + "has_alpha": Boolean, // Allows to modify color alpha from the GUI, optional, default false + + "id": String, // The id used to identify the color for use, + + "requested": boolean, // Whether a color field will be displayed to the user to change the value, optional, default true +} +``` + +##### OffsetObject + +```json5 +{ + "id": String, // To identify the offset when you want to activate or deactivate it + + "requested": boolean, // Whether a slider will be displayed to the user to change the value, optional, by default true + + "value": byte, // To determine the pixels to be offset, optional, by default 0 + + "min_value": byte, // Is the minimum value of `value` in the slider, optional, by default 0, + + "max_value": byte, // Is the maximum value of `value` in the slider, optional, by default 8 + + "axis": String, // Determines whether it is the X or Y axis, `X` for x and `Y` for `Y` + + "enabled": boolean // If enabled by default, optional, default false, when enabled the pixels are offset, + // can be toggled with StepObject "toggle_offset" +} +``` + +
+ +#### Possible StepObjects + +
+Objects JSON structure + +##### Condition +A condition, which allows handling specific cases, can help add compatibility in some instances, such as certain models requiring certain steps if the skin is slim or wide. + +```json5 +{ + "type": "condition", + + "condition": String, // The condition to be used is required and may or may not have arguments (which go into "arguments"). + // Possible values are: + // + // "is_slim_model": true if the selected skin is slim, false if it's wide. + // More technically, it verifies if the LEFT_ARM + 15 skin at x and y has an alpha of 0. + // Requires no arguments. + //--- + // "is_pixel": Compares if the pixel of an area is as expected. True if it's the same, false if it's different. + // It has the following arguments: + // + // "pos": PointObject + // "expected_color": string, // following the format of #AARRGGBB or #RRGGBB, for example #FF353635 + //--- + // "is_alpha": Compares if the alpha of the pixel of an area is as expected. True if it's within the range, + // false if it's outside the range. The range is inclusive. + // It has the following arguments: + // + // "pos": PointObject + // "min_alpha": int, //value from 0 to 255 + // "max_alpha": int, //value from 0 to 255 + + "arguments": Object, // The arguments required by "condition" are optional depending on whether + // the option requires arguments or not. + + + // "if_true" or "if_false" is required; there must be at least 1, both can be present. + + "if_true": StepObject[], // In case the condition is true + + "if_false": StepObject[] // In case the condition is false +} +``` + +##### Copy +Copies an area from the selected texture and places it in the destination texture, possibly the step you'll use the most + +```json5 +{ + "type": "copy", + + "source": Area, // The area of the selected texture where the pixels will be copied + + "destination": Area, // The area of the final texture where the copied pixels will be placed, + // this value is optional and if not specified, the same values of "source" will be used + + "add_hat_layer": boolean, // if true, it adds the first layer of the source in the destination + // and adds the second layer of both, this value ignores "hat_layer" of source and destination, + // this value is optional and by default is false + + "overlap_source_hat": boolean, // if true, it adds the first and second layer of the source in the destination, + // this value ignores "hat_layer" of source, this value is optional and by default is false + + "degrees": int, // rotates the texture when placing it in the destination but rotating it from its center, + // this value is optional and by default is 0 + + "mirror_horizontal": boolean, // applies a horizontal mirror to the copied texture, + // it is applied after rotating with degrees, this value is optional and by default is false + + "mirror_vertical": boolean // applies a vertical mirror to the copied texture, + // it is applied after rotating with degrees, this value is optional and by default is false +} +``` + +##### Delete +Deletes pixels from the selected area in the final texture + +```json5 +{ + "type": "delete", + "area": Area // the area where the pixels will be deleted +} +``` + +##### Fill color +Fills an area with the selected color using the specified algorithm + +```json5 +{ + "type": "fill_color", + + "area": Area, // the area to be filled with the selected color + + "algorithm": String // the type of algorithm to be used to obtain the color, possible algorithms: + // * desaturate: performs desaturation, converting the color to a grayscale scale. + // It removes the color information from the pixel and retains only its luminance component + // + // * grayscale: similar to the desaturation algorithm, this method also converts the color to grayscale. + // It uses a weighted average approach to calculate the grayscale value, which can yield slightly different + // results than desaturation. + // + // * inverse: invert the color to use its opposite + // + // * solid: uses the selected color without modifying// + // + // * multiply: multiplies the selected color and the color of the pixel to be changed, + // obtains a result more similar to the selected color if the selected pixel is in grayscale and is whiter +} +``` + +#### Function +Use steps from another [Head models](#models), allowing for reuse, helping to avoid having steps with slight changes and repeated in other [Head models](#models). + +Extra notes: + +* The [selected destination](#select-destination) is passed, so changing it will affect what the function changes. +* The [selected texture](#select-texture) is also passed, so changing it will make it the first texture that the function uses. +* The same applies to the [selected color](#select-color). +* If an [offset](#offsetobject) is passed, it will be passed in its current state to the previous Head models at the end of the function, which means that if you leave an offset enabled within your function, it will be applied to the next [step](#possible-stepobjects), even if that offset was not originally in the current model. + +```json5 +{ + "type": "function", + + "function_path": String, // Required, it's the other model that will be used, the initial path is + // `assets/fzmm/fzmm_models`, so possible values might be: `internal/my_custom_function` or `heads/plushie1`, + // note: no need to add .json + + "textures": TextureObject, // Optional, parameter that will be passed to the function, so it can use them + + "colors": ColorObject, // Optional, parameter that will be passed to the function, so it can use them + + "offsets": OffsetObject, // Optional, parameter that will be passed to the function, so it can use them, + // at the end of the function they will be added to the current model + + "pos": PointObject, // Optional, offset that will be applied to the function, not affected by `inverted_left_and_right` + + "inverted_left_and_right": boolean // Optional, parameter that will be passed to the function, so it can use them +} + + +``` + +##### Select color +Selects the color to be used in the next step, by default there is no color selected, the only color that can currently be modified via GUI is `selected_color`. White is used if no color is found + +```json5 +{ + "type": "select_color", + "color_id": String // The id defined in colors +} +``` + +##### Select destination +Select a texture that will be used in the following steps as the target of the modifications. The texture selected by default is the destination skin, its id is `destination_skin` + +```json5 +{ + "type": "select_destination", + "texture_id": String // The id defined in textures +} +``` + +##### Select texture +Selects a texture that will be used in the following steps. The default selected texture is the base skin, its id is `base_skin` + +```json5 +{ + "type": "select_texture", + "texture_id": String // The id defined in textures +} +``` + +##### Toggle offset +Step to enable or disable the offset, so that it only takes effect when you want it to, the offset is applied in the destination of all the steps to which it can be applied while it is enabled + +```json5 +{ + "type": "toggle_offset", + + "offset_id": String, // The id defined in offsets + + "enabled": boolean // new value +} +``` + +
+ +#### Other objects + +
+Objects JSON structure + +##### Area +Represents an area in a Minecraft skin model, with information about its position, size, and whether it includes the hat layer or not + +```json5 +{ + "offset": String, // The offset of the area + // Possible values are "HEAD", "BODY", "RIGHT_ARM", "RIGHT_LEG", "LEFT_LEG", "LEFT_ARM" + // + // Preconfigured values that do not require any other area attribute (x, y, etc.): + // "ALL" (entire skin), "ALL_BODY" (entire skin excluding the head) + + "hat_layer": boolean, // // Whether the area is the hat layer + + "x": int, // The x coordinate of the top-left corner of the area + + "y": int, // The y coordinate of the top-left corner of the area + + "width": int, // The width of the area + + "height": int // The height of the area +} +``` + +##### PointObject +Represents a point in a Minecraft skin model, with information about its position + +```json5 +{ + "offset": String, // The offset of the area + // Possible values are "HEAD", "BODY", "RIGHT_ARM", "RIGHT_LEG", "LEFT_LEG", "LEFT_ARM" + + "hat_layer": boolean, // // Whether the area is the hat layer + + "x": int, // The x coordinate of the top-left corner of the area + + "y": int // The y coordinate of the top-left corner of the area +} +``` + +
+ +#### Examples +You can find examples of the models in: https://github.com/Zailer43/FZMM-Mod/tree/2df8caf9bfb55cb50db88b114ba871ab7ef6ccf3/src/main/resources/resourcepacks/fzmm_default_heads/assets/fzmm/fzmm_models + +--- + +## Q: Can I generate a head without internet? +A: You can't, you need to have internet to access the mineskin API and send them the skin, so they upload it to a minecraft account, and then give you the value of the skin, you also need internet to load the skin. + +## Q: Can I speed up the generation of heads? +A: You can do it by associating **your Google account** in [mineskin](https://mineskin.org/apikey) and entering your API Key in the mod configuration, it will make uploading skins **1-2 seconds faster** + +## Q: Where did you get the heads that the mod currently contains +A: Mostly from [NameMC](https://namemc.com) and some from [Minecraft-Heads](https://minecraft-heads.com), I have cropped them and deleted the unnecessary pixels of the head diff --git a/docs/en/wiki/head_generator/README.md b/docs/en/wiki/head_generator/README.md index 005d7f84..85ecbc1f 100644 --- a/docs/en/wiki/head_generator/README.md +++ b/docs/en/wiki/head_generator/README.md @@ -7,6 +7,9 @@ and with the "models" option you can turn your skin into a plushie/mini version, # Versions Versions are only added when there was a change, if the version you are using does not appear it means that there were no changes, so you must go to the most recent one. +## [0.2.14](./0.2.14_head_generator.md) +Add `has_alpha` in Color parameter + ## [0.2.11](./0.2.11_head_generator.md) Remove `Desaturate` step (break change) diff --git a/src/main/java/fzmm/zailer/me/client/gui/head_generator/components/HeadComponentOverlay.java b/src/main/java/fzmm/zailer/me/client/gui/head_generator/components/HeadComponentOverlay.java index 528464b5..e0876646 100644 --- a/src/main/java/fzmm/zailer/me/client/gui/head_generator/components/HeadComponentOverlay.java +++ b/src/main/java/fzmm/zailer/me/client/gui/head_generator/components/HeadComponentOverlay.java @@ -15,6 +15,7 @@ import fzmm.zailer.me.client.logic.head_generator.AbstractHeadEntry; import fzmm.zailer.me.client.logic.head_generator.model.HeadModelEntry; import fzmm.zailer.me.client.logic.head_generator.model.InternalModels; +import fzmm.zailer.me.client.logic.head_generator.model.parameters.ColorParameter; import fzmm.zailer.me.client.logic.head_generator.model.parameters.INestedParameters; import fzmm.zailer.me.client.logic.head_generator.model.parameters.OffsetParameter; import fzmm.zailer.me.client.logic.head_generator.model.parameters.ParameterList; @@ -183,7 +184,7 @@ private void addTextureParameters(FlowLayout parametersLayout, INestedParameters private void addColorParameters(FlowLayout parametersLayout, INestedParameters parametersEntry, String baseTranslation, AbstractHeadComponentEntry headComponentEntry) { - ParameterList colorParameters = parametersEntry.getNestedColorParameters(); + ParameterList colorParameters = parametersEntry.getNestedColorParameters(); for (var colorParameter : colorParameters.parameterList()) { if (!colorParameter.isRequested()) continue; @@ -191,8 +192,11 @@ private void addColorParameters(FlowLayout parametersLayout, INestedParameters p ColorRow colorRow = new ColorRow(baseTranslation, id, id, false, false); parametersLayout.child(colorRow); - ColorRow.setup(parametersLayout, id, colorParameter.value().orElse(Color.WHITE), false, 300, s -> { - colorParameters.update(colorParameter.id(), colorRow.getValue()); + ColorParameter color = colorParameter.value().orElse(ColorParameter.getDefault()); + boolean hasAlpha = color.hasAlpha(); + + ColorRow.setup(parametersLayout, id, color.color(), hasAlpha, 300, s -> { + colorParameters.update(colorParameter.id(), new ColorParameter(colorRow.getValue(), hasAlpha)); headComponentEntry.update(); }); diff --git a/src/main/java/fzmm/zailer/me/client/logic/head_generator/HeadResourcesLoader.java b/src/main/java/fzmm/zailer/me/client/logic/head_generator/HeadResourcesLoader.java index eebae246..72fbb6f2 100644 --- a/src/main/java/fzmm/zailer/me/client/logic/head_generator/HeadResourcesLoader.java +++ b/src/main/java/fzmm/zailer/me/client/logic/head_generator/HeadResourcesLoader.java @@ -183,7 +183,7 @@ public static HeadModelEntry getHeadModel(String basePath, Identifier identifier JsonObject jsonObject = JsonParser.parseReader(new InputStreamReader(inputStream)).getAsJsonObject(); Optional> textures = getParameterList(jsonObject, "textures", HeadResourcesLoader::textureParser); - Optional> colors = getParameterList(jsonObject, "colors", HeadResourcesLoader::colorParser); + Optional> colors = getParameterList(jsonObject, "colors", HeadResourcesLoader::colorParser); Optional> offsets = getParameterList(jsonObject, "offsets", HeadResourcesLoader::offsetParser); boolean isPaintableModel = jsonObject.has("paintable") && jsonObject.get("paintable").getAsBoolean(); boolean isEditingSkinBody = jsonObject.has("is_editing_skin_body") && jsonObject.get("is_editing_skin_body").getAsBoolean(); @@ -265,7 +265,7 @@ public static IParameterEntry textureParser(JsonObject jsonObject return new ResettableModelParameter<>(id, null, defaultValue, requested); } - public static IParameterEntry colorParser(JsonObject jsonObject) { + public static IParameterEntry colorParser(JsonObject jsonObject) { String id = HeadResourcesLoader.get(jsonObject, "id").getAsString(); boolean requested = !jsonObject.has("requested") || jsonObject.get("requested").getAsBoolean(); @@ -275,7 +275,9 @@ public static IParameterEntry colorParser(JsonObject jsonObject) { color = parseColor(colorHex); } - return new ModelParameter<>(id, color, requested); + boolean hasAlpha = jsonObject.has("has_alpha") && jsonObject.get("has_alpha").getAsBoolean(); + + return new ModelParameter<>(id, new ColorParameter(color, hasAlpha), requested); } public static Color parseColor(String colorHex) { diff --git a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/HeadModelEntry.java b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/HeadModelEntry.java index 32d538df..35461ec6 100644 --- a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/HeadModelEntry.java +++ b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/HeadModelEntry.java @@ -3,13 +3,9 @@ import fzmm.zailer.me.client.gui.head_generator.category.HeadModelCategory; import fzmm.zailer.me.client.gui.head_generator.category.HeadPaintableCategory; import fzmm.zailer.me.client.logic.head_generator.AbstractHeadEntry; -import fzmm.zailer.me.client.logic.head_generator.model.parameters.INestedParameters; -import fzmm.zailer.me.client.logic.head_generator.model.parameters.OffsetParameter; -import fzmm.zailer.me.client.logic.head_generator.model.parameters.ParameterList; -import fzmm.zailer.me.client.logic.head_generator.model.parameters.ResettableModelParameter; +import fzmm.zailer.me.client.logic.head_generator.model.parameters.*; import fzmm.zailer.me.client.logic.head_generator.model.steps.IModelStep; import fzmm.zailer.me.utils.ImageUtils; -import io.wispforest.owo.ui.core.Color; import net.minecraft.util.Identifier; import org.jetbrains.annotations.Nullable; @@ -26,7 +22,7 @@ public class HeadModelEntry extends AbstractHeadEntry implements INestedParamete @Nullable private ParameterList textures = null; @Nullable - private ParameterList colors = null; + private ParameterList colors = null; @Nullable private ParameterList offsets = null; private boolean isPaintable = false; @@ -41,7 +37,7 @@ public HeadModelEntry() { public HeadModelEntry(String key, List steps, @Nullable ParameterList textures, - @Nullable ParameterList colors, + @Nullable ParameterList colors, @Nullable ParameterList offsets) { super(key); this.steps.addAll(steps); @@ -69,7 +65,7 @@ public BufferedImage getHeadSkin(BufferedImage baseSkin) { Graphics2D destinationGraphics = result.createGraphics(); ModelData data = new ModelData(destinationGraphics, DESTINATION_ID, this.textures, - this.colors, this.offsets, baseSkin, Color.WHITE, this.isInvertedLeftAndRight()); + this.colors, this.offsets, baseSkin, ColorParameter.getDefault(), this.isInvertedLeftAndRight()); this.apply(data, baseSkin, result); this.resetOffset(data.offsets()); @@ -170,7 +166,7 @@ public ParameterList getTextureParameters() { } @Override - public ParameterList getColorParameters() { + public ParameterList getColorParameters() { return this.colors == null ? new ParameterList<>() : this.colors; } diff --git a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/ModelData.java b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/ModelData.java index b61208b6..18002617 100644 --- a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/ModelData.java +++ b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/ModelData.java @@ -1,9 +1,9 @@ package fzmm.zailer.me.client.logic.head_generator.model; import fzmm.zailer.me.client.FzmmClient; +import fzmm.zailer.me.client.logic.head_generator.model.parameters.ColorParameter; import fzmm.zailer.me.client.logic.head_generator.model.parameters.OffsetParameter; import fzmm.zailer.me.client.logic.head_generator.model.parameters.ParameterList; -import io.wispforest.owo.ui.core.Color; import org.jetbrains.annotations.Nullable; import java.awt.*; @@ -14,15 +14,15 @@ public final class ModelData { private Graphics2D destinationGraphics; private String destinationId; private final ParameterList textures; - private final ParameterList colors; + private final ParameterList colors; private final ParameterList offsets; private final boolean isInvertedLeftAndRight; private BufferedImage selectedTexture; - private Color selectedColor; + private ColorParameter selectedColor; public ModelData(Graphics2D destinationGraphics, String destinationId, @Nullable ParameterList textures, - @Nullable ParameterList colors, @Nullable ParameterList offsets, - BufferedImage selectedTexture, Color selectedColor, boolean isInvertedLeftAndRight) { + @Nullable ParameterList colors, @Nullable ParameterList offsets, + BufferedImage selectedTexture, ColorParameter selectedColor, boolean isInvertedLeftAndRight) { this.destinationGraphics = destinationGraphics; this.destinationId = destinationId; this.textures = textures == null ? new ParameterList<>() : textures; @@ -33,8 +33,8 @@ public ModelData(Graphics2D destinationGraphics, String destinationId, @Nullable this.isInvertedLeftAndRight = isInvertedLeftAndRight; } - public Color getColor(String key) { - return this.colors.get(key).orElse(Color.WHITE); + public ColorParameter getColor(String key) { + return this.colors.get(key).orElse(ColorParameter.getDefault()); } @@ -62,7 +62,7 @@ public ParameterList textures() { return this.textures; } - public ParameterList colors() { + public ParameterList colors() { return this.colors; } @@ -74,7 +74,7 @@ public BufferedImage selectedTexture() { return this.selectedTexture; } - public Color selectedColor() { + public ColorParameter selectedColor() { return this.selectedColor; } @@ -90,7 +90,7 @@ public void selectedTexture(BufferedImage texture) { this.selectedTexture = texture; } - public void selectedColor(Color color) { + public void selectedColor(ColorParameter color) { this.selectedColor = color; } diff --git a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/parameters/ColorParameter.java b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/parameters/ColorParameter.java new file mode 100644 index 00000000..eefcb131 --- /dev/null +++ b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/parameters/ColorParameter.java @@ -0,0 +1,9 @@ +package fzmm.zailer.me.client.logic.head_generator.model.parameters; + +import io.wispforest.owo.ui.core.Color; + +public record ColorParameter(Color color, boolean hasAlpha) { + public static ColorParameter getDefault() { + return new ColorParameter(Color.WHITE, false); + } +} diff --git a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/parameters/INestedParameters.java b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/parameters/INestedParameters.java index df1f2395..42db8bc5 100644 --- a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/parameters/INestedParameters.java +++ b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/parameters/INestedParameters.java @@ -1,7 +1,6 @@ package fzmm.zailer.me.client.logic.head_generator.model.parameters; import fzmm.zailer.me.client.logic.head_generator.model.steps.IModelStep; -import io.wispforest.owo.ui.core.Color; import java.awt.image.BufferedImage; import java.util.List; @@ -39,7 +38,7 @@ default ParameterList getNestedTextureParameters() { return this.getNestedParameters(this::getTextureParameters, INestedParameters::getNestedTextureParameters); } - default ParameterList getNestedColorParameters() { + default ParameterList getNestedColorParameters() { return this.getNestedParameters(this::getColorParameters, INestedParameters::getNestedColorParameters); } @@ -47,7 +46,7 @@ default ParameterList getNestedColorParameters() { ParameterList getTextureParameters(); - ParameterList getColorParameters(); + ParameterList getColorParameters(); List getSteps(); } diff --git a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/parameters/ResettableModelParameter.java b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/parameters/ResettableModelParameter.java index 709116e7..a82e2669 100644 --- a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/parameters/ResettableModelParameter.java +++ b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/parameters/ResettableModelParameter.java @@ -4,7 +4,7 @@ public class ResettableModelParameter extends ModelParameter { @Nullable - private final String defaultValue; + private final String defaultValue; /** * @param defaultValue The default value is a string because it is the value used in the text field diff --git a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/ModelFillColorStep.java b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/ModelFillColorStep.java index 3afdf794..08e0ac28 100644 --- a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/ModelFillColorStep.java +++ b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/ModelFillColorStep.java @@ -5,8 +5,8 @@ import fzmm.zailer.me.client.logic.head_generator.HeadResourcesLoader; import fzmm.zailer.me.client.logic.head_generator.model.ModelArea; import fzmm.zailer.me.client.logic.head_generator.model.ModelData; +import fzmm.zailer.me.client.logic.head_generator.model.parameters.ColorParameter; import fzmm.zailer.me.client.logic.head_generator.model.steps.fill_color.IFillColorAlgorithm; -import io.wispforest.owo.ui.core.Color; import java.awt.image.BufferedImage; import java.util.Optional; @@ -33,7 +33,7 @@ public void apply(ModelData data) { ModelArea area = this.area.copyWithOffset(data.offsets().parameterList()); BufferedImage texture = optionalTexture.get(); - Color selectedColor = data.selectedColor(); + ColorParameter selectedColor = data.selectedColor(); int posX = area.getXWithOffset(); int posY = area.getYWithOffset(); @@ -52,7 +52,7 @@ public void apply(ModelData data) { for (int y = posY; y < posY2; y++) { for (int x = posX; x < posX2; x++) { int pixelColor = texture.getRGB(x, y); - if (!this.algorithm.acceptTransparency() && (pixelColor >> 24) == 0) + if (!this.algorithm.acceptTransparentPixel() && (pixelColor >> 24) == 0) continue; int colorArgb = this.algorithm.getColor(selectedColor, pixelColor); diff --git a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/ModelFunctionStep.java b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/ModelFunctionStep.java index 72ebba9c..2fa9aa07 100644 --- a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/ModelFunctionStep.java +++ b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/ModelFunctionStep.java @@ -8,7 +8,6 @@ import fzmm.zailer.me.client.logic.head_generator.model.ModelData; import fzmm.zailer.me.client.logic.head_generator.model.ModelPoint; import fzmm.zailer.me.client.logic.head_generator.model.parameters.*; -import io.wispforest.owo.ui.core.Color; import org.jetbrains.annotations.Nullable; import java.awt.image.BufferedImage; @@ -23,7 +22,7 @@ public class ModelFunctionStep implements IModelStep, INestedParameters { @Nullable private final ParameterList textures; @Nullable - private final ParameterList colors; + private final ParameterList colors; @Nullable private final ParameterList offsets; @Nullable @@ -31,7 +30,7 @@ public class ModelFunctionStep implements IModelStep, INestedParameters { private final boolean isInvertedLeftAndRight; public ModelFunctionStep(String functionPath, @Nullable ParameterList textures, - @Nullable ParameterList colors, @Nullable ParameterList offsets, + @Nullable ParameterList colors, @Nullable ParameterList offsets, ModelPoint pos, boolean isInvertedLeftAndRight) { this.functionPath = functionPath; this.textures = textures; @@ -57,7 +56,7 @@ public void apply(ModelData data) { ParameterList textures = this.textures != null ? this.textures.copy() : null; ParameterList offsets = this.offsets != null ? this.offsets.copy() : new ParameterList<>(); - ParameterList colors = this.colors != null ? this.colors.copy() : null; + ParameterList colors = this.colors != null ? this.colors.copy() : null; if (this.functionOffsets != null) { offsets.put(this.functionOffsets); @@ -137,7 +136,7 @@ public ParameterList getTextureParameters() { } @Override - public ParameterList getColorParameters() { + public ParameterList getColorParameters() { return this.colors == null ? new ParameterList<>() : this.colors; } @@ -158,7 +157,7 @@ public static ModelFunctionStep parse(JsonObject jsonObject) { Optional> textures = HeadResourcesLoader.getParameterList(jsonObject, "textures", HeadResourcesLoader::textureParser); - Optional> colors = HeadResourcesLoader.getParameterList(jsonObject, + Optional> colors = HeadResourcesLoader.getParameterList(jsonObject, "colors", HeadResourcesLoader::colorParser); Optional> offsets = HeadResourcesLoader.getParameterList(jsonObject, diff --git a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorDesaturate.java b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorDesaturate.java index 947bddc2..fa99b5c8 100644 --- a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorDesaturate.java +++ b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorDesaturate.java @@ -1,10 +1,10 @@ package fzmm.zailer.me.client.logic.head_generator.model.steps.fill_color; -import io.wispforest.owo.ui.core.Color; +import fzmm.zailer.me.client.logic.head_generator.model.parameters.ColorParameter; public class FillColorDesaturate implements IFillColorAlgorithm { @Override - public int getColor(Color selectedColor, int pixelColor) { + public int getColor(ColorParameter colorParameter, int pixelColor) { int alpha = (pixelColor >> 24) & 0xFF; int red = (pixelColor >> 16) & 0xFF; int green = (pixelColor >> 8) & 0xFF; @@ -16,7 +16,7 @@ public int getColor(Color selectedColor, int pixelColor) { } @Override - public boolean acceptTransparency() { + public boolean acceptTransparentPixel() { return false; } } diff --git a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorGrayscale.java b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorGrayscale.java index 31e72979..a2ada50c 100644 --- a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorGrayscale.java +++ b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorGrayscale.java @@ -1,10 +1,10 @@ package fzmm.zailer.me.client.logic.head_generator.model.steps.fill_color; -import io.wispforest.owo.ui.core.Color; +import fzmm.zailer.me.client.logic.head_generator.model.parameters.ColorParameter; public class FillColorGrayscale implements IFillColorAlgorithm { @Override - public int getColor(Color selectedColor, int pixelColor) { + public int getColor(ColorParameter colorParameter, int pixelColor) { int alpha = (pixelColor >> 24) & 0xFF; int red = (pixelColor >> 16) & 0xFF; int green = (pixelColor >> 8) & 0xFF; @@ -17,7 +17,7 @@ public int getColor(Color selectedColor, int pixelColor) { } @Override - public boolean acceptTransparency() { + public boolean acceptTransparentPixel() { return false; } } diff --git a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorInverse.java b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorInverse.java index d9e9f91a..52970634 100644 --- a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorInverse.java +++ b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorInverse.java @@ -1,10 +1,10 @@ package fzmm.zailer.me.client.logic.head_generator.model.steps.fill_color; -import io.wispforest.owo.ui.core.Color; +import fzmm.zailer.me.client.logic.head_generator.model.parameters.ColorParameter; public class FillColorInverse implements IFillColorAlgorithm { @Override - public int getColor(Color selectedColor, int pixelColor) { + public int getColor(ColorParameter colorParameter, int pixelColor) { int alpha = (pixelColor >> 24); int red = (pixelColor >> 16) & 0xFF; int green = (pixelColor >> 8) & 0xFF; @@ -18,7 +18,7 @@ public int getColor(Color selectedColor, int pixelColor) { } @Override - public boolean acceptTransparency() { + public boolean acceptTransparentPixel() { return false; } } diff --git a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorMultiply.java b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorMultiply.java index 773b9e57..b865920e 100644 --- a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorMultiply.java +++ b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorMultiply.java @@ -1,24 +1,26 @@ package fzmm.zailer.me.client.logic.head_generator.model.steps.fill_color; +import fzmm.zailer.me.client.logic.head_generator.model.parameters.ColorParameter; import io.wispforest.owo.ui.core.Color; public class FillColorMultiply implements IFillColorAlgorithm { @Override - public int getColor(Color selectedColor, int pixelColor) { - int alpha = (pixelColor >> 24); + public int getColor(ColorParameter colorParameter, int pixelColor) { + Color color = colorParameter.color(); + float alpha = colorParameter.hasAlpha() ? color.alpha() : ((pixelColor >> 24) & 0xFF) / 255f; int origRed = (pixelColor >> 16) & 0xFF; int origGreen = (pixelColor >> 8) & 0xFF; int origBlue = pixelColor & 0xFF; - int newRed = (int) (origRed * selectedColor.red()); - int newGreen = (int) (origGreen * selectedColor.green()); - int newBlue = (int) (origBlue * selectedColor.blue()); + int newRed = (int) (origRed * color.red()); + int newGreen = (int) (origGreen * color.green()); + int newBlue = (int) (origBlue * color.blue()); - return new Color(newRed / 255f, newGreen / 255f, newBlue / 255f, alpha / 255f).argb(); + return new Color(newRed / 255f, newGreen / 255f, newBlue / 255f, alpha).argb(); } @Override - public boolean acceptTransparency() { + public boolean acceptTransparentPixel() { return false; } } diff --git a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorSolid.java b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorSolid.java index 2000db98..df33ecc4 100644 --- a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorSolid.java +++ b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/FillColorSolid.java @@ -1,15 +1,15 @@ package fzmm.zailer.me.client.logic.head_generator.model.steps.fill_color; -import io.wispforest.owo.ui.core.Color; +import fzmm.zailer.me.client.logic.head_generator.model.parameters.ColorParameter; public class FillColorSolid implements IFillColorAlgorithm { @Override - public int getColor(Color selectedColor, int pixelColor) { - return selectedColor.argb(); + public int getColor(ColorParameter colorParameter, int pixelColor) { + return colorParameter.color().argb(); } @Override - public boolean acceptTransparency() { + public boolean acceptTransparentPixel() { return true; } } diff --git a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/IFillColorAlgorithm.java b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/IFillColorAlgorithm.java index 1029a30d..be4bfa63 100644 --- a/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/IFillColorAlgorithm.java +++ b/src/main/java/fzmm/zailer/me/client/logic/head_generator/model/steps/fill_color/IFillColorAlgorithm.java @@ -1,6 +1,6 @@ package fzmm.zailer.me.client.logic.head_generator.model.steps.fill_color; -import io.wispforest.owo.ui.core.Color; +import fzmm.zailer.me.client.logic.head_generator.model.parameters.ColorParameter; public interface IFillColorAlgorithm { IFillColorAlgorithm DESATURATE = new FillColorDesaturate(); @@ -12,10 +12,10 @@ public interface IFillColorAlgorithm { /** * @return ARGB color */ - int getColor(Color selectedColor, int pixelColor); + int getColor(ColorParameter colorParameter, int pixelColor); /** * @return true if the algorithm supports alpha 0 */ - boolean acceptTransparency(); + boolean acceptTransparentPixel(); } diff --git a/src/main/java/fzmm/zailer/me/utils/FzmmWikiConstants.java b/src/main/java/fzmm/zailer/me/utils/FzmmWikiConstants.java index 9dcaa6ac..8304b02f 100644 --- a/src/main/java/fzmm/zailer/me/utils/FzmmWikiConstants.java +++ b/src/main/java/fzmm/zailer/me/utils/FzmmWikiConstants.java @@ -4,7 +4,7 @@ public class FzmmWikiConstants { public static final String CURRENT_BRANCH = "1.21/dev"; public static final String BASE_LINK = "https://github.com/Zailer43/FZMM-Mod/blob/" + CURRENT_BRANCH + "/docs/en/wiki/"; - public static final String HEAD_GENERATOR_LAST_CHANGE_VERSION = "0.2.11"; + public static final String HEAD_GENERATOR_LAST_CHANGE_VERSION = "0.2.14"; public static final String HEAD_GENERATOR_WIKI_LINK = BASE_LINK + "head_generator/" + HEAD_GENERATOR_LAST_CHANGE_VERSION + "_head_generator.md"; public static final String PLAYER_STATUE_LAST_CHANGE_VERSION = "0.2.9"; diff --git a/src/main/resources/resourcepacks/fzmm_default_heads/assets/fzmm/fzmm_models/heads/colored_glasses.json b/src/main/resources/resourcepacks/fzmm_default_heads/assets/fzmm/fzmm_models/heads/colored_glasses.json index bf1874f7..2e723467 100644 --- a/src/main/resources/resourcepacks/fzmm_default_heads/assets/fzmm/fzmm_models/heads/colored_glasses.json +++ b/src/main/resources/resourcepacks/fzmm_default_heads/assets/fzmm/fzmm_models/heads/colored_glasses.json @@ -2,7 +2,8 @@ "paintable": true, "colors": [ { "id": "selected_color", - "color_hex": "#202020" + "color_hex": "#D0202020", + "has_alpha": true } ], "steps": [ diff --git a/src/main/resources/resourcepacks/fzmm_default_heads/assets/fzmm/fzmm_models/heads/sunglasses3.json b/src/main/resources/resourcepacks/fzmm_default_heads/assets/fzmm/fzmm_models/heads/sunglasses3.json index 795db806..3a84ee6d 100644 --- a/src/main/resources/resourcepacks/fzmm_default_heads/assets/fzmm/fzmm_models/heads/sunglasses3.json +++ b/src/main/resources/resourcepacks/fzmm_default_heads/assets/fzmm/fzmm_models/heads/sunglasses3.json @@ -3,7 +3,8 @@ "colors": [ { "id": "glass_color", - "color_hex": "#3e3e3e" + "color_hex": "#D03e3e3e", + "has_alpha": true } ], "steps": [