compat: Environmental colored wisteria leaves

- Uses a new per-texture configuration system that allows customizing block states
- This system also allows defining the texture stitching layout, based on the following template:
1 2 3
4 5 6
7 8 9
This commit is contained in:
Martin Prokoph
2025-03-14 15:31:47 +01:00
parent 9a53699677
commit 723e8d2bc7
28 changed files with 374 additions and 273 deletions

Binary file not shown.

View File

@@ -1,6 +1,6 @@
{
"variants": {
"": [
"half=bottom": [
{
"model": "environmental:block/blue_wisteria_leaves1"
},
@@ -61,6 +61,68 @@
"model": "environmental:block/blue_wisteria_leaves4",
"y": 270
}
],
"half=top": [
{
"model": "environmental:block/blue_wisteria_leaves_top1"
},
{
"model": "environmental:block/blue_wisteria_leaves_top1",
"y": 90
},
{
"model": "environmental:block/blue_wisteria_leaves_top1",
"y": 180
},
{
"model": "environmental:block/blue_wisteria_leaves_top1",
"y": 270
},
{
"model": "environmental:block/blue_wisteria_leaves_top2"
},
{
"model": "environmental:block/blue_wisteria_leaves_top2",
"y": 90
},
{
"model": "environmental:block/blue_wisteria_leaves_top2",
"y": 180
},
{
"model": "environmental:block/blue_wisteria_leaves_top2",
"y": 270
},
{
"model": "environmental:block/blue_wisteria_leaves_top3"
},
{
"model": "environmental:block/blue_wisteria_leaves_top3",
"y": 90
},
{
"model": "environmental:block/blue_wisteria_leaves_top3",
"y": 180
},
{
"model": "environmental:block/blue_wisteria_leaves_top3",
"y": 270
},
{
"model": "environmental:block/blue_wisteria_leaves_top4"
},
{
"model": "environmental:block/blue_wisteria_leaves_top4",
"y": 90
},
{
"model": "environmental:block/blue_wisteria_leaves_top4",
"y": 180
},
{
"model": "environmental:block/blue_wisteria_leaves_top4",
"y": 270
}
]
}
}

View File

@@ -1,66 +0,0 @@
{
"variants": {
"": [
{
"model": "environmental:block/blue_wisteria_leaves_top1"
},
{
"model": "environmental:block/blue_wisteria_leaves_top1",
"y": 90
},
{
"model": "environmental:block/blue_wisteria_leaves_top1",
"y": 180
},
{
"model": "environmental:block/blue_wisteria_leaves_top1",
"y": 270
},
{
"model": "environmental:block/blue_wisteria_leaves_top2"
},
{
"model": "environmental:block/blue_wisteria_leaves_top2",
"y": 90
},
{
"model": "environmental:block/blue_wisteria_leaves_top2",
"y": 180
},
{
"model": "environmental:block/blue_wisteria_leaves_top2",
"y": 270
},
{
"model": "environmental:block/blue_wisteria_leaves_top3"
},
{
"model": "environmental:block/blue_wisteria_leaves_top3",
"y": 90
},
{
"model": "environmental:block/blue_wisteria_leaves_top3",
"y": 180
},
{
"model": "environmental:block/blue_wisteria_leaves_top3",
"y": 270
},
{
"model": "environmental:block/blue_wisteria_leaves_top4"
},
{
"model": "environmental:block/blue_wisteria_leaves_top4",
"y": 90
},
{
"model": "environmental:block/blue_wisteria_leaves_top4",
"y": 180
},
{
"model": "environmental:block/blue_wisteria_leaves_top4",
"y": 270
}
]
}
}

View File

