Browse Source

Fix #126.

Warning: Korlib C API change. Version bumped.
pull/161/head
Adam Johnson 5 years ago
parent
commit
3897dfa1c2
Signed by: Hoikas
GPG Key ID: 0B6515D6FF6F271E
  1. 2
      korlib/module.cpp
  2. 23
      korlib/texture.cpp
  3. 32
      korman/exporter/material.py
  4. 3
      korman/korlib/__init__.py
  5. 18
      korman/korlib/texture.py

2
korlib/module.cpp

@ -19,7 +19,7 @@
#include "texture.h" #include "texture.h"
// This konstant is compared against that in the Python module to prevent sneaky errors... // This konstant is compared against that in the Python module to prevent sneaky errors...
#define KORLIB_API_VERSION 1 #define KORLIB_API_VERSION 2
static PyMethodDef korlib_Methods[] = { static PyMethodDef korlib_Methods[] = {
{ _pycs("create_bump_LUT"), (PyCFunction)create_bump_LUT, METH_VARARGS, NULL }, { _pycs("create_bump_LUT"), (PyCFunction)create_bump_LUT, METH_VARARGS, NULL },

23
korlib/texture.cpp

@ -195,6 +195,12 @@ enum {
TEX_DETAIL_MULTIPLY = 2, TEX_DETAIL_MULTIPLY = 2,
}; };
enum {
kOpaque = 0,
kOnOff = 1,
kFull = 2,
};
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
PyObject* m_blenderImage; PyObject* m_blenderImage;
@ -476,12 +482,19 @@ static PyMethodDef pyGLTexture_Methods[] = {
static PyObject* pyGLTexture_get_has_alpha(pyGLTexture* self, void*) { static PyObject* pyGLTexture_get_has_alpha(pyGLTexture* self, void*) {
char* data = PyBytes_AsString(self->m_imageData); char* data = PyBytes_AsString(self->m_imageData);
size_t bufsz = self->m_width * self->m_height * sizeof(uint32_t); size_t bufsz = self->m_width * self->m_height * sizeof(uint32_t);
for (size_t i = 3; i < bufsz; i += 4) { bool transparency = false;
if (data[i] != 255) {
return PyBool_FromLong(1); uint32_t* datap = reinterpret_cast<uint32_t*>(data);
} uint32_t* endp = reinterpret_cast<uint32_t*>(data + bufsz);
while (datap < endp) {
uint8_t alpha = ((*datap & 0xFF000000) >> 24);
if (alpha == 0x00)
transparency = true;
else if (alpha != 0xFF)
return PyLong_FromLong(kFull);
datap++;
} }
return PyBool_FromLong(0); return PyLong_FromLong(transparency ? kOnOff : kOpaque);
} }
static PyObject* pyGLTexture_get_image_data(pyGLTexture* self, void*) { static PyObject* pyGLTexture_get_image_data(pyGLTexture* self, void*) {

32
korman/exporter/material.py

@ -61,19 +61,16 @@ class _Texture:
self.detail_opacity_start = kwargs["detail_opacity_start"] self.detail_opacity_start = kwargs["detail_opacity_start"]
self.detail_opacity_stop = kwargs["detail_opacity_stop"] self.detail_opacity_stop = kwargs["detail_opacity_stop"]
self.calc_alpha = False self.calc_alpha = False
self.use_alpha = True self.alpha_type = TextureAlpha.full
self.allowed_formats = {"DDS"} self.allowed_formats = {"DDS"}
self.is_cube_map = False self.is_cube_map = False
else: else:
self.is_detail_map = False self.is_detail_map = False
use_alpha = kwargs.get("use_alpha")
if kwargs.get("force_calc_alpha", False) or self.calc_alpha: if kwargs.get("force_calc_alpha", False) or self.calc_alpha:
self.calc_alpha = True self.calc_alpha = True
self.use_alpha = True self.alpha_type = TextureAlpha.full
elif use_alpha is None:
self.use_alpha = (image.channels == 4 and image.use_alpha)
else: else:
self.use_alpha = use_alpha self.alpha_type = kwargs.get("alpha_type", TextureAlpha.opaque)
self.allowed_formats = kwargs.get("allowed_formats", self.allowed_formats = kwargs.get("allowed_formats",
{"DDS"} if self.mipmap else {"PNG", "JPG"}) {"DDS"} if self.mipmap else {"PNG", "JPG"})
self.is_cube_map = kwargs.get("is_cube_map", False) self.is_cube_map = kwargs.get("is_cube_map", False)
@ -124,8 +121,8 @@ class _Texture:
def _update(self, other): def _update(self, other):
"""Update myself with any props that might be overridable from another copy of myself""" """Update myself with any props that might be overridable from another copy of myself"""
# NOTE: detail map properties should NEVER be overridden. NEVER. EVER. kthx. # NOTE: detail map properties should NEVER be overridden. NEVER. EVER. kthx.
if other.use_alpha: if self.alpha_type < other.alpha_type:
self.use_alpha = True self.alpha_type = other.alpha_type
if other.mipmap: if other.mipmap:
self.mipmap = True self.mipmap = True
@ -536,8 +533,8 @@ class MaterialConverter:
# prevent that as well, so we could theoretically slice-and-dice the single # prevent that as well, so we could theoretically slice-and-dice the single
# image here... but... meh. Offloading taim. # image here... but... meh. Offloading taim.
self.export_prepared_image(texture=texture, owner=layer, indent=3, self.export_prepared_image(texture=texture, owner=layer, indent=3,
use_alpha=False, mipmap=True, allowed_formats={"DDS"}, alpha_type=TextureAlpha.opaque, mipmap=True,
is_cube_map=True, tag="cubemap") allowed_formats={"DDS"}, is_cube_map=True, tag="cubemap")
def export_dynamic_env(self, bo, layer, texture, pl_class): def export_dynamic_env(self, bo, layer, texture, pl_class):
@ -650,12 +647,13 @@ class MaterialConverter:
# Does the image have any alpha at all? # Does the image have any alpha at all?
if texture.image is not None: if texture.image is not None:
has_alpha = texture.use_calculate_alpha or slot.use_stencil or self._test_image_alpha(texture.image) alpha_type = self._test_image_alpha(texture.image)
has_alpha = texture.use_calculate_alpha or slot.use_stencil or alpha_type != TextureAlpha.opaque
if (texture.image.use_alpha and texture.use_alpha) and not has_alpha: 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) warning = "'{}' wants to use alpha, but '{}' is opaque".format(texture.name, texture.image.name)
self._exporter().report.warn(warning, indent=3) self._exporter().report.warn(warning, indent=3)
else: else:
has_alpha = True alpha_type, has_alpha = TextureAlpha.opaque, False
# First, let's apply any relevant flags # First, let's apply any relevant flags
state = layer.state state = layer.state
@ -699,7 +697,7 @@ class MaterialConverter:
allowed_formats = {"DDS"} if mipmap else {"PNG", "BMP"} allowed_formats = {"DDS"} if mipmap else {"PNG", "BMP"}
self.export_prepared_image(texture=texture, owner=layer, self.export_prepared_image(texture=texture, owner=layer,
use_alpha=has_alpha, force_calc_alpha=slot.use_stencil, alpha_type=alpha_type, force_calc_alpha=slot.use_stencil,
is_detail_map=layer_props.is_detail_map, is_detail_map=layer_props.is_detail_map,
detail_blend=detail_blend, detail_blend=detail_blend,
detail_fade_start=layer_props.detail_fade_start, detail_fade_start=layer_props.detail_fade_start,
@ -778,7 +776,7 @@ class MaterialConverter:
compression = plBitmap.kUncompressed compression = plBitmap.kUncompressed
else: else:
raise RuntimeError(allowed_formats) raise RuntimeError(allowed_formats)
dxt = plBitmap.kDXT5 if key.use_alpha or key.calc_alpha else plBitmap.kDXT1 dxt = plBitmap.kDXT5 if key.alpha_type == TextureAlpha.full else plBitmap.kDXT1
# Mayhaps we have a cached version of this that has already been exported # Mayhaps we have a cached version of this that has already been exported
cached_image = texcache.get_from_texture(key, compression) cached_image = texcache.get_from_texture(key, compression)
@ -1035,10 +1033,8 @@ class MaterialConverter:
if result is not None: if result is not None:
return result return result
if image.channels != 4: if image.channels != 4 or not image.use_alpha:
result = False result = TextureAlpha.opaque
elif not image.use_alpha:
result = False
else: else:
# Using bpy.types.Image.pixels is VERY VERY VERY slow... # Using bpy.types.Image.pixels is VERY VERY VERY slow...
key = _Texture(image=image) key = _Texture(image=image)

3
korman/korlib/__init__.py

@ -13,7 +13,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Korman. If not, see <http://www.gnu.org/licenses/>. # along with Korman. If not, see <http://www.gnu.org/licenses/>.
_KORLIB_API_VERSION = 1 _KORLIB_API_VERSION = 2
try: try:
from _korlib import _KORLIB_API_VERSION as _C_API_VERSION from _korlib import _KORLIB_API_VERSION as _C_API_VERSION
@ -70,6 +70,7 @@ except ImportError as ex:
else: else:
from _korlib import * from _korlib import *
from .texture import TextureAlpha
finally: finally:
from .console import ConsoleCursor, ConsoleToggler from .console import ConsoleCursor, ConsoleToggler

18
korman/korlib/texture.py

@ -15,6 +15,7 @@
import array import array
import bgl import bgl
import enum
from ..helpers import ensure_power_of_two from ..helpers import ensure_power_of_two
import math import math
from PyHSPlasma import plBitmap from PyHSPlasma import plBitmap
@ -95,6 +96,13 @@ def scale_image(buf, srcW, srcH, dstW, dstH):
return bytes(dst) return bytes(dst)
@enum.unique
class TextureAlpha(enum.IntEnum):
opaque = 0
on_off = 1
full = 2
class GLTexture: class GLTexture:
def __init__(self, texkey=None, image=None, bgra=False, fast=False): def __init__(self, texkey=None, image=None, bgra=False, fast=False):
assert texkey or image assert texkey or image
@ -224,11 +232,13 @@ class GLTexture:
@property @property
def has_alpha(self): def has_alpha(self):
data = self._image_data data, xparency = self._image_data, False
for i in range(3, len(data), 4): for i in range(3, len(data), 4):
if data[i] != 255: if data[i] == 0:
return True xparency = True
return False elif data[i] != 255:
return TextureAlpha.full
return TextureAlpha.on_off if xparency else TextureAlpha.opaque
def _get_image_data(self): def _get_image_data(self):
return (self._width, self._height, self._image_data) return (self._width, self._height, self._image_data)

Loading…
Cancel
Save