Browse Source

Merge pull request #122 from Hoikas/lm-passes

Add named lightmap passes
pull/123/head
Adam Johnson 6 years ago committed by GitHub
parent
commit
4523f5a2fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      korman/exporter/convert.py
  2. 37
      korman/exporter/etlight.py
  3. 6
      korman/exporter/mesh.py
  4. 30
      korman/operators/op_export.py
  5. 2
      korman/properties/__init__.py
  6. 82
      korman/properties/modifiers/render.py
  7. 46
      korman/properties/prop_scene.py
  8. 1
      korman/ui/__init__.py
  9. 30
      korman/ui/modifiers/render.py
  10. 53
      korman/ui/ui_render_layer.py
  11. 12
      korman/ui/ui_world.py

5
korman/exporter/convert.py

@ -61,7 +61,7 @@ class Exporter:
self.mesh.add_progress_presteps(self.report) self.mesh.add_progress_presteps(self.report)
self.report.progress_add_step("Collecting Objects") self.report.progress_add_step("Collecting Objects")
self.report.progress_add_step("Harvesting Actors") self.report.progress_add_step("Harvesting Actors")
if self._op.bake_lighting: if self._op.lighting_method != "skip":
etlight.LightBaker.add_progress_steps(self.report) etlight.LightBaker.add_progress_steps(self.report)
self.report.progress_add_step("Exporting Scene Objects") self.report.progress_add_step("Exporting Scene Objects")
self.report.progress_add_step("Exporting Logic Nodes") self.report.progress_add_step("Exporting Logic Nodes")
@ -86,7 +86,6 @@ class Exporter:
# Step 2.9: It is assumed that static lighting is available for the mesh exporter. # Step 2.9: It is assumed that static lighting is available for the mesh exporter.
# Indeed, in PyPRP it was a manual step. So... BAKE NAO! # Indeed, in PyPRP it was a manual step. So... BAKE NAO!
if self._op.bake_lighting:
self._bake_static_lighting() self._bake_static_lighting()
# Step 3: Export all the things! # Step 3: Export all the things!
@ -113,6 +112,8 @@ class Exporter:
self.report.save() self.report.save()
def _bake_static_lighting(self): def _bake_static_lighting(self):
lighting_method = self._op.lighting_method
if lighting_method != "skip":
oven = etlight.LightBaker(self.report) oven = etlight.LightBaker(self.report)
oven.bake_static_lighting(self._objects) oven.bake_static_lighting(self._objects)

37
korman/exporter/etlight.py