@@ -1,6 +1,6 @@
{
"variants": {
"": [
"half=bottom": [
{
"model": "environmental:block/pink_wisteria_leaves1"
},
@@ -61,6 +61,68 @@
"model": "environmental:block/pink_wisteria_leaves4",
"y": 270
}
],
"half=top": [
{
"model": "environmental:block/pink_wisteria_leaves_top1"
},
{
"model": "environmental:block/pink_wisteria_leaves_top1",
"y": 90
},
{
"model": "environmental:block/pink_wisteria_leaves_top1",
"y": 180
},
{
"model": "environmental:block/pink_wisteria_leaves_top1",
"y": 270
},
{
"model": "environmental:block/pink_wisteria_leaves_top2"
},
{
"model": "environmental:block/pink_wisteria_leaves_top2",
"y": 90
},
{
"model": "environmental:block/pink_wisteria_leaves_top2",
"y": 180
},
{
"model": "environmental:block/pink_wisteria_leaves_top2",
"y": 270
},
{
"model": "environmental:block/pink_wisteria_leaves_top3"
},
{
"model": "environmental:block/pink_wisteria_leaves_top3",
"y": 90
},
{
"model": "environmental:block/pink_wisteria_leaves_top3",
"y": 180
},
{
"model": "environmental:block/pink_wisteria_leaves_top3",
"y": 270
},
{
"model": "environmental:block/pink_wisteria_leaves_top4"
},
{
"model": "environmental:block/pink_wisteria_leaves_top4",
"y": 90
},
{
"model": "environmental:block/pink_wisteria_leaves_top4",
"y": 180
},
{
"model": "environmental:block/pink_wisteria_leaves_top4",
"y": 270
}
]
}
}

View File

@@ -1,66 +0,0 @@
{
"variants": {
"": [
{
"model": "environmental:block/pink_wisteria_leaves_top1"
},
{
"model": "environmental:block/pink_wisteria_leaves_top1",
"y": 90
},
{
"model": "environmental:block/pink_wisteria_leaves_top1",
"y": 180
},
{
"model": "environmental:block/pink_wisteria_leaves_top1",
"y": 270
},
{
"model": "environmental:block/pink_wisteria_leaves_top2"
},
{
"model": "environmental:block/pink_wisteria_leaves_top2",
"y": 90
},
{
"model": "environmental:block/pink_wisteria_leaves_top2",
"y": 180
},
{
"model": "environmental:block/pink_wisteria_leaves_top2",
"y": 270
},
{
"model": "environmental:block/pink_wisteria_leaves_top3"
},
{
"model": "environmental:block/pink_wisteria_leaves_top3",
"y": 90
},
{
"model": "environmental:block/pink_wisteria_leaves_top3",
"y": 180
},
{
"model": "environmental:block/pink_wisteria_leaves_top3",
"y": 270
},
{
"model": "environmental:block/pink_wisteria_leaves_top4"
},
{
"model": "environmental:block/pink_wisteria_leaves_top4",
"y": 90
},
{
"model": "environmental:block/pink_wisteria_leaves_top4",
"y": 180
},
{
"model": "environmental:block/pink_wisteria_leaves_top4",
"y": 270
}
]
}
}

View File

@@ -1,6 +1,6 @@
{
"variants": {
"": [
"half=bottom": [
{
"model": "environmental:block/purple_wisteria_leaves1"
},
@@ -61,6 +61,68 @@
"model": "environmental:block/purple_wisteria_leaves4",
"y": 270
}
],
"half=top": [
{
"model": "environmental:block/purple_wisteria_leaves_top1"
},
{
"model": "environmental:block/purple_wisteria_leaves_top1",
"y": 90
},
{
"model": "environmental:block/purple_wisteria_leaves_top1",
"y": 180
},
{
"model": "environmental:block/purple_wisteria_leaves_top1",
"y": 270
},
{
"model": "environmental:block/purple_wisteria_leaves_top2"
},
{
"model": "environmental:block/purple_wisteria_leaves_top2",
"y": 90
},
{
"model": "environmental:block/purple_wisteria_leaves_top2",
"y": 180
},
{
"model": "environmental:block/purple_wisteria_leaves_top2",
"y": 270
},
{
"model": "environmental:block/purple_wisteria_leaves_top3"
},
{
"model": "environmental:block/purple_wisteria_leaves_top3",
"y": 90
},
{
"model": "environmental:block/purple_wisteria_leaves_top3",
"y": 180
},
{
"model": "environmental:block/purple_wisteria_leaves_top3",
"y": 270
},
{
"model": "environmental:block/purple_wisteria_leaves_top4"
},
{
"model": "environmental:block/purple_wisteria_leaves_top4",
"y": 90
},
{
"model": "environmental:block/purple_wisteria_leaves_top4",
"y": 180
},
{
"model": "environmental:block/purple_wisteria_leaves_top4",
"y": 270
}
]
}
}

