mirror of https://github.com/H-uru/korman.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
6.5 KiB
183 lines
6.5 KiB
# 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 * |
|
|
|
import cProfile |
|
from contextlib import contextmanager |
|
import pstats |
|
|
|
from ..exporter.etlight import LightBaker |
|
from ..exporter.explosions import ExportError |
|
from ..helpers import UiHelper |
|
from ..korlib import ConsoleToggler |
|
|
|
class _LightingOperator: |
|
@contextmanager |
|
def _oven(self, context): |
|
if context.scene.world is not None: |
|
verbose = context.scene.world.plasma_age.verbose |
|
console = context.scene.world.plasma_age.show_console |
|
else: |
|
verbose = False |
|
console = True |
|
with UiHelper(context), ConsoleToggler(console), LightBaker(verbose=verbose) as oven: |
|
yield oven |
|
|
|
@classmethod |
|
def poll(cls, context): |
|
if context.mode != "OBJECT": |
|
return False |
|
if context.object is not None: |
|
return context.scene.render.engine == "PLASMA_GAME" |
|
|
|
|
|
class LightmapAutobakePreviewOperator(_LightingOperator, bpy.types.Operator): |
|
bl_idname = "object.plasma_lightmap_preview" |
|
bl_label = "Preview Lightmap" |
|
bl_description = "Preview Lighting" |
|
bl_options = {"INTERNAL"} |
|
|
|
final = BoolProperty(name="Use this lightmap for export") |
|
|
|
def __init__(self): |
|
super().__init__() |
|
|
|
def execute(self, context): |
|
with self._oven(context) as bake: |
|
if not self.final: |
|
bake.lightmap_name = "{}_LIGHTMAPGEN_PREVIEW.png" |
|
bake.lightmap_uvtex_name = "LIGHTMAPGEN_PREVIEW" |
|
bake.force = True |
|
bake.retain_lightmap_uvtex = self.final |
|
if not bake.bake_static_lighting([context.object,]): |
|
self.report({"WARNING"}, "No valid lights found to bake.") |
|
return {"FINISHED"} |
|
|
|
lightmap_mod = context.object.plasma_modifiers.lightmap |
|
if lightmap_mod.bake_lightmap: |
|
tex = bpy.data.textures.get("LIGHTMAPGEN_PREVIEW") |
|
if tex is None: |
|
tex = bpy.data.textures.new("LIGHTMAPGEN_PREVIEW", "IMAGE") |
|
tex.extension = "CLIP" |
|
image = bake.get_lightmap(context.object) |
|
tex.image = image |
|
if self.final: |
|
lightmap_mod.image = image |
|
else: |
|
for i in context.object.data.vertex_colors: |
|
i.active = i.name == bake.vcol_layer_name |
|
|
|
return {"FINISHED"} |
|
|
|
|
|
class LightmapBakeMultiOperator(_LightingOperator, bpy.types.Operator): |
|
bl_idname = "object.plasma_lightmap_bake" |
|
bl_label = "Bake Lighting" |
|
bl_description = "Bake scene lighting to object(s)" |
|
|
|
bake_selection = BoolProperty(name="Bake Selection", |
|
description="Bake only the selected objects (else all objects)", |
|
options=set()) |
|
|
|
def __init__(self): |
|
super().__init__() |
|
|
|
def execute(self, context): |
|
profile_me = False |
|
|
|
try: |
|
if profile_me: |
|
cProfile.runctx("self._run(context)", globals(), locals(), "bake_cProfile") |
|
else: |
|
self._run(context) |
|
except ExportError as error: |
|
self.report({"ERROR"}, str(error)) |
|
return {"CANCELLED"} |
|
else: |
|
if profile_me: |
|
with open("bake_profile.log", "w") as out: |
|
stats = pstats.Stats("bake_cProfile", stream=out) |
|
stats = stats.sort_stats("time", "cumtime") |
|
stats.print_stats() |
|
return {"FINISHED"} |
|
|
|
def _run(self, context): |
|
all_objects = context.selected_objects if self.bake_selection else context.scene.objects |
|
filtered_objects = [i for i in all_objects if i.type == "MESH" and i.plasma_object.enabled] |
|
|
|
with self._oven(context) as bake: |
|
bake.force = True |
|
if not bake.bake_static_lighting(filtered_objects): |
|
self.report({"WARNING"}, "Nothing was baked.") |
|
return {"FINISHED"} |
|
|
|
for i in filtered_objects: |
|
lightmap_mod = i.plasma_modifiers.lightmap |
|
if lightmap_mod.bake_lightmap: |
|
lightmap_mod.image = bake.get_lightmap(i) |
|
|
|
|
|
class LightmapClearMultiOperator(_LightingOperator, bpy.types.Operator): |
|
bl_idname = "object.plasma_lightmap_clear" |
|
bl_label = "Clear Lighting" |
|
bl_description = "Clear baked lighting" |
|
|
|
clear_selection = BoolProperty(name="Clear Selection", |
|
description="Clear only the selected objects (else all objects)", |
|
options=set()) |
|
|
|
def __init__(self): |
|
super().__init__() |
|
|
|
def _iter_lightmaps(self, objects): |
|
yield from filter(lambda x: x.type == "MESH" and x.plasma_modifiers.lightmap.bake_lightmap, objects) |
|
|
|
def _iter_vcols(self, objects): |
|
yield from filter(lambda x: x.type == "MESH" and not x.plasma_modifiers.lightmap.bake_lightmap, objects) |
|
|
|
def execute(self, context): |
|
all_objects = context.selected_objects if self.clear_selection else context.scene.objects |
|
|
|
for i in self._iter_lightmaps(all_objects): |
|
i.plasma_modifiers.lightmap.image = None |
|
|
|
for i in self._iter_vcols(all_objects): |
|
vcols = i.data.vertex_colors |
|
col_layer = vcols.get("autocolor") |
|
if col_layer is not None: |
|
vcols.remove(col_layer) |
|
return {"FINISHED"} |
|
|
|
|
|
@bpy.app.handlers.persistent |
|
def _toss_garbage(scene): |
|
"""Removes all LIGHTMAPGEN and autocolor garbage before saving""" |
|
bpy_data = bpy.data |
|
tex = bpy_data.textures.get("LIGHTMAPGEN_PREVIEW") |
|
if tex is not None: |
|
bpy_data.textures.remove(tex) |
|
|
|
for i in bpy_data.images: |
|
if i.name.endswith("_LIGHTMAPGEN_PREVIEW.png"): |
|
bpy_data.images.remove(i) |
|
for i in bpy_data.meshes: |
|
uvtex = i.uv_textures.get("LIGHTMAPGEN_PREVIEW") |
|
if uvtex is not None: |
|
i.uv_textures.remove(uvtex) |
|
|
|
# collects light baking garbage |
|
bpy.app.handlers.save_pre.append(_toss_garbage)
|
|
|