@ -45,10 +45,11 @@ class _Texture:
else :
self . layer = kwargs . get ( " layer " )
self . calc_alpha = False
self . mipmap = False
self . mipmap = kwargs . get ( " mipmap " , False )
if kwargs . get ( " is_detail_map " , False ) :
self . is_detail_map = True
self . mipmap = True
self . detail_blend = kwargs [ " detail_blend " ]
self . detail_fade_start = kwargs [ " detail_fade_start " ]
self . detail_fade_stop = kwargs [ " detail_fade_stop " ]
@ -56,6 +57,7 @@ class _Texture:
self . detail_opacity_stop = kwargs [ " detail_opacity_stop " ]
self . calc_alpha = False
self . use_alpha = True
self . allowed_formats = { " DDS " }
else :
self . is_detail_map = False
use_alpha = kwargs . get ( " use_alpha " )
@ -66,7 +68,20 @@ class _Texture:
self . use_alpha = ( image . channels == 4 and image . use_alpha )
else :
self . use_alpha = use_alpha
self . allowed_formats = kwargs . get ( " allowed_formats " ,
{ " DDS " } if self . mipmap else { " PNG " , " JPG " } )
# Basic format sanity
if self . mipmap :
assert " DDS " in self . allowed_formats
if len ( self . allowed_formats ) == 1 :
self . auto_ext = next ( iter ( self . allowed_formats ) ) . lower ( )
elif self . mipmap :
self . auto_ext = " dds "
else :
self . auto_ext = " hsm "
self . extension = kwargs . get ( " extension " , self . auto_ext )
self . image = image
def __eq__ ( self , other ) :
@ -83,10 +98,10 @@ class _Texture:
return hash ( str ( self ) )
def __str__ ( self ) :
if self . mipmap :
name = str ( Path ( self . image . name ) . with_suffix ( " .dds " ) )
if self . extension is None :
name = self . image . name
else :
name = str ( Path ( self . image . name ) . with_suffix ( " .bmp " ) )
name = str ( Path ( self . image . name ) . with_suffix ( " . {} " . format ( self . extension ) ) )
if self . calc_alpha :
name = " ALPHAGEN_ {} " . format ( name )
@ -558,6 +573,7 @@ class MaterialConverter:
""" Exports a Blender ImageTexture to a plLayer """
texture = slot . texture
layer_props = texture . plasma_layer
mipmap = texture . use_mipmap
# Does the image have any alpha at all?
if texture . image is not None :
@ -598,7 +614,7 @@ class MaterialConverter:
layer . texture = dtm . key
else :
detail_blend = TEX_DETAIL_ALPHA
if layer_props . is_detail_map and texture . use_ mipmap:
if layer_props . is_detail_map and mipmap :
if slot . blend_type == " ADD " :
detail_blend = TEX_DETAIL_ADD
elif slot . blend_type == " MULTIPLY " :
@ -608,38 +624,55 @@ class MaterialConverter:
if layer_props . is_detail_map and not state . blendFlags & hsGMatState . kBlendMask :
state . blendFlags | = hsGMatState . kBlendDetail
key = _Texture ( texture = texture , use_alpha = has_alpha , force_calc_alpha = slot . use_stencil ,
is_detail_map = layer_props . is_detail_map , detail_blend = detail_blend ,
detail_fade_start = layer_props . detail_fade_start , detail_fade_stop = layer_props . detail_fade_stop ,
detail_opacity_start = layer_props . detail_opacity_start , detail_opacity_sto p= layer_props . detail_opacity_stop )
if key not in self . _pending :
self . _report . msg ( " Stashing ' {} ' for conversion as ' {} ' " ,
texture . image . name , str ( key ) , indent = 3 )
self . _pending [ key ] = [ layer . key , ]
else :
self . _report . msg ( " Found another user of ' {} ' " , texture . image . name , indent = 3 )
self . _pending [ key ] . append ( layer . key )
allowed_formats = { " DDS " } if mipmap else { " PNG " , " BMP " }
self . export_prepared_image ( texture = texture , owner = layer ,
use_alpha = has_alpha , force_calc_alpha = slot . use_stencil ,
is_detail_ma p = layer_props . is_detail_map ,
detail_blend = detail_blend ,
detail_fade_start = layer_props . detail_fade_start ,
detail_fade_stop = layer_props . detail_fade_stop ,
detail_opacity_start = layer_props . detail_opacity_start ,
detail_opacity_stop = layer_props . detail_opacity_stop ,
mipmap = mipmap , allowed_formats = allowed_formats ,
indent = 3 )
def _export_texture_type_none ( self , bo , layer , texture ) :
# We'll allow this, just for sanity's sake...
pass
def export_prepared_layer ( self , layer , image ) :
""" This exports an externally prepared layer and image """
key = _Texture ( image = image )
def export_prepared_image ( self , * * kwargs ) :
""" This exports an externally prepared image and an optional owning layer.
The following arguments are typical :
- texture : ( co - required ) the image texture datablock to export
- image : ( co - required ) the image datablock to export
- owner : ( required ) the Plasma object using this image
- mipmap : ( optional ) should the image be mipmapped ?
- allowed_formats : ( optional ) set of string * hints * for desired image export type
valid options : BMP , DDS , JPG , PNG
- extension : ( optional ) file extension to use for the image object
to use the image datablock extension , set this to None
- indent : ( optional ) indentation level for log messages
default : 2
"""
owner = kwargs . pop ( " owner " , None )
indent = kwargs . pop ( " indent " , 2 )
key = _Texture ( * * kwargs )
image = key . image
if key not in self . _pending :
self . _report . msg ( " Stashing ' {} ' for conversion as ' {} ' " , image . name , key , indent = 2 )
self . _pending [ key ] = [ layer . key , ]
self . _report . msg ( " Stashing ' {} ' for conversion as ' {} ' " , image . name , key , indent = indent )
self . _pending [ key ] = [ own er. key , ]
else :
self . _report . msg ( " Found another user of ' {} ' " , key , indent = 2 )
self . _pending [ key ] . append ( layer . key )
self . _report . msg ( " Found another user of ' {} ' " , key , indent = indent )
self . _pending [ key ] . append ( own er. key )
def finalize ( self ) :
self . _report . progress_advance ( )
self . _report . progress_range = len ( self . _pending )
inc_progress = self . _report . progress_increment
mgr = self . _mgr
for key , layers in self . _pending . items ( ) :
for key , own ers in self . _pending . items ( ) :
name = str ( key )
self . _report . msg ( " \n [Mipmap ' {} ' ] " , name )
@ -655,14 +688,27 @@ class MaterialConverter:
oWidth , oHeight , eWidth , eHeight , indent = 1 )
self . _resize_image ( image , eWidth , eHeight )
# Some basic mipmap settings.
compression = plBitmap . kDirectXCompression if key . mipmap else plBitmap . kUncompressed
dxt = plBitmap . kDXT5 if key . use_alpha or key . calc_alpha else plBitmap . kDXT1
# Now we try to use the pile of hints we were given to figure out what format to use
allowed_formats = key . allowed_formats
if key . mipmap :
compression = plBitmap . kDirectXCompression
dxt = plBitmap . kDXT5 if key . use_alpha or key . calc_alpha else plBitmap . kDXT1
elif " PNG " in allowed_formats and self . _mgr . getVer ( ) == pvMoul :
compression = plBitmap . kPNGCompression
elif " DDS " in allowed_formats :
compression = plBitmap . kDirectXCompression
dxt = plBitmap . kDXT5 if key . use_alpha or key . calc_alpha else plBitmap . kDXT1
elif " JPG " in allowed_formats :
compression = plBitmap . kJPEGCompression
elif " BMP " in allowed_formats :
compression = plBitmap . kUncompressed
else :
raise RuntimeError ( allowed_formats )
# Grab the image data from OpenGL and stuff it into the plBitmap
helper = GLTexture ( key )
with helper as glimage :
if key . mipmap :
if compression == plBitmap . kDirectXCompression :
numLevels = glimage . num_levels
self . _report . msg ( " Generating mip levels " , indent = 1 )
glimage . generate_mipmap ( )
@ -670,8 +716,8 @@ class MaterialConverter:
numLevels = 1
self . _report . msg ( " Stuffing image data " , indent = 1 )
# Uncompressed bitmaps are BGRA
fmt = compression == plBitmap . kUncompressed
# Non-DXT images are BGRA in Plasma
fmt = compression != plBitmap . kDirectXCompression
# Hold the uncompressed level data for now. We may have to make multiple copies of
# this mipmap for per-page textures :(
@ -684,13 +730,13 @@ class MaterialConverter:
# Now we poke our new bitmap into the pending layers. Note that we have to do some funny
# business to account for per-page textures
mgr = self . _mgr
pages = { }
self . _report . msg ( " Adding to Layer(s) " , indent = 1 )
for layer in layers :
self . _report . msg ( layer . name , indent = 2 )
page = mgr . get_textures_page ( layer ) # Layer's page or Textures.prp
self . _report . msg ( " Adding to... " , indent = 1 )
for owner_key in owners :
owner = owner_key . object
self . _report . msg ( " [ {} ' {} ' ] " , owner . ClassName ( ) [ 2 : ] , owner_key . name , indent = 2 )
page = mgr . get_textures_page ( owner_key ) # Layer's page or Textures.prp
# If we haven't created this plMipmap in the page (either layer's page or Textures.prp),
# then we need to do that and stuff the level data. This is a little tedious, but we
@ -703,7 +749,14 @@ class MaterialConverter:
pages [ page ] = mipmap
else :
mipmap = pages [ page ]
layer . object . texture = mipmap . key
if isinstance ( owner , plLayerInterface ) :
owner . texture = mipmap . key
elif isinstance ( owner , plImageLibMod ) :
owner . addImage ( mipmap . key )
else :
raise RuntimeError ( owner . ClassName ( ) )
inc_progress ( )
def get_materials ( self , bo ) :