armory/blender/arm/material/make_texture.py

144 lines
5.5 KiB
Python
Raw Normal View History

2016-12-15 23:50:21 +01:00
import bpy
2017-03-15 12:30:14 +01:00
import os
import arm.log as log
import arm.utils
import arm.assets as assets
import arm.material.mat_state as mat_state
import arm.make_state as state
2017-05-13 17:17:43 +02:00
import shutil
2016-12-15 23:50:21 +01:00
2017-04-22 15:08:44 +02:00
def make(image_node, tex_name, matname=None):
2016-12-15 23:50:21 +01:00
tex = {}
tex['name'] = tex_name
image = image_node.image
2017-02-25 17:13:22 +01:00
if matname == None:
matname = mat_state.material.name
2016-12-15 23:50:21 +01:00
if image == None:
return None
if image.filepath == '':
log.warn(matname + '/' + image.name + ' - file path not found')
return None
# Reference image name
2017-05-13 17:17:43 +02:00
texpath = arm.utils.asset_path(image.filepath)
texfile = arm.utils.extract_filename(image.filepath)
tex['file'] = arm.utils.safestr(texfile)
2016-12-15 23:50:21 +01:00
s = tex['file'].rsplit('.', 1)
if len(s) == 1:
log.warn(matname + '/' + image.name + ' - file extension required for image name')
return None
ext = s[1].lower()
2017-02-15 16:55:46 +01:00
do_convert = ext != 'jpg' and ext != 'png' and ext != 'hdr' and ext != 'mp4' # Convert image
2016-12-15 23:50:21 +01:00
if do_convert:
tex['file'] = tex['file'].rsplit('.', 1)[0] + '.jpg'
# log.warn(matname + '/' + image.name + ' - image format is not (jpg/png/hdr), converting to jpg.')
2017-05-13 17:17:43 +02:00
if image.packed_file != None or not is_ascii(texfile):
# Extract packed data / copy non-ascii texture
2017-05-23 01:03:44 +02:00
unpack_path = arm.utils.get_fp_build() + '/compiled/Assets/unpacked'
2016-12-15 23:50:21 +01:00
if not os.path.exists(unpack_path):
os.makedirs(unpack_path)
unpack_filepath = unpack_path + '/' + tex['file']
if do_convert:
if not os.path.isfile(unpack_filepath):
2017-03-15 12:30:14 +01:00
arm.utils.write_image(image, unpack_filepath)
2017-05-13 17:17:43 +02:00
else:
# Write bytes if size is different or file does not exist yet
if image.packed_file != None:
if not os.path.isfile(unpack_filepath) or os.path.getsize(unpack_filepath) != image.packed_file.size:
with open(unpack_filepath, 'wb') as f:
f.write(image.packed_file.data)
# Copy non-ascii texture
else:
if not os.path.isfile(unpack_filepath) or os.path.getsize(unpack_filepath) != os.path.getsize(texpath):
shutil.copy(texpath, unpack_filepath)
2016-12-15 23:50:21 +01:00
assets.add(unpack_filepath)
else:
2017-05-13 17:17:43 +02:00
if not os.path.isfile(arm.utils.asset_path(image.filepath)):
2017-01-13 11:24:35 +01:00
log.warn('Material ' + matname + '/' + image.name + ' - file not found(' + image.filepath + ')')
2017-01-12 12:11:25 +01:00
return None
2016-12-15 23:50:21 +01:00
if do_convert:
2017-05-23 01:03:44 +02:00
converted_path = arm.utils.get_fp_build() + '/compiled/Assets/unpacked/' + tex['file']
2016-12-15 23:50:21 +01:00
# TODO: delete cache when file changes
if not os.path.isfile(converted_path):
2017-03-15 12:30:14 +01:00
arm.utils.write_image(image, converted_path)
2016-12-15 23:50:21 +01:00
assets.add(converted_path)
else:
# Link image path to assets
2017-02-22 16:55:51 +01:00
# TODO: Khamake converts .PNG to .jpg? Convert ext to lowercase on windows
2017-03-15 12:30:14 +01:00
if arm.utils.get_os() == 'win':
2017-02-22 16:55:51 +01:00
s = image.filepath.rsplit('.', 1)
2017-05-13 17:17:43 +02:00
assets.add(arm.utils.asset_path(s[0] + '.' + s[1].lower()))
2017-02-22 16:55:51 +01:00
else:
2017-05-13 17:17:43 +02:00
assets.add(arm.utils.asset_path(image.filepath))
2016-12-15 23:50:21 +01:00
# if image_format != 'RGBA32':
# tex['format'] = image_format
interpolation = image_node.interpolation
2017-08-21 20:16:06 +02:00
rpdat = arm.utils.get_rp()
texfilter = rpdat.arm_texture_filter
2017-05-19 10:25:59 +02:00
if texfilter == 'Anisotropic':
2016-12-15 23:50:21 +01:00
interpolation = 'Smart'
2017-05-19 10:25:59 +02:00
elif texfilter == 'Linear':
2016-12-15 23:50:21 +01:00
interpolation = 'Linear'
2017-05-19 10:25:59 +02:00
elif texfilter == 'Point':
interpolation = 'Closest'
2017-11-07 02:26:03 +01:00
# if image_node.color_space == NON_COLOR_DATA:
# interpolation = image_node.interpolation
2016-12-15 23:50:21 +01:00
# TODO: Blender seems to load full images on size request, cache size instead
powimage = is_pow(image.size[0]) and is_pow(image.size[1])
2017-05-12 21:49:42 +02:00
if state.target == 'html5' and powimage == False and (image_node.interpolation == 'Cubic' or image_node.interpolation == 'Smart'):
log.warn(matname + '/' + image.name + ' - non power of 2 texture using ' + image_node.interpolation + ' interpolation requires WebGL2')
if interpolation == 'Cubic': # Mipmap linear
tex['mipmap_filter'] = 'linear'
tex['generate_mipmaps'] = True
elif interpolation == 'Smart': # Mipmap anisotropic
tex['min_filter'] = 'anisotropic'
tex['mipmap_filter'] = 'linear'
tex['generate_mipmaps'] = True
2017-05-19 10:25:59 +02:00
elif interpolation == 'Closest':
tex['min_filter'] = 'point'
tex['mag_filter'] = 'point'
# else defaults to linear
2016-12-15 23:50:21 +01:00
if image_node.extension != 'REPEAT': # Extend or clip
tex['u_addressing'] = 'clamp'
tex['v_addressing'] = 'clamp'
else:
if state.target == 'html5' and powimage == False:
2017-05-12 21:49:42 +02:00
log.warn(matname + '/' + image.name + ' - non power of 2 texture using repeat mode requires WebGL2')
# tex['u_addressing'] = 'clamp'
# tex['v_addressing'] = 'clamp'
2016-12-15 23:50:21 +01:00
2017-02-15 16:55:46 +01:00
if image.source == 'MOVIE': # Just append movie texture trait for now
movie_trait = {}
movie_trait['type'] = 'Script'
movie_trait['class_name'] = 'armory.trait.internal.MovieTexture'
movie_trait['parameters'] = [tex['file']]
for o in mat_state.mat_armusers[mat_state.material]:
o['traits'].append(movie_trait)
tex['source'] = 'movie'
tex['file'] = '' # MovieTexture will load the video
2016-12-15 23:50:21 +01:00
return tex
def is_pow(num):
return ((num & (num - 1)) == 0) and num != 0
2017-05-13 17:17:43 +02:00
def is_ascii(s):
return len(s) == len(s.encode())