@ -78,9 +78,9 @@ class LightBaker(_MeshManager):
self._select_only(objs, toggle) self._select_only(objs, toggle)
bpy.ops.object.bake_image() bpy.ops.object.bake_image()
def _bake_vcols(self, objs): def _bake_vcols(self, objs, layers):
with GoodNeighbor() as toggle: with GoodNeighbor() as toggle:
bpy.context.scene.layers = (True,) * _NUM_RENDER_LAYERS bpy.context.scene.layers = layers
self._apply_render_settings(toggle, True) self._apply_render_settings(toggle, True)
self._select_only(objs, toggle) self._select_only(objs, toggle)
bpy.ops.object.bake_image() bpy.ops.object.bake_image()
@ -147,14 +147,15 @@ class LightBaker(_MeshManager):
if value: if value:
if key[0] == "lightmap": if key[0] == "lightmap":
num_objs = len(value) num_objs = len(value)
self._report.msg("{} Lightmap(s) [H:{:X}]", num_objs, hash(key), indent=1) self._report.msg("{} Lightmap(s) [H:{:X}]", num_objs, hash(key[1:]), indent=1)
if largest_pass > 1 and num_objs < round(largest_pass * 0.02): if largest_pass > 1 and num_objs < round(largest_pass * 0.02):
obj_names = ", ".join((i.name for i in value)) pass_names = set((i.plasma_modifiers.lightmap.bake_pass_name for i in value))
self._report.warn("Small lightmap pass! Objects: {}".format(obj_names), indent=2) pass_msg = ", ".join(pass_names)
self._report.warn("Small lightmap bake pass! Bake Pass(es): {}".format(pass_msg), indent=2)
self._bake_lightmaps(value, key[1:]) self._bake_lightmaps(value, key[1:])
elif key[0] == "vcol": elif key[0] == "vcol":
self._report.msg("{} Crap Light(s)", len(value), indent=1) self._report.msg("{} Vertex Color(s) [H:{:X}]", len(value), hash(key[1:]), indent=1)
self._bake_vcols(value) self._bake_vcols(value, key[1:])
else: else:
raise RuntimeError(key[0]) raise RuntimeError(key[0])
inc_progress() inc_progress()
@ -219,8 +220,9 @@ class LightBaker(_MeshManager):
def _harvest_bakable_objects(self, objs): def _harvest_bakable_objects(self, objs):
# The goal here is to minimize the calls to bake_image, so we are going to collect everything # The goal here is to minimize the calls to bake_image, so we are going to collect everything
# that needs to be baked and sort it out by configuration. # that needs to be baked and sort it out by configuration.
bake = { ("vcol",): [] } default_layers = tuple((True,) * _NUM_RENDER_LAYERS)
bake_vcol = bake[("vcol",)] bake, bake_passes = {}, bpy.context.scene.plasma_scene.bake_passes
bake_vcol = bake.setdefault(("vcol",) + default_layers, [])
for i in objs: for i in objs:
if i.type != "MESH": if i.type != "MESH":
@ -231,15 +233,24 @@ class LightBaker(_MeshManager):
mods = i.plasma_modifiers mods = i.plasma_modifiers
lightmap_mod = mods.lightmap lightmap_mod = mods.lightmap
if lightmap_mod.enabled: if lightmap_mod.enabled:
if lightmap_mod.bake_pass_name:
bake_pass = bake_passes.get(lightmap_mod.bake_pass_name, None)
if bake_pass is None:
raise ExportError("Bake Lighting '{}': Could not find pass '{}'".format(i.name, lightmap_mod.bake_pass_name))
lm_layers = tuple(bake_pass.render_layers)
else:
lm_layers = default_layers
# In order for Blender to be able to bake this properly, at least one of the # In order for Blender to be able to bake this properly, at least one of the
# layers this object is on must be selected. We will sanity check this now. # layers this object is on must be selected. We will sanity check this now.
lm_layers, obj_layers = tuple(lightmap_mod.render_layers), tuple(i.layers) obj_layers = tuple(i.layers)
lm_active_layers = set((i for i, value in enumerate(lm_layers) if value)) lm_active_layers = set((i for i, value in enumerate(lm_layers) if value))
obj_active_layers = set((i for i, value in enumerate(obj_layers) if value)) obj_active_layers = set((i for i, value in enumerate(obj_layers) if value))
if not lm_active_layers & obj_active_layers: if not lm_active_layers & obj_active_layers:
raise ExportError("Lightmap '{}': At least one layer the object is on must be selected".format(i.name)) raise ExportError("Bake Lighting '{}': At least one layer the object is on must be selected".format(i.name))
key = ("lightmap",) + lm_layers method = "lightmap" if lightmap_mod.bake_lightmap else "vcol"
key = (method,) + lm_layers
bake_pass = bake.setdefault(key, []) bake_pass = bake.setdefault(key, [])
bake_pass.append(i) bake_pass.append(i)
elif mods.lighting.preshade: elif mods.lighting.preshade:
@ -356,9 +367,11 @@ class LightBaker(_MeshManager):
def _prep_for_vcols(self, bo, toggle): def _prep_for_vcols(self, bo, toggle):
mesh = bo.data mesh = bo.data
modifier = bo.plasma_modifiers.lightmap
vcols = mesh.vertex_colors vcols = mesh.vertex_colors
# Create a special light group for baking # Create a special light group for baking
user_lg = modifier.lights if modifier.enabled else None
if not self._generate_lightgroup(bo): if not self._generate_lightgroup(bo):
return False return False

6
korman/exporter/mesh.py

