Browse Source

Merge remote-tracking branch 'hoikas/stencils'

pull/8/head
Adam Johnson 10 years ago
parent
commit
6477c803c4
  1. 4
      korman/exporter/manager.py
  2. 91
      korman/exporter/material.py
  3. 10
      korman/exporter/mesh.py

4
korman/exporter/manager.py

@ -200,13 +200,13 @@ class ExportManager:
location = self._pages[bl.plasma_object.page]
return self._nodes[location].key
def get_textures_page(self, layer):
def get_textures_page(self, key):
"""Gets the appropriate page for a texture for a given plLayer"""
# The point of this is to account for per-page textures...
if "Textures" in self._pages:
return self._pages["Textures"]
else:
return layer.key.location
return key.location
def has_coordiface(self, bo):
if bo.type in {"CAMERA", "EMPTY", "LAMP"}:

91
korman/exporter/material.py

@ -87,10 +87,9 @@ class _GLTexture:
# NOTE: the variable names are correct for GL_RGBA. We'll still get the right values for
# BGRA, obviously, but red will suddenly be... blue. Yeah.
if calc_alpha:
for i in range(size, 4):
base = i*4
r, g, b = buf[base:base+2]
buf[base+3] = int((r + g + b) / 3)
for i in range(0, size, 4):
r, g, b = buf[i:i+3]
buf[i+3] = int((r + g + b) / 3)
return bytes(buf)
def _get_integer(self, arg):
@ -108,7 +107,7 @@ class _GLTexture:
class _Texture:
def __init__(self, texture=None, image=None, use_alpha=None):
def __init__(self, texture=None, image=None, use_alpha=None, force_calc_alpha=False):
assert (texture or image)
if texture is not None:
@ -120,7 +119,10 @@ class _Texture:
self.calc_alpha = False
self.mipmap = False
if use_alpha is None:
if force_calc_alpha or self.calc_alpha:
self.calc_alpha = True
self.use_alpha = True
elif use_alpha is None:
self.use_alpha = (image.channels == 4 and image.use_alpha)
else:
self.use_alpha = use_alpha
@ -169,13 +171,25 @@ class MaterialConverter:
self._exporter = weakref.ref(exporter)
self._pending = {}
self._alphatest = {}
self._tex_exporters = {
"ENVRIONMENT_MAP": self._export_texture_type_environment_map,
"IMAGE": self._export_texture_type_image,
"NONE": self._export_texture_type_none,
}
def export_material(self, bo, bm):
"""Exports a Blender Material as an hsGMaterial"""
print(" Exporting Material '{}'".format(bm.name))
hsgmat = self._mgr.add_object(hsGMaterial, name=bm.name, bl=bo)
self._export_texture_slots(bo, bm, hsgmat)
slots = [slot for slot in bm.texture_slots if slot is not None and slot.use and
slot.texture is not None and slot.texture.type in self._tex_exporters]
# Okay, I know this isn't Pythonic... But we're doing it this way because we might actually
# export many slots in one go. Think stencils.
i = 0
while i < len(slots):
i += self._export_texture_slot(bo, bm, hsgmat, slots, i)
# Plasma makes several assumptions that every hsGMaterial has at least one layer. If this
# material had no Textures, we will need to initialize a default layer
@ -193,10 +207,9 @@ class MaterialConverter:
# Looks like we're done...
return hsgmat.key
def _export_texture_slots(self, bo, bm, hsgmat):
for slot in bm.texture_slots:
if slot is None or not slot.use:
continue
def _export_texture_slot(self, bo, bm, hsgmat, slots, idx):
slot = slots[idx]
num_exported = 1
name = "{}_{}".format(bm.name, slot.name)
print(" Exporting Plasma Layer '{}'".format(name))
@ -212,8 +225,31 @@ class MaterialConverter:
else:
print(" No UVMap specified... Blindly using the first one, maybe it exists :|")
# General texture flags and such
state = layer.state
if slot.use_stencil:
hsgmat.compFlags |= hsGMaterial.kCompNeedsBlendChannel
state.blendFlags |= hsGMatState.kBlendAlpha | hsGMatState.kBlendAlphaMult | hsGMatState.kBlendNoTexColor
state.clampFlags |= hsGMatState.kClampTexture
state.ZFlags |= hsGMatState.kZNoZWrite
layer.ambient = hsColorRGBA(1.0, 1.0, 1.0, 1.0)
# Plasma actually wants the next layer first, so let's export him
nextIdx = idx + 1
if len(slots) == nextIdx:
raise ExportError("Texture Slot '{}' wants to be a stencil, but there are no more TextureSlots.".format(slot.name))
print(" --- BEGIN STENCIL ---")
self._export_texture_slot(bo, bm, hsgmat, slots, nextIdx)
print(" --- END STENCIL ---")
num_exported += 1
# Now that we've exported the bugger, flag him as binding with this texture
prev_layer = hsgmat.layers[-1].object
prev_state = prev_layer.state
prev_state.miscFlags |= hsGMatState.kMiscBindNext | hsGMatState.kMiscRestartPassHere
if not prev_state.blendFlags & hsGMatState.kBlendMask:
prev_state.blendFlags |= hsGMatState.kBlendAlpha
else:
# Standard layer flags ahoy
if slot.blend_type == "ADD":
state.blendFlags |= hsGMatState.kBlendAdd
elif slot.blend_type == "MULTIPLY":
@ -221,15 +257,14 @@ class MaterialConverter:
# Export the specific texture type
texture = slot.texture
export_fn = "_export_texture_type_{}".format(texture.type.lower())
if not hasattr(self, export_fn):
raise explosions.UnsupportedTextureError(texture, bm)
getattr(self, export_fn)(bo, hsgmat, layer, texture)
self._tex_exporters[texture.type](bo, hsgmat, layer, slot)
hsgmat.addLayer(layer.key)
return num_exported
def _export_texture_type_environment_map(self, bo, hsgmat, layer, texture):
def _export_texture_type_environment_map(self, bo, hsgmat, layer, slot):
"""Exports a Blender EnvironmentMapTexture to a plLayer"""
texture = slot.texture
bl_env = texture.environment_map
if bl_env.source in {"STATIC", "ANIMATED"}:
if bl_env.mapping == "PLANE" and self._mgr.getVer() >= pvMoul:
@ -324,21 +359,25 @@ class MaterialConverter:
return pl_env.key
def _export_texture_type_image(self, bo, hsgmat, layer, texture):
def _export_texture_type_image(self, bo, hsgmat, layer, slot):
"""Exports a Blender ImageTexture to a plLayer"""
texture = slot.texture
# Does the image have any alpha at all?
has_alpha = texture.use_calculate_alpha or self._test_image_alpha(texture.image)
has_alpha = texture.use_calculate_alpha or slot.use_stencil or self._test_image_alpha(texture.image)
if (texture.image.use_alpha and texture.use_alpha) and not has_alpha:
warning = "'{}' wants to use alpha, but '{}' is opaque".format(texture.name, texture.image.name)
self._exporter().report.warn(warning, indent=3)
# First, let's apply any relevant flags
state = layer.state
if texture.invert_alpha and has_alpha:
state.blendFlags |= hsGMatState.kBlendInvertAlpha
if not slot.use_stencil:
# mutually exclusive blend flags
if texture.use_alpha and has_alpha:
state.blendFlags |= hsGMatState.kBlendAlpha
if texture.invert_alpha and has_alpha:
state.blendFlags |= hsGMatState.kBlendInvertAlpha
if texture.extension == "CLIP":
state.clampFlags |= hsGMatState.kClampTexture
@ -349,13 +388,13 @@ class MaterialConverter:
if texture.image is None:
bitmap = self.add_object(plDynamicTextMap, name="{}_DynText".format(layer.key.name), bl=bo)
else:
key = _Texture(texture=texture, use_alpha=has_alpha)
key = _Texture(texture=texture, use_alpha=has_alpha, force_calc_alpha=slot.use_stencil)
if key not in self._pending:
print(" Stashing '{}' for conversion as '{}'".format(texture.image.name, str(key)))
self._pending[key] = [layer,]
self._pending[key] = [layer.key,]
else:
print(" Found another user of '{}'".format(texture.image.name))
self._pending[key].append(layer)
self._pending[key].append(layer.key)
def _export_texture_type_none(self, bo, hsgmat, layer, texture):
# We'll allow this, just for sanity's sake...
@ -431,7 +470,7 @@ class MaterialConverter:
print(" Adding to Layer(s)")
for layer in layers:
print(" {}".format(layer.key.name))
print(" {}".format(layer.name))
page = mgr.get_textures_page(layer) # Layer's page or Textures.prp
# If we haven't created this plMipmap in the page (either layer's page or Textures.prp),
@ -447,7 +486,7 @@ class MaterialConverter:
pages[page] = mipmap
else:
mipmap = pages[page]
layer.texture = mipmap.key
layer.object.texture = mipmap.key
def get_materials(self, bo):
return self._obj2mat[bo]

10
korman/exporter/mesh.py

@ -42,7 +42,7 @@ class _RenderLevel:
# Naive... BlendSpans (any blending on the first layer) are MAJOR_BLEND
if blendSpan:
self.major = self.MAJOR_BLEND
self.major = self.MAJOR_DEFAULT
# We use the blender material's pass index (which we stashed in the hsGMaterial) to increment
# the render pass, just like it says...
@ -69,8 +69,12 @@ class _RenderLevel:
class _DrawableCriteria:
def __init__(self, hsgmat, pass_index):
_layer = hsgmat.layers[0].object # better doggone well have a layer...
self.blend_span = bool(_layer.state.blendFlags & hsGMatState.kBlendMask)
for layer in hsgmat.layers:
if layer.object.state.blendFlags & hsGMatState.kBlendMask:
self.blend_span = True
break
else:
self.blend_span = False
self.criteria = 0 # TODO
self.render_level = _RenderLevel(hsgmat, pass_index, self.blend_span)

Loading…
Cancel
Save