From 4779c8c710fc620cef3f261a0656d7cd355640ac Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sat, 8 Sep 2018 21:00:45 -0400 Subject: [PATCH] Centralize lightmap render layer settings This allows the artist to control what happens with lightmaps more easily when there are lots of lightmapped objects in the age. Fixes #118 --- korman/exporter/etlight.py | 11 +++++- korman/properties/__init__.py | 2 + korman/properties/modifiers/render.py | 34 +++++++++++++++-- korman/properties/prop_scene.py | 46 +++++++++++++++++++++++ korman/ui/__init__.py | 1 + korman/ui/modifiers/render.py | 3 +- korman/ui/ui_render_layer.py | 53 +++++++++++++++++++++++++++ 7 files changed, 145 insertions(+), 5 deletions(-) create mode 100644 korman/properties/prop_scene.py create mode 100644 korman/ui/ui_render_layer.py diff --git a/korman/exporter/etlight.py b/korman/exporter/etlight.py index 402e870..bf8c2f6 100644 --- a/korman/exporter/etlight.py +++ b/korman/exporter/etlight.py @@ -221,6 +221,7 @@ class LightBaker(_MeshManager): # that needs to be baked and sort it out by configuration. bake = { ("vcol",): [] } bake_vcol = bake[("vcol",)] + bake_passes = bpy.context.scene.plasma_scene.bake_passes for i in objs: if i.type != "MESH": @@ -231,9 +232,17 @@ class LightBaker(_MeshManager): mods = i.plasma_modifiers lightmap_mod = mods.lightmap 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("Lightmap '{}': Could not find pass '{}'".format(i.name, lightmap_mod.bake_pass_name)) + lm_layers = tuple(bake_pass.render_layers) + else: + lm_layers = tuple((True,) * _NUM_RENDER_LAYERS) + # 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. - 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)) obj_active_layers = set((i for i, value in enumerate(obj_layers) if value)) if not lm_active_layers & obj_active_layers: diff --git a/korman/properties/__init__.py b/korman/properties/__init__.py index 4da436b..d8ea5e6 100644 --- a/korman/properties/__init__.py +++ b/korman/properties/__init__.py @@ -20,6 +20,7 @@ from .prop_image import * from .prop_lamp import * from . import modifiers from .prop_object import * +from .prop_scene import * from .prop_texture import * from .prop_world import * @@ -30,6 +31,7 @@ def register(): bpy.types.Lamp.plasma_lamp = bpy.props.PointerProperty(type=PlasmaLamp) bpy.types.Object.plasma_net = bpy.props.PointerProperty(type=PlasmaNet) 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.World.plasma_age = bpy.props.PointerProperty(type=PlasmaAge) bpy.types.World.plasma_fni = bpy.props.PointerProperty(type=PlasmaFni) diff --git a/korman/properties/modifiers/render.py b/korman/properties/modifiers/render.py index bd4ae04..f253655 100644 --- a/korman/properties/modifiers/render.py +++ b/korman/properties/modifiers/render.py @@ -142,13 +142,15 @@ class PlasmaFollowMod(idprops.IDPropObjectMixin, PlasmaModifierProperties): return True -class PlasmaLightMapGen(idprops.IDPropMixin, PlasmaModifierProperties): +class PlasmaLightMapGen(idprops.IDPropMixin, PlasmaModifierProperties, PlasmaModifierUpgradable): pl_id = "lightmap" bl_category = "Render" bl_label = "Lightmap" bl_description = "Auto-Bake Lightmap" + deprecated_properties = {"render_layers"} + quality = EnumProperty(name="Quality", description="Resolution of lightmap", items=[ @@ -159,12 +161,16 @@ class PlasmaLightMapGen(idprops.IDPropMixin, PlasmaModifierProperties): ]) render_layers = BoolVectorProperty(name="Layers", - description="Render layers to use for baking", - options=set(), + description="DEPRECATED: Render layers to use for baking", + options={"HIDDEN"}, subtype="LAYER", size=_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", description="Group that defines the collection of lights to bake", type=bpy.types.Group) @@ -229,10 +235,32 @@ class PlasmaLightMapGen(idprops.IDPropMixin, PlasmaModifierProperties): def key_name(self): return "{}_LIGHTMAPGEN".format(self.id_data.name) + @property + def latest_version(self): + return 2 + @property def resolution(self): 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): pl_id = "lighting" diff --git a/korman/properties/prop_scene.py b/korman/properties/prop_scene.py new file mode 100644 index 0000000..074df1e --- /dev/null +++ b/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 . + +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"}) diff --git a/korman/ui/__init__.py b/korman/ui/__init__.py index d1ef238..3369bb7 100644 --- a/korman/ui/__init__.py +++ b/korman/ui/__init__.py @@ -20,6 +20,7 @@ from .ui_list import * from .ui_menus import * from .ui_modifiers import * from .ui_object import * +from .ui_render_layer import * from .ui_texture import * from .ui_toolbox import * from .ui_world import * diff --git a/korman/ui/modifiers/render.py b/korman/ui/modifiers/render.py index df55ee4..79deb5e 100644 --- a/korman/ui/modifiers/render.py +++ b/korman/ui/modifiers/render.py @@ -84,8 +84,9 @@ def lighting(modifier, layout, context): col.label("No static lights will be baked.", icon="LAYER_USED") def lightmap(modifier, layout, context): + pl_scene = context.scene.plasma_scene layout.row(align=True).prop(modifier, "quality", expand=True) - layout.prop(modifier, "render_layers", text="Active Render Layers") + layout.prop_search(modifier, "bake_pass_name", pl_scene, "bake_passes", icon="RENDERLAYERS") layout.prop(modifier, "lights") layout.prop_search(modifier, "uv_map", context.active_object.data, "uv_textures") diff --git a/korman/ui/ui_render_layer.py b/korman/ui/ui_render_layer.py new file mode 100644 index 0000000..d87f04b --- /dev/null +++ b/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 . + +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")