Browse Source

Merge 84ab9206c3 into 16b0ebdc15

pull/176/merge
Adam Johnson 5 years ago committed by GitHub
parent
commit
4b8a1afa26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 119
      korman/operators/op_image.py
  2. 30
      korman/ui/ui_menus.py

119
korman/operators/op_image.py

@ -34,11 +34,89 @@ _CUBE_FACES = {
}
class ImageOperator:
def execute(self, context):
with ConsoleToggler(True), ExportProgressLogger() as self._report:
try:
self._execute(context)
except ExportError as error:
self.report({"ERROR"}, str(error))
return {"CANCELLED"}
else:
return {"FINISHED"}
def _execute(self, context):
raise NotImplementedError()
@classmethod
def poll(cls, context):
return context.scene.render.engine == "PLASMA_GAME"
class PlasmaBakeImageAlphaOperator(ImageOperator, bpy.types.Operator):
bl_idname = "image.plasma_bake_image_alpha"
bl_label = "Bake Image Alpha"
bl_description = "Bake an image's calculated alpha to another image's alpha channel"
filepath = StringProperty(name="Alpha Image",
subtype="FILE_PATH",
options=set())
def _execute(self, context):
self._report.progress_add_step("Preparing Images")
self._report.progress_add_step("Baking Alpha")
self._report.progress_add_step("Creating Image")
self._report.progress_start("BAKING IMAGE ALPHA")
if not Path(self.filepath).is_file():
raise ExportError("No image found at '{}'".format(self.filepath))
self._report.progress_advance()
images, im_diffuse = bpy.data.images, context.space_data.image
with TemporaryObject(images.load(self.filepath), images.remove) as im_alpha:
width, height = self._check_image_scale(im_diffuse, im_alpha)
self._report.progress_advance()
pixels = self._calc_alpha(im_diffuse, im_alpha, width, height)
self._report.progress_advance()
self._make_image(im_diffuse.name, self.filepath, width, height, pixels, context)
self._report.progress_end()
def _check_image_scale(self, im_diffuse, im_alpha):
sz_diffuse, sz_alpha = tuple(im_diffuse.size), tuple(im_alpha.size)
if tuple(im_diffuse.size) != tuple(im_alpha.size):
self._report.warn("Image sizes do not match, rescaling alpha image")
im_alpha.scale(*sz_diffuse)
return sz_diffuse
def _calc_alpha(self, im_diffuse, im_alpha, width, height):
# DO NOT REMOVE this copying... Trying to operate directly on the bpy_prop_collection
# is slower than molasses running uphill in Siberia!
pixels_diffuse, pixels_alpha = list(im_diffuse.pixels), tuple(im_alpha.pixels)
for i in range(width * height):
alpha_idx = i * 4
pixels_diffuse[alpha_idx + 3] = sum(pixels_alpha[alpha_idx:alpha_idx+2]) / 3.0
return pixels_diffuse
def _make_image(self, name_diffuse, name_alpha, width, height, pixels, context=None):
name = "{}_ALPHAGEN_{}.png".format(Path(name_diffuse).stem, Path(name_alpha).stem)
im_dest = bpy.data.images.new(name, width, height, True)
im_dest.pixels = pixels
im_dest.update()
im_dest.pack(as_png=True)
if context and context.space_data:
context.space_data.image = im_dest
return im_dest
def invoke(self, context, event):
context.window_manager.fileselect_add(self)
return {"RUNNING_MODAL"}
@classmethod
def poll(cls, context):
space = context.space_data
return super().poll(context) and space and space.image
class PlasmaBuildCubeMapOperator(ImageOperator, bpy.types.Operator):
bl_idname = "image.plasma_build_cube_map"
bl_label = "Build Cubemap"
@ -58,24 +136,11 @@ class PlasmaBuildCubeMapOperator(ImageOperator, bpy.types.Operator):
default="",
options={"HIDDEN"})
def __init__(self):
self._report = ExportProgressLogger()
def _execute(self, context):
self._report.progress_add_step("Finding Face Images")
self._report.progress_add_step("Loading Face Images")
self._report.progress_add_step("Scaling Face Images")
self._report.progress_add_step("Generating Cube Map")
def execute(self, context):
with ConsoleToggler(True) as _:
try:
self._execute()
except ExportError as error:
self.report({"ERROR"}, str(error))
return {"CANCELLED"}
else:
return {"FINISHED"}
def _execute(self):
self._report.progress_start("BUILDING CUBE MAP")
if not Path(self.filepath).is_file():
raise ExportError("No cube image found at '{}'".format(self.filepath))
@ -235,3 +300,29 @@ class PlasmaBuildCubeMapOperator(ImageOperator, bpy.types.Operator):
min_width, min_height)
self._report.progress_increment()
return min_width, min_height, tuple(result_data)
class PlasmaClampAlphaOperator(ImageOperator, bpy.types.Operator):
bl_idname = "image.plasma_clamp_image_alpha"
bl_label = "Clamp Image Alpha"
bl_description = "Clamp an image's alpha to fully opaque or transparent"
bl_options = {"UNDO"}
def _execute(self, context):
self._report.progress_add_step("Clamping Alpha")
self._report.progress_start("CLAMPING ALPHA")
self._report.progress_advance()
image = context.space_data.image
pixels = list(image.pixels)
width, height = image.size
# significant figures: round up the even
for i in range(3, (width * height * 4), 4):
pixels[i] = 1.0 if pixels[i] >= 0.5 else 0.0
image.pixels = pixels
self._report.progress_end()
@classmethod
def poll(cls, context):
space = context.space_data
return super().poll(context) and space and space.image

30
korman/ui/ui_menus.py

@ -13,7 +13,8 @@
# You should have received a copy of the GNU General Public License
# along with Korman. If not, see <http://www.gnu.org/licenses/>.
from ..operators.op_mesh import *
import bpy
import functools
class PlasmaMenu:
@classmethod
@ -34,14 +35,33 @@ class PlasmaAddMenu(PlasmaMenu, bpy.types.Menu):
layout.operator("mesh.plasma_linkingbook_add", text="Linking Book", icon="FILE_IMAGE")
def build_plasma_menu(self, context):
class PlasmaImageMenu(PlasmaMenu, bpy.types.Menu):
bl_idname = "menu.plasma_image"
bl_label = "Plasma"
bl_description = "Plasma Image Operators"
def draw(self, context):
layout = self.layout
layout.operator("image.plasma_bake_image_alpha", icon="IMAGE_RGB_ALPHA")
layout.operator("image.plasma_clamp_image_alpha", icon="IMAGE_ALPHA")
layout.separator()
layout.operator("image.plasma_build_cube_map", icon="MATCUBE")
def _build_plasma_menu(menu_operator, self, context):
if context.scene.render.engine != "PLASMA_GAME":
return
self.layout.separator()
self.layout.menu("menu.plasma_add", icon="URL")
self.layout.menu(menu_operator, icon="URL")
build_plasma_add_menu = functools.partial(_build_plasma_menu, "menu.plasma_add")
build_plasma_image_menu = functools.partial(_build_plasma_menu, "menu.plasma_image")
def register():
bpy.types.INFO_MT_add.append(build_plasma_menu)
bpy.types.INFO_MT_add.append(build_plasma_add_menu)
bpy.types.IMAGE_MT_image.append(build_plasma_image_menu)
def unregister():
bpy.types.INFO_MT_add.remove(build_plasma_menu)
bpy.types.INFO_MT_add.remove(build_plasma_add_menu)
bpy.types.IMAGE_MT_image.remove(build_plasma_image_menu)

Loading…
Cancel
Save