@ -3,23 +3,52 @@ import os
from expertmm import *
from minetestinfo import * #paths and FLAG_EMPTY_HEXCOLOR = "#010000"
from PIL import Image , ImageDraw , ImageFont , ImageColor
import shutil
u_skins_mod_path = " C: \\ Users \\ jgustafson \\ Desktop \\ Backup \\ fcalocal \\ usr \\ local \\ share \\ minetest \\ games \\ fca_game_a \\ mods \\ u_skins \\ u_skins "
u_skins_mod_path = os . path . join ( profile_path , " Desktop \\ Backup \\ fcalocal \\ usr \\ local \\ share \\ minetest \\ games \\ fca_game_a \\ mods \\ u_skins \\ u_skins " )
games_path = os . path . join ( minetestinfo . get_var ( " shared_minetest_path " ) , " games " )
verbose_enable = True
image_size = ( 64 , 32 )
preview_size = ( 16 , 32 )
visual_debug_enable = False
dump_path = os . path . join ( u_skins_mod_path , " debug " ) # only created or used if visual_debug_enable
world_path = None
world_name = None
if minetestinfo . contains ( " primary_world_path " ) :
world_path = minetestinfo . get_var ( " primary_world_path " )
world_name = os . path . basename ( world_path )
print ( " Using world ' " + world_name + " ' " )
#game_name = game_path_from_gameid_dict(
gameid = None
game_path = None
mods_path = None
if not os . path . isdir ( u_skins_mod_path ) :
if world_path is not None and os . path . isdir ( world_path ) :
gameid = get_world_var ( " gameid " )
print ( " Using game ' " + str ( gameid ) + " ' " )
if gameid is not None and games_path is not None :
game_path = os . path . join ( games_path , gameid )
mods_path = os . path . join ( game_path , " mods " )
print ( " Using mods_path ' " + mods_path + " ' " )
print ( " Looking for u_skins mod in u_skins modpack... " )
u_skins_mod_path = os . path . join ( os . path . join ( os . path . join ( game_path , " mods " ) , " u_skins " ) , " u_skins " ) # get the u_skins mod in the u_skins modpack
print ( " trying ' " + u_skins_mod_path + " ' " )
#u_skins_mod_path = os.path.join( os.path.join( os.path.join(game_path, "mods"), "u_skins" ), "u_skins" ) # get the u_skins mod in the u_skins modpack
#print(" trying '"+u_skins_mod_path+"'")
u_skins_modpack_path = os . path . join ( mods_path , " u_skins " )
u_skins_mod_path = os . path . join ( u_skins_modpack_path , " u_skins " )
else :
print ( " Unknown world, so can ' t detect game. " )
meta_path = os . path . join ( u_skins_mod_path , " meta " )
textures_path = os . path . join ( u_skins_mod_path , " textures " )
in_path = " C: \\ Users \\ jgustafson \\ Downloads \\ skins-to-add "
image_prefix = " character_ "
preview_suffix = " _preview "
default_license = " CC BY-SA 3.0 "
default_license_string = " CC BY-SA 3.0 "
if not os . path . isdir ( in_path ) :
in_path = " . "
print ( " Looking for new textures in current directory " )
png_count = 0
@ -44,8 +73,6 @@ rect_trans_list.append(RectTransferInfo((4,20,4,12),(8,20,4,12),False)) # leg.l
rect_trans_list . append ( RectTransferInfo ( ( 4 , 20 , 4 , 12 ) , ( 4 , 20 , 4 , 12 ) , True ) ) # leg.r (True since on legs, right one must be flipped manually)
#yes, the flipping is different for leg vs arm
image_size = ( 64 , 32 )
preview_size = ( 16 , 32 )
class USkinInfo :
author_string = None
@ -60,16 +87,18 @@ class USkinInfo:
pass
def set_from_skindb_skin_file_path ( self , file_path , license_name_string ) :
self . author_string = None
self . name_string = None
self . license_name_string = license_name_string
self . source_image_path = file_path
file_name = os . path . basename ( self . source_image_path )
self . license_name_string = license_name_string
noext_name = file_name
dot_index = file_name . rfind ( " . " )
if dot_index > = 0 :
noext_name = file_name [ : dot_index ]
by_string = " _by_ "
by_index = noext_name . rfind ( by_string )
print ( " noext_name: " + noext_name )
#print("noext_name:"+noext_name )
if by_index > = 0 :
self . author_string = noext_name [ by_index + len ( by_string ) : ]
self . name_string = noext_name [ : by_index ]
@ -77,24 +106,56 @@ class USkinInfo:
self . author_string = " <unknown> "
self . name_string = noext_name
def set_from_metadata_path ( self , metadata_file_path ) :
is_ok = False
self . name_string = None
self . author_string = None
self . license_name_string = None
if os . path . isfile ( metadata_file_path ) :
ins = open ( metadata_file_path , ' r ' )
line = True
counting_number = 1
while line :
participle = " reading line " + str ( counting_number )
line = ins . readline ( )
if line :
line_strip = line . strip ( )
if len ( line_strip ) > 0 :
if self . name_string is None :
self . name_string = line_strip
elif self . author_string is None :
self . author_string = line_strip
is_ok = True
elif self . license_name_string is None :
self . license_name_string = line_strip
counting_number + = 1
ins . close ( )
if not is_ok :
raw_input ( " ERROR: Did not find line 2 for name_string in ' " + metadata_file_path + " ' " )
else :
raw_input ( " Missing ' " + metadata_file_path + " ' -- press enter to continue... " )
return is_ok
def print_dump ( self , min_indent ) :
print ( min_indent + " author_string: " + self . author_string )
print ( min_indent + " name_string: " + self . name_string )
print ( min_indent + " author_string: " + self . license_name_string )
print ( min_indent + " author_string: " + self . author_string )
print ( min_indent + " license_name_string: " + self . license_name_string )
def _save_metadata ( self , metadata_file_path ) :
outs = open ( metadata_file_path , ' w ' )
outs . write ( self . author_string + " \n " )
outs . write ( self . name_string + " \n " )
outs . write ( self . author_string + " \n " )
outs . write ( self . license_name_string + " \n " )
outs . close ( )
def push_next_skin_file ( self ) :
def push_next_skin_file_if_self_is_new ( self ) :
result = False
os . listdir ( textures_path )
this_index = 1
while os . path . isfile ( get_png_path_from_index ( this_index ) ) :
this_index + = 1
if not skin_exists ( self . name_string , self . author_string ) :
#image_name = get_png_name_from_index(this_index)
image_path = get_png_path_from_index ( this_index )
metadata_name = get_metadata_name_from_index ( this_index )
@ -102,12 +163,14 @@ class USkinInfo:
#preview_name = get_preview_name_from_index(this_index)
preview_path = get_preview_path_from_index ( this_index )
print ( " saving to image_path: " + image_path )
print ( " saving to preview_path: " + preview_path )
print ( " saving to metadata_path: " + metadata_path )
self . _save_metadata ( metadata_path )
#actually save the skin and metadata files:
print ( " Not yet implemented. " )
print ( " saving to preview_path: " + preview_path )
self . print_dump ( " " )
shutil . copy ( self . source_image_path , image_path )
result = True
preview_im = Image . new ( " RGBA " , preview_size , " #000000 " )
fill_image_with_transparency ( preview_im )
skin_im = Image . open ( open ( self . source_image_path , ' rb ' ) ) # double-open to make sure file is finished writing
@ -117,13 +180,80 @@ class USkinInfo:
#im.load() # make sure PIL has read the data
#fp.close()
for rect_trans in rect_trans_list :
partial_im = skin_im . crop ( rect_trans . source_rect_tuple )
left , top , right , bottom = rect_trans . dest_rect_tuple
preview_im . paste ( partial_im , ( left , top ) )
source_left , source_top , source_right , source_bottom = rect_trans . source_rect_tuple
source_right + = source_left
source_bottom + = source_top
pil_source_rect_tuple = source_left , source_top , source_right , source_bottom
partial_im = skin_im . crop ( pil_source_rect_tuple )
dest_left , dest_top , dest_right , dest_bottom = rect_trans . dest_rect_tuple
dest_right + = dest_left
dest_bottom + = dest_top
pil_dest_rect_tuple = dest_left , dest_top , dest_right , dest_bottom
preview_im . paste ( partial_im , ( dest_left , dest_top ) )
debug_img_name = " debug " + str ( pil_source_rect_tuple ) + " .png "
if visual_debug_enable :
#if visual_debug_enable:
#raw_input("Press enter to save temp cropping images to '"+dump_path+"'")
if not os . path . isdir ( dump_path ) :
os . makedirs ( dump_path )
debug_img_path = os . path . join ( dump_path , debug_img_name )
#if not os.path.isfile(debug_img_path):
print ( " saving " + debug_img_path )
print ( " (after pasting to destination rect " + str ( pil_dest_rect_tuple ) + " ) " )
partial_im . save ( debug_img_path )
preview_im . save ( preview_path )
print ( " Saved preview to ' " + preview_path + " ' " )
print ( " " )
else :
print ( " Skin already exists: " + self . name_string + " by " + self . author_string )
def get_png_path_from_index ( this_index ) :
return os . path . join ( textures_path , get_png_name_from_index ( this_index ) )
def get_png_name_from_index ( this_index ) :
return image_prefix + str ( this_index ) + " .png "
def get_preview_path_from_index ( this_index ) :
return os . path . join ( textures_path , get_preview_name_from_index ( this_index ) )
def get_preview_name_from_index ( this_index ) :
return image_prefix + str ( this_index ) + preview_suffix + " .png "
def get_metadata_name_from_index ( this_index ) :
return image_prefix + str ( this_index ) + " .txt "
def get_metadata_path_from_index ( this_index ) :
return os . path . join ( meta_path , get_metadata_name_from_index ( this_index ) )
print ( " Loading existing skin metadata to avoid duplication (but ignoring metadata files that do not have pngs) " )
si_list = list ( )
this_index = 1
while os . path . isfile ( get_png_path_from_index ( this_index ) ) :
existing_metadata_path = get_metadata_path_from_index ( this_index )
this_si = USkinInfo ( )
is_ok = this_si . set_from_metadata_path ( get_metadata_path_from_index ( this_index ) )
if is_ok :
#if not skin_exists(this_si.name_string, this_si.author_string):
si_list . append ( this_si )
#if verbose_enable:
# print("Added skin metadata:")
# this_si.print_dump(" ")
this_index + = 1
print ( " Found metadata for " + str ( len ( si_list ) ) + " png file(s). " )
print ( " The functions in " + __file__ + " are now ready. " )
print ( " * These functions mark destination as ' " + default_license_string + " ' license unless you " )
print ( " first change the global default_license_string variable " )
print ( " in your program that has: " )
print ( " from u_skin_adder import * " )
print ( " * Skin filename should include _by_ (with underscores) to specify author. " )
print ( " * Examples: " )
print ( " load_new_skins_from_folder(folder_path) " )
print ( " add_skin_if_new(file_path) " )
def fill_image_with_transparency ( im ) :
#modified version of: unutbu. "Python PIL: how to make area transparent in PNG? (answer 7 Dec 2010 at 19:08)" <http://stackoverflow.com/questions/4379978/python-pil-how-to-make-area-transparent-in-png>. 7 Dec 2010. 8 Apr 2016.
@ -141,38 +271,80 @@ def fill_image_with_transparency(im):
im . putalpha ( mask )
#im.save('/tmp/output.png')
def get_png_path_from_index ( this_index ) :
return os . path . join ( textures_path , get_png_name_from_index ( this_index ) )
def get_png_name_from_index ( this_index ) :
return image_prefix + str ( this_index ) + " .png "
show_no_dest_warnings = True
def skin_exists ( name_string , author_string ) :
global show_no_dest_warnings
#global si_list
result = False
count = 0
#if verbose_enable:
# print(" Checking for existing "+name_string+" by "+author_string+":")
for si in si_list :
if si . name_string == name_string and si . author_string == author_string :
result = True
break
#else:
# if verbose_enable:
# print(" "+si.name_string+" by "+si.author_string+" is not it.")
count + = 1
if not result :
if count < 1 :
#if show_no_dest_warnings:
raw_input ( " WARNING: 0 skins during skin_exists check. Press enter to continue... " )
#show_no_dest_warnings = False
return result
def get_preview_path_from_index ( this_index ) :
return os . path . join ( textures_path , get_preview_name_from_index ( this_index ) )
def get_preview_name_from_index ( this_index ) :
return image_prefix + str ( this_index ) + preview_suffix + " .png "
def get_metadata_name_from_index ( this_index ) :
return image_prefix + str ( this_index ) + " .txt "
#if os.path.isdir(meta_path):
#
#accepts CC BY 3.0 skins, and looks for _by_ in name, followed by author (otherwise puts <unknown> on author line of metadata txt file in u_skin/meta folder)
def add_skin_if_new ( sub_path ) :
this_usi = USkinInfo ( )
this_usi . set_from_skindb_skin_file_path ( sub_path , default_license_string )
return this_usi . push_next_skin_file_if_self_is_new ( )
if os . path . isdir ( meta_path ) :
def load_new_skins_from_folder ( in_path ) :
#in_path = os.path.join(profile_path,"Downloads\\skins-to-add")
#if not os.path.isdir(in_path):
# in_path = "."
# print("Looking for new textures in current directory")
if not skin_exists ( " Sam 0 " , " Jordach " ) :
print ( " " )
print ( " WARNING: Missing ' Sam 0 ' by ' Jordach ' " )
print ( " among " + str ( len ( si_list ) ) + " skin(s). " )
print ( " Only continue if you expected that skin to not be there. " )
raw_input ( " Press enter to continue... " )
if os . path . isdir ( meta_path ) :
if os . path . isdir ( textures_path ) :
if os . path . isdir ( in_path ) :
folder_path = in_path
new_count = 0
found_count = 0
old_count = 0
for sub_name in os . listdir ( folder_path ) :
sub_path = os . path . join ( folder_path , sub_name )
if os . path . isfile ( sub_path ) :
if ( sub_name [ : 1 ] != " . " ) :
if len ( sub_name ) > 4 and sub_name [ - 4 : ] == " .png " :
this_usi = USkinInfo ( )
this_usi . set_from_skindb_skin_file_path ( sub_path , default_license )
this_usi . push_next_skin_file ( )
found_count + = 1
if add_skin_if_new ( sub_path ) :
new_count + = 1
else :
old_count + = 1
print ( " Added " + str ( new_count ) + " new skins(s) among " + str ( found_count ) + " discovered in specified source folder. " )
if old_count > 0 :
print ( " " + str ( old_count ) + " (with matching author and title) were already in destination. " )
else :
print ( " ERROR: Failed to get new texture files since in_path does not exist: ' " + in_path + " ' " )
else :
print ( " ERROR: missing textures_path (tried ' " + textures_path + " ' ) " )
else :
else :
print ( " ERROR: missing meta_path (tried ' " + meta_path + " ' ) " )
input ( " Press return to exit. " )
#raw_input("Press return to exit." )