Use hardware coloring for tallgrass and friends
[MineClone/MineClone2.git] / tools / Texture_Converter.py
blob2896092f7d2c813760a4b228f6086919c34cc3f6
1 #!/usr/bin/env python
2 # EXPERIMENTAL texture pack copying utility.
3 # This Python script helps in converting Minecraft texture packs. It has 2 main features:
4 # - Can create a Minetest texture pack (default)
5 # - Can update the MineClone 2 textures
6 # This script is currently incomplete, not all textures are converted.
8 # Requirements:
9 # - Python 3
10 # - Python Library: Pillow
11 # - ImageMagick
13 # Usage (to be simplified later):
14 # - Put extracted texture pack into $HOME/tmp/pp
15 # - Make sure the file “Texture_Conversion_Table.csv” is in the same directory as the script
16 # - Run the script in its directory
17 # - If everything worked, retrieve texture pack in texture_pack/
19 __author__ = "Wuzzy"
20 __license__ = "WTFPL"
21 __status__ = "Development"
23 ### SETTINGS ###
24 # If True, will only make console output but not convert anything.
25 dry_run = False
27 # If True, textures will be put into a texture pack directory structure.
28 # If False, textures will be put into MineClone 2 directories.
29 make_texture_pack = True
31 # If True, prints all copying actions
32 verbose = False
34 ### END OF SETTINGS ###
36 import shutil, csv, os, tempfile
37 from PIL import Image
39 # Helper variables
40 home = os.environ["HOME"]
41 mineclone2_path = home + "/.minetest/games/mineclone2"
42 working_dir = os.getcwd()
43 base_dir = home + "/tmp/pp"
44 tex_dir = base_dir + "/assets/minecraft/textures"
46 # FUNCTION DEFINITIONS
48 def convert_alphatex(one, two, three, four, five):
49 os.system("convert "+one+" -crop 1x1+"+three+" -depth 8 -resize "+four+"x"+four+" "+tempfile1.name)
50 os.system("composite -compose Multiply "+tempfile1.name+" "+two+" "+tempfile2.name)
51 os.system("composite -compose Dst_In "+two+" "+tempfile1.name+" -alpha Set "+five)
53 def target_dir(directory):
54 if make_texture_pack:
55 return working_dir + "/texture_pack"
56 else:
57 return mineclone2_path + directory
59 # Copy texture files
60 def convert_textures():
61 failed_conversions = 0
62 print("Texture conversion BEGINS NOW!")
63 with open("Texture_Conversion_Table.csv", newline="") as csvfile:
64 reader = csv.reader(csvfile, delimiter=",", quotechar='"')
65 first_row = True
66 for row in reader:
67 # Skip first row
68 if first_row:
69 first_row = False
70 continue
72 src_dir = row[0]
73 src_filename = row[1]
74 dst_dir = row[2]
75 dst_filename = row[3]
76 if row[4] != "":
77 xs = int(row[4])
78 ys = int(row[5])
79 xl = int(row[6])
80 yl = int(row[7])
81 xt = int(row[8])
82 yt = int(row[9])
83 else:
84 xs = None
86 src_file = base_dir + src_dir + "/" + src_filename # source file
87 src_file_exists = os.path.isfile(src_file)
88 dst_file = target_dir(dst_dir) + "/" + dst_filename # destination file
90 if src_file_exists == False:
91 print("WARNING: Source file does not exist: "+src_file)
92 failed_conversions = failed_conversions + 1
93 continue
95 if xs != None:
96 # Crop and copy images
97 image = Image.open(src_file)
98 if not dry_run:
99 region = image.crop((xs, ys, xs+xl, ys+yl))
100 region.load()
101 region.save(dst_file)
102 if verbose:
103 print(src_file + " → " + dst_file)
104 else:
105 # Copy image verbatim
106 if not dry_run:
107 shutil.copy2(src_file, dst_file)
108 if verbose:
109 print(src_file + " → " + dst_file)
111 # Convert chest textures (requires ImageMagick)
112 PXSIZE = 16
113 chest_file = tex_dir + "/entity/chest/normal.png"
115 if os.path.isfile(chest_file):
116 CHPX=((PXSIZE / 16 * 14)) # Chests in MC are 2/16 smaller!
118 os.system("convert " + chest_file + " \
119 \( -clone 0 -crop "+str(CHPX)+"x"+str(CHPX)+"+"+str(CHPX)+"+0 \) -geometry +0+0 -composite -extent "+str(CHPX)+"x"+str(CHPX)+" "+target_dir("/mods/ITEMS/mcl_chests/textures")+"/default_chest_top.png")
121 os.system("convert " + chest_file + " \
122 \( -clone 0 -crop "+str(CHPX)+"x"+str((PXSIZE/16)*5)+"+"+str(CHPX)+"+"+str(CHPX)+" \) -geometry +0+0 -composite \
123 \( -clone 0 -crop "+str(CHPX)+"x"+str((PXSIZE/16)*10)+"+"+str(CHPX)+"+"+str((2*CHPX) + ((PXSIZE/16)*5))+" \) -geometry +0+"+str((PXSIZE/16)*5)+" -composite \
124 -extent "+str(CHPX)+"x"+str(CHPX)+" "+target_dir("/mods/ITEMS/mcl_chests/textures")+"/default_chest_front.png")
126 # TODO: Convert other chest sides
128 # Convert grass
129 grass_file = tex_dir + "/blocks/grass_top.png"
130 if os.path.isfile(grass_file):
131 FOLIAG = tex_dir+"/colormap/foliage.png"
132 GRASS = tex_dir+"/colormap/grass.png"
135 # Leaves
136 convert_alphatex(FOLIAG, tex_dir+"/blocks/leaves_oak.png", "70+120", str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/default_leaves.png")
137 convert_alphatex(FOLIAG, tex_dir+"/blocks/leaves_big_oak.png", "70+120", str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/mcl_core_leaves_big_oak.png")
138 convert_alphatex(FOLIAG, tex_dir+"/blocks/leaves_acacia.png", "16+240", str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/default_acacia_leaves.png")
139 convert_alphatex(FOLIAG, tex_dir+"/blocks/leaves_spruce.png", "226+240", str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/mcl_core_leaves_spruce.png")
140 convert_alphatex(FOLIAG, tex_dir+"/blocks/leaves_birch.png", "70+120", str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/mcl_core_leaves_birch.png")
141 convert_alphatex(FOLIAG, tex_dir+"/blocks/leaves_jungle.png", "16+32", str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/default_jungleleaves.png")
143 # Waterlily
144 convert_alphatex(FOLIAG, tex_dir+"/blocks/waterlily.png", "16+32", str(PXSIZE), target_dir("/mods/ITEMS/mcl_flowers/textures")+"/flowers_waterlily.png")
146 # Vines
147 convert_alphatex(FOLIAG, tex_dir+"/blocks/vine.png", "16+32", str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/mcl_core_vine.png")
149 # Tall grass, fern (inventory images)
150 col = "49+172" # Plains grass color
151 convert_alphatex(GRASS, tex_dir+"/blocks/tallgrass.png", col, str(PXSIZE), target_dir("/mods/ITEMS/mcl_flowers/textures")+"/mcl_flowers_tallgrass_inv.png")
152 convert_alphatex(GRASS, tex_dir+"/blocks/fern.png", col, str(PXSIZE), target_dir("/mods/ITEMS/mcl_flowers/textures")+"/mcl_flowers_fern_inv.png")
153 convert_alphatex(GRASS, tex_dir+"/blocks/double_plant_fern_top.png", col, str(PXSIZE), target_dir("/mods/ITEMS/mcl_flowers/textures")+"/mcl_flowers_double_plant_fern_inv.png")
154 convert_alphatex(GRASS, tex_dir+"/blocks/double_plant_grass_top.png", col, str(PXSIZE), target_dir("/mods/ITEMS/mcl_flowers/textures")+"/mcl_flowers_double_plant_grass_inv.png")
156 # TODO: Convert grass palette
158 offset = [
159 [ "49+172", "", "grass" ], # Default grass: Plains
160 [ "0+255", "_dry", "dry_grass" ], # Dry grass: Savanna, Mesa Plateau F, Nether, …
162 for o in offset:
164 os.system("convert "+GRASS+" -crop 1x1+"+o[0]+" -depth 8 -resize "+str(PXSIZE)+"x"+str(PXSIZE)+" "+tempfile1.name)
165 os.system("composite -compose Multiply "+tempfile1.name+" "+tex_dir+"/blocks/grass_top.png "+target_dir("/mods/ITEMS/mcl_core/textures")+"/default_"+o[2]+".png")
166 convert_alphatex(GRASS, tex_dir+"/blocks/grass_side_overlay.png", o[0], str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/default_"+o[2]+"_side.png")
170 # TODO: Convert banner masks
171 # if os.path.isdir(tex_dir + "/entity/banner"):
172 # These are the ImageMagick commands needed to convert the mask images
173 # os.system("mogrify -transparent-color "+filename)
174 # os.system("mogrify -clip-mask "+tex_dir+"/entity/banner/base.png"+" -alpha Copy "+filename)
175 # os.system("mogrify -fill white -colorize 100 "+filename)
177 print("Textures conversion COMPLETE!")
178 if failed_conversions > 0:
179 print("WARNING: Number of missing files in original resource pack: "+str(failed_conversions))
180 print("NOTE: Please keep in mind this script does not reliably convert all the textures yet.")
181 if make_texture_pack:
182 print("You can now retrieve the texture pack in "+working_dir+"/texture_pack/")
184 # ENTRY POINT
185 if make_texture_pack and not os.path.isdir("./texture_pack"):
186 os.mkdir("texture_pack")
188 tempfile1 = tempfile.NamedTemporaryFile()
189 tempfile2 = tempfile.NamedTemporaryFile()
191 convert_textures()
193 tempfile1.close()
194 tempfile2.close()