View File

@@ -1,66 +0,0 @@
{
"variants": {
"": [
{
"model": "environmental:block/purple_wisteria_leaves_top1"
},
{
"model": "environmental:block/purple_wisteria_leaves_top1",
"y": 90
},
{
"model": "environmental:block/purple_wisteria_leaves_top1",
"y": 180
},
{
"model": "environmental:block/purple_wisteria_leaves_top1",
"y": 270
},
{
"model": "environmental:block/purple_wisteria_leaves_top2"
},
{
"model": "environmental:block/purple_wisteria_leaves_top2",
"y": 90
},
{
"model": "environmental:block/purple_wisteria_leaves_top2",
"y": 180
},
{
"model": "environmental:block/purple_wisteria_leaves_top2",
"y": 270
},
{
"model": "environmental:block/purple_wisteria_leaves_top3"
},
{
"model": "environmental:block/purple_wisteria_leaves_top3",
"y": 90
},
{
"model": "environmental:block/purple_wisteria_leaves_top3",
"y": 180
},
{
"model": "environmental:block/purple_wisteria_leaves_top3",
"y": 270
},
{
"model": "environmental:block/purple_wisteria_leaves_top4"
},
{
"model": "environmental:block/purple_wisteria_leaves_top4",
"y": 90
},
{
"model": "environmental:block/purple_wisteria_leaves_top4",
"y": 180
},
{
"model": "environmental:block/purple_wisteria_leaves_top4",
"y": 270
}
]
}
}

View File

@@ -1,6 +1,6 @@
{
"variants": {
"": [
"half=bottom": [
{
"model": "environmental:block/white_wisteria_leaves1"
},
@@ -61,6 +61,68 @@
"model": "environmental:block/white_wisteria_leaves4",
"y": 270
}
],
"half=top": [
{
"model": "environmental:block/white_wisteria_leaves_top1"
},
{
"model": "environmental:block/white_wisteria_leaves_top1",
"y": 90
},
{
"model": "environmental:block/white_wisteria_leaves_top1",
"y": 180
},
{
"model": "environmental:block/white_wisteria_leaves_top1",
"y": 270
},
{
"model": "environmental:block/white_wisteria_leaves_top2"
},
{
"model": "environmental:block/white_wisteria_leaves_top2",
"y": 90
},
{
"model": "environmental:block/white_wisteria_leaves_top2",
"y": 180
},
{
"model": "environmental:block/white_wisteria_leaves_top2",
"y": 270
},
{
"model": "environmental:block/white_wisteria_leaves_top3"
},
{
"model": "environmental:block/white_wisteria_leaves_top3",
"y": 90
},
{
"model": "environmental:block/white_wisteria_leaves_top3",
"y": 180
},
{
"model": "environmental:block/white_wisteria_leaves_top3",
"y": 270
},
{
"model": "environmental:block/white_wisteria_leaves_top4"
},
{
"model": "environmental:block/white_wisteria_leaves_top4",
"y": 90
},
{
"model": "environmental:block/white_wisteria_leaves_top4",
"y": 180
},
{
"model": "environmental:block/white_wisteria_leaves_top4",
"y": 270
}
]
}
}

View File