@ -195,7 +195,8 @@ class MeshConverter(_MeshManager):
# Lightmapping requires its own LIGHTMAPGEN channel # Lightmapping requires its own LIGHTMAPGEN channel
# NOTE: the LIGHTMAPGEN texture has already been created, so it is in num_user_texs # NOTE: the LIGHTMAPGEN texture has already been created, so it is in num_user_texs
if bo.plasma_modifiers.lightmap.enabled: lm = bo.plasma_modifiers.lightmap
if lm.enabled and lm.bake_type == "lightmap":
num_user_texs -= 1 num_user_texs -= 1
max_user_texs -= 1 max_user_texs -= 1
@ -261,12 +262,13 @@ class MeshConverter(_MeshManager):
bumpmap = self.material.get_bump_layer(bo) bumpmap = self.material.get_bump_layer(bo)
# Locate relevant vertex color layers now... # Locate relevant vertex color layers now...
lm = bo.plasma_modifiers.lightmap
color, alpha = None, None color, alpha = None, None
for vcol_layer in mesh.tessface_vertex_colors: for vcol_layer in mesh.tessface_vertex_colors:
name = vcol_layer.name.lower() name = vcol_layer.name.lower()
if name in _VERTEX_COLOR_LAYERS: if name in _VERTEX_COLOR_LAYERS:
color = vcol_layer.data color = vcol_layer.data
elif name == "autocolor" and color is None and not bo.plasma_modifiers.lightmap.enabled: elif name == "autocolor" and color is None and not lm.bake_lightmap:
color = vcol_layer.data color = vcol_layer.data
elif name == "alpha": elif name == "alpha":
alpha = vcol_layer.data alpha = vcol_layer.data

30
korman/operators/op_export.py

@ -37,10 +37,6 @@ class ExportOperator(bpy.types.Operator):
"description": "Profiles the exporter using cProfile", "description": "Profiles the exporter using cProfile",
"default": False}), "default": False}),
"bake_lighting": (BoolProperty, {"name": "Bake Static Lights",
"description": "Bake all lightmaps and vertex shading on export",
"default": True}),
"verbose": (BoolProperty, {"name": "Display Verbose Log", "verbose": (BoolProperty, {"name": "Display Verbose Log",
"description": "Shows the verbose export log in the console", "description": "Shows the verbose export log in the console",
"default": False}), "default": False}),
@ -58,6 +54,18 @@ class ExportOperator(bpy.types.Operator):
("use", "Use Texture Cache", "Use (and update, if needed) cached textures."), ("use", "Use Texture Cache", "Use (and update, if needed) cached textures."),
("rebuild", "Rebuild Texture Cache", "Rebuilds the texture cache from scratch.")], ("rebuild", "Rebuild Texture Cache", "Rebuilds the texture cache from scratch.")],
"default": "use"}), "default": "use"}),
"lighting_method": (EnumProperty, {"name": "Static Lighting",
"description": "Static Lighting Settings",
"items": [("skip", "Don't Bake Lighting", "Static lighting is not baked during this export (fastest export)"),
("bake", "Bake Lighting", "Static lighting is baked according to your specifications"),
("force_vcol", "Force Vertex Color Bake", "All static lighting is baked as vertex colors (faster export)"),
("force_lightmap", "Force Lightmap Bake", "All static lighting is baked as lightmaps (slower export)")],
"default": "bake"}),
"export_active": (BoolProperty, {"name": "INTERNAL: Export currently running",
"default": False,
"options": {"SKIP_SAVE"}}),
} }
# This wigs out and very bad things happen if it's not directly on the operator... # This wigs out and very bad things happen if it's not directly on the operator...
@ -77,7 +85,7 @@ class ExportOperator(bpy.types.Operator):
# The crazy mess we're doing with props on the fly means we have to explicitly draw them :( # The crazy mess we're doing with props on the fly means we have to explicitly draw them :(
layout.prop(self, "version") layout.prop(self, "version")
layout.prop(age, "texcache_method", text="") layout.prop(age, "texcache_method", text="")
layout.prop(age, "bake_lighting") layout.prop(age, "lighting_method")
row = layout.row() row = layout.row()
row.enabled = ConsoleToggler.is_platform_supported() row.enabled = ConsoleToggler.is_platform_supported()
row.prop(age, "show_console") row.prop(age, "show_console")
@ -89,6 +97,12 @@ class ExportOperator(bpy.types.Operator):
return getattr(bpy.context.scene.world.plasma_age, attr) return getattr(bpy.context.scene.world.plasma_age, attr)
raise AttributeError(attr) raise AttributeError(attr)
def __setattr__(self, attr, value):
if attr in self._properties:
setattr(bpy.context.scene.world.plasma_age, attr, value)
else:
super().__setattr__(attr, value)
@property @property
def has_reports(self): def has_reports(self):
return hasattr(self.report) return hasattr(self.report)
@ -120,6 +134,7 @@ class ExportOperator(bpy.types.Operator):
with _UiHelper(context) as _ui: with _UiHelper(context) as _ui:
e = exporter.Exporter(self) e = exporter.Exporter(self)
try: try:
self.export_active = True
if self.profile_export: if self.profile_export:
profile = path.with_name("{}_cProfile".format(ageName)) profile = path.with_name("{}_cProfile".format(ageName))
profile = cProfile.runctx("e.run()", globals(), locals(), str(profile)) profile = cProfile.runctx("e.run()", globals(), locals(), str(profile))
@ -136,6 +151,8 @@ class ExportOperator(bpy.types.Operator):
stats = stats.sort_stats("time", "calls") stats = stats.sort_stats("time", "calls")
stats.print_stats() stats.print_stats()
return {"FINISHED"} return {"FINISHED"}
finally:
self.export_active = False
def invoke(self, context, event): def invoke(self, context, event):
# Called when a user hits "export" from the menu # Called when a user hits "export" from the menu
@ -157,7 +174,8 @@ class ExportOperator(bpy.types.Operator):
for name, (prop, options) in cls._properties.items(): for name, (prop, options) in cls._properties.items():
# Hide these settings from being seen on the age properties # Hide these settings from being seen on the age properties
age_options = dict(options) age_options = dict(options)
age_options["options"] = {"HIDDEN"} bl_options = age_options.setdefault("options", set())
bl_options.add("HIDDEN")
# Now do the majick # Now do the majick
setattr(PlasmaAge, name, prop(**age_options)) setattr(PlasmaAge, name, prop(**age_options))

