Skip to content

Texture Stretch

dfdvdsf edited this page Aug 10, 2026 · 1 revision

New file: src/main/java/decok/dfcdvadstf/catframe/ui/util/TextureStretching.java

Design: Strategy interface + built-in implementations + static convenience methods + external data-driven configuration.

public final class TextureStretching {
    // Strategy interface (extensible)
    public interface StretchStrategy {
        void draw(ResourceLocation tex, int x, int y, int w, int h);
    }

    // ── Built-in implementation 1: Nine-patch ──
    // 4 corners fixed, 4 edges tiled, center tiled
    public static void drawNinePatch(ResourceLocation tex, int x, int y, int w, int h,
                                      int edgeL, int edgeT, int edgeR, int edgeB,
                                      int texW, int texH);

    // ── Built-in implementation 2: fixed ends, repeated middle ──
    // left edgeL pixels fixed, right edgeR pixels fixed, middle repeats with tileW pixels
    public static void drawFixedEndRepeat(ResourceLocation tex, int x, int y, int w, int h,
                                           int edgeL, int edgeR, int tileW,
                                           int texW, int texH);

    // ── Generic tiling (extracted from ContentPanelRenderer/TabBar) ──
    public static void drawTiled(ResourceLocation tex, int x, int y, int w, int h,
                                  int tileW, int tileH);
}

Refactor existing code (reduce duplication):

  • ContentPanelRenderer.drawTiledTexture() → delegate to TextureStretching.drawTiled()
  • TabBar.drawTiledBackground() → delegate to TextureStretching.drawTiled()
  • The left-middle-right logic of TabBar.drawSingleTabButton() → delegate to TextureStretching.drawFixedEndRepeat()

//Below are the user's ideas This data-driven approach was derived from vanilla's design. The default is envisioned similar to the *.png.mcmeta files introduced by dynamic textures, defining the following types:

Example:

{
  
  "stretching":{
    "type": "three_patch",
    "default":{
      "width": 16,
      "hight": 16
    },
    "edge":{
      "up": 2,
      "down": 3,
      "left": 2,
      "right": 2
    },
    "limit":{
      "width": 20,
      "hight": 6
    },
    "inner":{
      "will_stretch": false,
      "height": 11,
      "width": 12
    }
  }
}

Definition: It must be defined inside the streching key. It also requires a corresponding *.png.mcmeta file. It is not combined with dynamic textures. (Basically, when writing GUIs you don't need that combination either.)

The contents are as follows:

Key Possible values Required? (if not, write the size in parentheses) Description
type nine_patch/three_patch/tile/static No (static) Defines which transformation is applied: nine_patch -> nine-patch stretching, three_patch -> fixed ends with repeated middle, tile -> tiling/generic, static -> static, no processing (this corresponds to the StretchType part of the interface I wrote)
default {"width": 16,"hight":16} Yes Defines the default size of this texture; integers suffice. If either width or height written here doesn't match the actual texture size, the texture is stretched to fit the tiling unit's height, and then tiled.
edge Can be an object or an integer Yes; when an integer, >=0 Defines the edge width of this texture; integers suffice. If the integer form is used, it is equivalent to setting all inner values to this value. If it's an object, all four side widths (up/down/left/right) must be written. For three_patch, only the left and right edges need to be defined.
limit Object No; all inner values default to 0 Defines the minimum texture size. If the data is invalid (i.e. the width/height passed into the method < limit), throw TextureStretchLimitException directly
inner See below See below Handling for the interior
will_strech Boolean No (default false) false means the default: no stretching, treated as tiling; true means stretching is applied.
inner.width, inner.height Integer No; default 0 The width/height of one tiling unit. The texture is stretched to fit the tiling unit's width/height, and then tiled. If the width/hight values here, with will_stretch set to false, plus the corresponding direction's width/height exceed the width/hight in default, also throw a TextureStretchLimitException

//User's remark: it's not something where you just know what it does from the input data; it's more like a data marker, marking its properties: what you can do, what you can't do. //User's review: by the way, the method you wrote doesn't seem to define width/height yet, so I wrote it this way. //And you could also implement the content through the built-in interface implementations, but that's a later concern. Not implementing it for now.

Clone this wiki locally