@@ -1,66 +0,0 @@
{
"variants": {
"": [
{
"model": "environmental:block/white_wisteria_leaves_top1"
},
{
"model": "environmental:block/white_wisteria_leaves_top1",
"y": 90
},
{
"model": "environmental:block/white_wisteria_leaves_top1",
"y": 180
},
{
"model": "environmental:block/white_wisteria_leaves_top1",
"y": 270
},
{
"model": "environmental:block/white_wisteria_leaves_top2"
},
{
"model": "environmental:block/white_wisteria_leaves_top2",
"y": 90
},
{
"model": "environmental:block/white_wisteria_leaves_top2",
"y": 180
},
{
"model": "environmental:block/white_wisteria_leaves_top2",
"y": 270
},
{
"model": "environmental:block/white_wisteria_leaves_top3"
},
{
"model": "environmental:block/white_wisteria_leaves_top3",
"y": 90
},
{
"model": "environmental:block/white_wisteria_leaves_top3",
"y": 180
},
{
"model": "environmental:block/white_wisteria_leaves_top3",
"y": 270
},
{
"model": "environmental:block/white_wisteria_leaves_top4"
},
{
"model": "environmental:block/white_wisteria_leaves_top4",
"y": 90
},
{
"model": "environmental:block/white_wisteria_leaves_top4",
"y": 180
},
{
"model": "environmental:block/white_wisteria_leaves_top4",
"y": 270
}
]
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 918 B

After

Width:  |  Height:  |  Size: 1016 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 912 B

After

Width:  |  Height:  |  Size: 1005 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 922 B

After

Width:  |  Height:  |  Size: 1015 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 876 B

After

Width:  |  Height:  |  Size: 949 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 918 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 912 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 922 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 876 B

View File

@@ -20,6 +20,17 @@ def printCyan(out): print("\033[96m{}\033[00m" .format(out))
def printOverride(out): print(" -> {}".format(out))
def dumpJson(data, f): json.dump(data, f, separators=(',', ':')) if minify else json.dump(data, f, indent=4)
class BlockStateData:
def __init__(self, namespace, block_name, state):
self.namespace = namespace
self.block_name = block_name
self.state = state
def fromFile(leaf, root, infile):
with open(os.path.join(root, infile), "r") as f:
printOverride("Loading blockstate data from: "+f.name)
return BlockStateData.fromJson(leaf, json.load(f).get("blockStateData"))
def fromJson(leaf, data): return BlockStateData(data["block"].split(":")[0], data["block"].split(":")[1], data["state"]) if "block" in data else BlockStateData(leaf.getId().split(":")[0], leaf.getId().split(":")[1], data["state"])
class LeafBlock:
def __init__(self, namespace, block_name, texture_name):
self.namespace = namespace
@@ -36,6 +47,7 @@ class LeafBlock:
block_id_override = None
texture_id_override = None
dynamictrees_namespace = None
blockstate_data = None
def getId(self):
if (self.block_id_override != None): return self.block_id_override
return self.namespace+":"+self.block_name
@@ -139,6 +151,10 @@ def autoGen(jsonData, args):
leaf.should_generate_item_model = True
printOverride("Also generating item model")
# Check for blockstate data
if infile.replace(".png", ".betterleaves.json") in files:
leaf.blockstate_data = BlockStateData.fromFile(leaf, root, infile.replace(".png", ".betterleaves.json"))
# Generate blockstates & models
generateBlockstate(leaf, block_state_copies)
generateBlockModels(leaf)
@@ -216,6 +232,29 @@ def generateTexture(root, infile, useProgrammerArt=False):
outfolder = root.replace("assets", "").replace("input", "assets")
os.makedirs(outfolder, exist_ok=True)
# Check for texture stitching data
textureMap = {}
if os.path.isfile(os.path.join(root, infile.replace(".png", ".betterleaves.json"))):
with open(os.path.join(root, infile.replace(".png", ".betterleaves.json")), "r") as f:
json_data = json.load(f)
if "textureStitching" in json_data:
printOverride("Using texture stitching data from: " + f.name)
# Create texture map from stitching data
for key, value in json_data["textureStitching"].items():
if "-" in key:
for i in range(int(key.split("-")[0]), int(key.split("-")[1])+1): textureMap[str(i)] = value
else: textureMap[key] = value
# Turn texture map into absolute paths
for key, value in textureMap.items():
textureRoot = f"./input/assets/{value.split(":")[0]}/textures/"
textureFile = value.split(":")[1] + ".png"
if "/" in textureFile:
textureRoot += textureFile.rsplit("/")[0]
textureFile = textureFile.rsplit("/")[1]
textureRoot = scanPacksForTexture(textureRoot, textureFile)
if useProgrammerArt: root = scanPacksForTexture(textureRoot, textureFile, "./input/programmer_art")
textureMap[key] = os.path.join(textureRoot, textureFile)
root = scanPacksForTexture(root, infile)
if useProgrammerArt: root = scanPacksForTexture(root, infile, "./input/programmer_art")
@@ -232,7 +271,11 @@ def generateTexture(root, infile, useProgrammerArt=False):
# Now we paste the regular texture in a 3x3 grid, centered in the middle
for x in range(-1, 2):
for y in range(-1, 2):
out.paste(vanilla, (int(width / 2 + width * x), int(height / 2 + height * y)))
texture = vanilla
index = (x + 2) + (y + 1) * 3 # Turns coordinates into a number from 1 to 9
if str(index) in textureMap: # Load texture from texture stitching map
texture = Image.open(textureMap[str(index)])
out.paste(texture, (int(width / 2 + width * x), int(height / 2 + height * y)))
# As the last step, we apply our custom mask to round the edges and smoothen things out
mask = Image.open('input/mask.png').convert('L').resize(out.size, resample=Image.NEAREST)
@@ -248,19 +291,33 @@ def generateBlockstate(leaf, block_state_copies):
mod_namespace = leaf.getId().split(":")[0]
block_name = leaf.getId().split(":")[1]
block_state_namespace = mod_namespace
block_state_name = block_name
state = ""
if leaf.blockstate_data != None: # In case custom blockstate data is defined
block_state_namespace = leaf.blockstate_data.namespace
block_state_name = leaf.blockstate_data.block_name
state = leaf.blockstate_data.state
# Create structure for blockstate file
block_state_file = f"assets/{mod_namespace}/blockstates/{block_name}.json"
block_state_file = f"assets/{block_state_namespace}/blockstates/{block_state_name}.json"
block_state_data = {
"variants": {
"": []
f"{state}": []
}
}
if os.path.exists(block_state_file): # In case the blockstate file already exists, we want to add to it
with open(block_state_file, "r") as f:
block_state_data = json.load(f)
block_state_data["variants"][state] = []
# Add four rotations for each of the four individual leaf models
for i in range(1, 5):
block_state_data["variants"][""] += { "model": f"{mod_namespace}:block/{block_name}{i}" }, { "model": f"{mod_namespace}:block/{block_name}{i}", "y": 90 }, { "model": f"{mod_namespace}:block/{block_name}{i}", "y": 180 }, { "model": f"{mod_namespace}:block/{block_name}{i}", "y": 270 },
block_state_data["variants"][state] += { "model": f"{mod_namespace}:block/{block_name}{i}" }, { "model": f"{mod_namespace}:block/{block_name}{i}", "y": 90 }, { "model": f"{mod_namespace}:block/{block_name}{i}", "y": 180 }, { "model": f"{mod_namespace}:block/{block_name}{i}", "y": 270 },
# Create blockstates folder if it doesn't exist already
os.makedirs("assets/{}/blockstates/".format(mod_namespace), exist_ok=True)
os.makedirs("assets/{}/blockstates/".format(block_state_namespace), exist_ok=True)
# Write blockstate file
with open(block_state_file, "w") as f:

View File

@@ -0,0 +1,5 @@
{
"blockStateData": {
"state": "half=bottom"
}
}

View File

@@ -0,0 +1,10 @@
{
"blockStateData": {
"block": "environmental:blue_wisteria_leaves",
"state": "half=top"
},
"textureStitching": {
"1-3": "environmental:block/wisteria_leaves",
"7-9": "environmental:block/blue_wisteria_leaves"
}
}

View File

@@ -0,0 +1,5 @@
{
"blockStateData": {
"state": "half=bottom"
}
}

View File

@@ -0,0 +1,10 @@
{
"blockStateData": {
"block": "environmental:pink_wisteria_leaves",
"state": "half=top"
},
"textureStitching": {
"1-3": "environmental:block/wisteria_leaves",
"7-9": "environmental:block/pink_wisteria_leaves"
}
}

View File

@@ -0,0 +1,5 @@
{
"blockStateData": {
"state": "half=bottom"
}
}

View File

@@ -0,0 +1,10 @@
{
"blockStateData": {
"block": "environmental:purple_wisteria_leaves",
"state": "half=top"
},
"textureStitching": {
"1-3": "environmental:block/wisteria_leaves",
"7-9": "environmental:block/purple_wisteria_leaves"
}
}

View File

@@ -0,0 +1,5 @@
{
"blockStateData": {
"state": "half=bottom"
}
}

View File

@@ -0,0 +1,10 @@
{
"blockStateData": {
"block": "environmental:white_wisteria_leaves",
"state": "half=top"
},
"textureStitching": {
"1-3": "environmental:block/wisteria_leaves",
"7-9": "environmental:block/white_wisteria_leaves"
}
}