2
korman/properties/__init__.py

@ -20,6 +20,7 @@ from .prop_image import *
from .prop_lamp import * from .prop_lamp import *
from . import modifiers from . import modifiers
from .prop_object import * from .prop_object import *
from .prop_scene import *
from .prop_texture import * from .prop_texture import *
from .prop_world import * from .prop_world import *
@ -30,6 +31,7 @@ def register():
bpy.types.Lamp.plasma_lamp = bpy.props.PointerProperty(type=PlasmaLamp) bpy.types.Lamp.plasma_lamp = bpy.props.PointerProperty(type=PlasmaLamp)
bpy.types.Object.plasma_net = bpy.props.PointerProperty(type=PlasmaNet) bpy.types.Object.plasma_net = bpy.props.PointerProperty(type=PlasmaNet)
bpy.types.Object.plasma_object = bpy.props.PointerProperty(type=PlasmaObject) bpy.types.Object.plasma_object = bpy.props.PointerProperty(type=PlasmaObject)
bpy.types.Scene.plasma_scene = bpy.props.PointerProperty(type=PlasmaScene)
bpy.types.Texture.plasma_layer = bpy.props.PointerProperty(type=PlasmaLayer) bpy.types.Texture.plasma_layer = bpy.props.PointerProperty(type=PlasmaLayer)
bpy.types.World.plasma_age = bpy.props.PointerProperty(type=PlasmaAge) bpy.types.World.plasma_age = bpy.props.PointerProperty(type=PlasmaAge)
bpy.types.World.plasma_fni = bpy.props.PointerProperty(type=PlasmaFni) bpy.types.World.plasma_fni = bpy.props.PointerProperty(type=PlasmaFni)

82
korman/properties/modifiers/render.py

@ -142,12 +142,14 @@ class PlasmaFollowMod(idprops.IDPropObjectMixin, PlasmaModifierProperties):
return True return True
class PlasmaLightMapGen(idprops.IDPropMixin, PlasmaModifierProperties): class PlasmaLightMapGen(idprops.IDPropMixin, PlasmaModifierProperties, PlasmaModifierUpgradable):
pl_id = "lightmap" pl_id = "lightmap"
bl_category = "Render" bl_category = "Render"
bl_label = "Lightmap" bl_label = "Bake Lighting"
bl_description = "Auto-Bake Lightmap" bl_description = "Auto-Bake Static Lighting"
deprecated_properties = {"render_layers"}
quality = EnumProperty(name="Quality", quality = EnumProperty(name="Quality",
description="Resolution of lightmap", description="Resolution of lightmap",
@ -156,15 +158,28 @@ class PlasmaLightMapGen(idprops.IDPropMixin, PlasmaModifierProperties):
("256", "256px", "256x256 pixels"), ("256", "256px", "256x256 pixels"),
("512", "512px", "512x512 pixels"), ("512", "512px", "512x512 pixels"),
("1024", "1024px", "1024x1024 pixels"), ("1024", "1024px", "1024x1024 pixels"),
("2048", "2048px", "2048x2048 pixels"),
]) ])
bake_type = EnumProperty(name="Bake To",
description="Destination for baked lighting data",
items=[
("lightmap", "Lightmap Texture", "Bakes lighting to a lightmap texture"),
("vcol", "Vertex Colors", "Bakes lighting to vertex colors"),
],
options=set())
render_layers = BoolVectorProperty(name="Layers", render_layers = BoolVectorProperty(name="Layers",
description="Render layers to use for baking", description="DEPRECATED: Render layers to use for baking",
options=set(), options={"HIDDEN"},
subtype="LAYER", subtype="LAYER",
size=_NUM_RENDER_LAYERS, size=_NUM_RENDER_LAYERS,
default=((True,) * _NUM_RENDER_LAYERS)) default=((True,) * _NUM_RENDER_LAYERS))
bake_pass_name = StringProperty(name="Bake Pass",
description="Pass in which to bake lighting",
options=set())
lights = PointerProperty(name="Light Group", lights = PointerProperty(name="Light Group",
description="Group that defines the collection of lights to bake", description="Group that defines the collection of lights to bake",
type=bpy.types.Group) type=bpy.types.Group)
@ -172,7 +187,26 @@ class PlasmaLightMapGen(idprops.IDPropMixin, PlasmaModifierProperties):
uv_map = StringProperty(name="UV Texture", uv_map = StringProperty(name="UV Texture",
description="UV Texture used as the basis for the lightmap") description="UV Texture used as the basis for the lightmap")
@property
def bake_lightmap(self):
if not self.enabled:
return False
age = bpy.context.scene.world.plasma_age
if age.export_active:
if age.lighting_method == "force_lightmap":
return True
elif self.bake_type == "lightmap" and age.lighting_method == "bake":
return True
else:
return False
else:
return self.bake_type == "lightmap"
def export(self, exporter, bo, so): def export(self, exporter, bo, so):
# If we're exporting vertex colors, who gives a rat's behind?
if not self.bake_lightmap:
return
lightmap_im = bpy.data.images.get("{}_LIGHTMAPGEN.png".format(bo.name)) lightmap_im = bpy.data.images.get("{}_LIGHTMAPGEN.png".format(bo.name))
# If no lightmap image is found, then either lightmap generation failed (error raised by oven) # If no lightmap image is found, then either lightmap generation failed (error raised by oven)
@ -229,16 +263,38 @@ class PlasmaLightMapGen(idprops.IDPropMixin, PlasmaModifierProperties):
def key_name(self): def key_name(self):
return "{}_LIGHTMAPGEN".format(self.id_data.name) return "{}_LIGHTMAPGEN".format(self.id_data.name)
@property
def latest_version(self):
return 2
@property @property
def resolution(self): def resolution(self):
return int(self.quality) return int(self.quality)
def upgrade(self):
# In version 1, bake passes were assigned on a per modifier basis by setting
# the view layers on the modifier. Version 2 moves them into a global list
# that can be selected by name in the modifier
if self.current_version < 2:
bake_passes = bpy.context.scene.plasma_scene.bake_passes
render_layers = tuple(self.render_layers)
# Try to find a render pass matching, if possible...
bake_pass = next((i for i in bake_passes if tuple(i.render_layers) == render_layers), None)
if bake_pass is None:
bake_pass = bake_passes.add()
bake_pass.display_name = "Pass {}".format(len(bake_passes))
bake_pass.render_layers = render_layers
self.bake_pass_name = bake_pass.display_name
self.property_unset("render_layers")
self.current_version = 2
class PlasmaLightingMod(PlasmaModifierProperties): class PlasmaLightingMod(PlasmaModifierProperties):
pl_id = "lighting" pl_id = "lighting"
bl_category = "Render" bl_category = "Render"
bl_label = "Lighting" bl_label = "Lighting Info"
bl_description = "Fine tune Plasma lighting settings" bl_description = "Fine tune Plasma lighting settings"
force_rt_lights = BoolProperty(name="Force RT Lighting", force_rt_lights = BoolProperty(name="Force RT Lighting",
@ -252,10 +308,10 @@ class PlasmaLightingMod(PlasmaModifierProperties):
@property @property
def allow_preshade(self): def allow_preshade(self):
bo = self.id_data mods = self.id_data.plasma_modifiers
if bo.plasma_modifiers.water_basic.enabled: if mods.water_basic.enabled:
return False return False
if bo.plasma_modifiers.lightmap.enabled: if mods.lightmap.bake_lightmap:
return False return False
return True return True
@ -284,12 +340,12 @@ class PlasmaLightingMod(PlasmaModifierProperties):
@property @property
def want_rt_lights(self): def want_rt_lights(self):
"""Gets whether or not this object ought to be lit dynamically""" """Gets whether or not this object ought to be lit dynamically"""
bo = self.id_data mods = self.id_data.plasma_modifiers
if bo.plasma_modifiers.lightmap.enabled: if mods.lightmap.enabled and mods.lightmap.bake_type == "lightmap":
return False return False
if bo.plasma_modifiers.water_basic.enabled: if mods.water_basic.enabled:
return True return True
if bo.plasma_object.has_transform_animation: if self.id_data.plasma_object.has_transform_animation:
return True return True
return False return False

46
korman/properties/prop_scene.py

@ -0,0 +1,46 @@
# This file is part of Korman.
#
# Korman is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Korman is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Korman. If not, see <http://www.gnu.org/licenses/>.
import bpy
from bpy.props import *
from ..exporter.etlight import _NUM_RENDER_LAYERS
class PlasmaBakePass(bpy.types.PropertyGroup):
def _get_display_name(self):
return self.name
def _set_display_name(self, value):
for i in bpy.data.objects:
lm = i.plasma_modifiers.lightmap
if lm.bake_pass_name == self.name:
lm.bake_pass_name = value
self.name = value
display_name = StringProperty(name="Pass Name",
get=_get_display_name,
set=_set_display_name,
options=set())
render_layers = BoolVectorProperty(name="Layers to Bake",
description="Render layers to use for baking",
options=set(),
subtype="LAYER",
size=_NUM_RENDER_LAYERS,
default=((True,) * _NUM_RENDER_LAYERS))
class PlasmaScene(bpy.types.PropertyGroup):
bake_passes = CollectionProperty(type=PlasmaBakePass)
active_pass_index = IntProperty(options={"HIDDEN"})

1
korman/ui/__init__.py

@ -20,6 +20,7 @@ from .ui_list import *
from .ui_menus import * from .ui_menus import *
from .ui_modifiers import * from .ui_modifiers import *
from .ui_object import * from .ui_object import *
from .ui_render_layer import *
from .ui_texture import * from .ui_texture import *
from .ui_toolbox import * from .ui_toolbox import *
from .ui_world import * from .ui_world import *

30
korman/ui/modifiers/render.py

@ -16,6 +16,7 @@
import bpy import bpy
from .. import ui_list from .. import ui_list
from ...exporter.mesh import _VERTEX_COLOR_LAYERS
def fademod(modifier, layout, context): def fademod(modifier, layout, context):
layout.prop(modifier, "fader_type") layout.prop(modifier, "fader_type")
@ -73,27 +74,42 @@ def lighting(modifier, layout, context):
col.label("Other Plasma lights {} be cast at runtime.".format("will" if modifier.rt_lights else "will NOT"), col.label("Other Plasma lights {} be cast at runtime.".format("will" if modifier.rt_lights else "will NOT"),
icon="LAYER_USED") icon="LAYER_USED")
map_type = "a lightmap" if lightmap.enabled and lightmap.bake_type == "lightmap" else "vertex colors"
if lightmap.enabled and lightmap.lights: if lightmap.enabled and lightmap.lights:
col.label(" All '{}' lights will be baked to a lightmap".format(lightmap.lights), col.label("All '{}' lights will be baked to {}".format(lightmap.lights.name, map_type),
icon="LAYER_USED") icon="LAYER_USED")
elif have_static_lights: elif have_static_lights:
light_type = "Blender-only" if modifier.rt_lights else "unanimated" light_type = "Blender-only" if modifier.rt_lights else "unanimated"
map_type = "a lightmap" if lightmap.enabled else "vertex colors"
col.label("Other {} lights will be baked to {}.".format(light_type, map_type), icon="LAYER_USED") col.label("Other {} lights will be baked to {}.".format(light_type, map_type), icon="LAYER_USED")
else: else:
col.label("No static lights will be baked.", icon="LAYER_USED") col.label("No static lights will be baked.", icon="LAYER_USED")
def lightmap(modifier, layout, context): def lightmap(modifier, layout, context):
layout.row(align=True).prop(modifier, "quality", expand=True) pl_scene = context.scene.plasma_scene
layout.prop(modifier, "render_layers", text="Active Render Layers") is_texture = modifier.bake_type == "lightmap"
layout.prop(modifier, "bake_type")
if modifier.bake_type == "vcol":
col_layer = next((i for i in modifier.id_data.data.vertex_colors if i.name.lower() in _VERTEX_COLOR_LAYERS), None)
if col_layer is not None:
layout.label("Mesh color layer '{}' will override this lighting.".format(col_layer.name), icon="ERROR")
col = layout.column()
col.active = is_texture
col.prop(modifier, "quality")
layout.prop_search(modifier, "bake_pass_name", pl_scene, "bake_passes", icon="RENDERLAYERS")
layout.prop(modifier, "lights") layout.prop(modifier, "lights")
layout.prop_search(modifier, "uv_map", context.active_object.data, "uv_textures") col = layout.column()
col.active = is_texture
col.prop_search(modifier, "uv_map", context.active_object.data, "uv_textures")
# Lightmaps can only be applied to objects with opaque materials. # Lightmaps can only be applied to objects with opaque materials.
if any((i.use_transparency for i in modifier.id_data.data.materials if i is not None)): if is_texture and any((i.use_transparency for i in modifier.id_data.data.materials if i is not None)):
layout.label("Transparent objects cannot be lightmapped.", icon="ERROR") layout.label("Transparent objects cannot be lightmapped.", icon="ERROR")
else: else:
operator = layout.operator("object.plasma_lightmap_preview", "Preview Lightmap", icon="RENDER_STILL") col = layout.column()
col.active = is_texture
operator = col.operator("object.plasma_lightmap_preview", "Preview Lightmap", icon="RENDER_STILL")
# Kind of clever stuff to show the user a preview... # Kind of clever stuff to show the user a preview...
# We can't show images, so we make a hidden ImageTexture called LIGHTMAPGEN_PREVIEW. We check # We can't show images, so we make a hidden ImageTexture called LIGHTMAPGEN_PREVIEW. We check

53
korman/ui/ui_render_layer.py

@ -0,0 +1,53 @@
# This file is part of Korman.
#
# Korman is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Korman is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Korman. If not, see <http://www.gnu.org/licenses/>.
import bpy
from . import ui_list
class RenderLayerButtonsPanel:
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render_layer"
@classmethod
def poll(cls, context):
return context.scene.render.engine == "PLASMA_GAME"
class BakePassUI(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_property, index=0, flt_flag=0):
layout.prop(item, "display_name", emboss=False, text="", icon="RENDERLAYERS")
class PlasmaBakePassPanel(RenderLayerButtonsPanel, bpy.types.Panel):
bl_label = "Plasma Bake Passes"
def draw(self, context):
layout = self.layout
scene = context.scene.plasma_scene
ui_list.draw_list(layout, "BakePassUI", "scene", scene, "bake_passes",
"active_pass_index", name_prefix="Pass",
name_prop="display_name", rows=3, maxrows=3)
active_pass_index = scene.active_pass_index
try:
bake_pass = scene.bake_passes[active_pass_index]
except:
pass
else:
box = layout.box()
box.prop(bake_pass, "display_name")
box.prop(bake_pass, "render_layers")

12
korman/ui/ui_world.py

@ -133,18 +133,18 @@ class PlasmaAgePanel(AgeButtonsPanel, bpy.types.Panel):
col = split.column() col = split.column()
col.label("Export Settings:") col.label("Export Settings:")
col.prop(age, "texcache_method", text="") col.enabled = ConsoleToggler.is_platform_supported()
col.prop(age, "bake_lighting") col.prop(age, "verbose")
cons_ui = col.column() col.prop(age, "show_console")
cons_ui.enabled = ConsoleToggler.is_platform_supported()
cons_ui.prop(age, "verbose")
cons_ui.prop(age, "show_console")
col = split.column() col = split.column()
col.label("Plasma Settings:") col.label("Plasma Settings:")
col.prop(age, "age_sdl") col.prop(age, "age_sdl")
col.prop(age, "use_texture_page") col.prop(age, "use_texture_page")
layout.separator()
layout.prop(age, "lighting_method")
layout.prop(age, "texcache_method")
class PlasmaEnvironmentPanel(AgeButtonsPanel, bpy.types.Panel): class PlasmaEnvironmentPanel(AgeButtonsPanel, bpy.types.Panel):

Loading…
Cancel
Save