Skip to content
Snippets Groups Projects
Commit 5417a6c0 authored by lijenstina's avatar lijenstina
Browse files

Dynamic Sky: Cleanup, Fixes

Bumped version to 1.0.2
Pep8 cleanup
add several checks to prevent crashes
add a scene prop to store the world name
avoid hardcoding the name
add some warnings in the Panel
parent 36ba3f82
No related branches found
No related tags found
No related merge requests found
# Dynamic Sky.py (c) 2015 Pratik Solanki (Draguu)
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program 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.
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
# This program 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 2
# of the License, or (at your option) any later version.
#
# ***** END GPL LICENCE BLOCK *****
# This program 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 this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
bl_info = {
"name": "Dynamic Sky",
"author": "Pratik Solanki",
"version": (1, 0, 1),
"version": (1, 0, 2),
"blender": (2, 78, 0),
"location": "View3D > Tools",
"description": "Creates Dynamic Sky for Cycles",
......@@ -27,29 +29,59 @@ bl_info = {
"wiki_url": "http://www.dragoneex.com/downloads/dynamic-skyadd-on",
"category": "Lighting",
}
import bpy
class dsky(bpy.types.Operator):
import bpy
from bpy.props import StringProperty
from bpy.types import (
Operator,
Panel,
)
# Handle error notifications
def error_handlers(self, error, reports="ERROR"):
if self and reports:
self.report({'WARNING'}, reports + " (See Console for more info)")
print("\n[Dynamic Sky]\nError: {}\n".format(error))
def check_world_name(name_id="Dynamic"):
# check if the new name pattern is in world data
name_list = []
suffix = 1
try:
name_list = [world.name for world in bpy.data.worlds if name_id in world.name]
new_name = "{}_{}".format(name_id, len(name_list) + suffix)
if new_name in name_list:
# KISS failed - numbering is not sequential
# try harvesting numbers in world names, find the rightmost ones
test_num = []
from re import findall
for words in name_list:
test_num.append(findall("\d+", words))
suffix += max([int(l[-1]) for l in test_num])
new_name = "{}_{}".format(name_id, suffix)
return new_name
except Exception as e:
error_handlers(False, e)
pass
return name_id
class dsky(Operator):
bl_idname = "sky.dyn"
bl_label = "Make a Procidural sky"
bl_label = "Make a Procedural sky"
bl_description = "Make a Procedural Sky"
def execute(self, context):
try:
get_name = check_world_name()
context.scene.dynamic_sky_name = get_name
bpy.context.scene.render.engine = 'CYCLES'
def clean_node_tree(node_tree):
nodes = node_tree.nodes
for node in nodes:
if not node.type == 'OUTPUT_WORLD':
nodes.remove(node)
return node_tree.nodes[0]
bpy.context.scene.render.engine = 'CYCLES'
def dynamic():
world = bpy.data.worlds.new('Dynamic')
world = bpy.data.worlds.new(get_name)
world.cycles.sample_as_light = True
world.cycles.sample_map_resolution = 2048
world.use_nodes = True
......@@ -66,110 +98,110 @@ class dsky(bpy.types.Operator):
nor = nt.nodes.new(type="ShaderNodeNormal")
cr1 = nt.nodes.new(type ="ShaderNodeValToRGB")
cr1 = nt.nodes.new(type="ShaderNodeValToRGB")
cr1.color_ramp.elements[0].position = 0.969
cr1.color_ramp.interpolation = 'EASE'
cr2 = nt.nodes.new(type ="ShaderNodeValToRGB")
cr2 = nt.nodes.new(type="ShaderNodeValToRGB")
cr2.color_ramp.elements[0].position = 0.991
cr2.color_ramp.elements[1].position = 1
cr2.color_ramp.interpolation = 'EASE'
cr3 = nt.nodes.new(type ="ShaderNodeValToRGB")
cr3 = nt.nodes.new(type="ShaderNodeValToRGB")
cr3.color_ramp.elements[0].position = 0.779
cr3.color_ramp.elements[1].position = 1
cr3.color_ramp.interpolation = 'EASE'
mat1 = nt.nodes.new(type ="ShaderNodeMath")
mat1 = nt.nodes.new(type="ShaderNodeMath")
mat1.operation = 'MULTIPLY'
mat1.inputs[1].default_value = 0.2
mat2 = nt.nodes.new(type ="ShaderNodeMath")
mat2 = nt.nodes.new(type="ShaderNodeMath")
mat2.operation = 'MULTIPLY'
mat2.inputs[1].default_value = 2
mat3 = nt.nodes.new(type ="ShaderNodeMath")
mat3 = nt.nodes.new(type="ShaderNodeMath")
mat3.operation = 'MULTIPLY'
mat3.inputs[1].default_value = 40.9
mat4 = nt.nodes.new(type ="ShaderNodeMath")
mat4 = nt.nodes.new(type="ShaderNodeMath")
mat4.operation = 'SUBTRACT'
mat4.inputs[1].default_value = 1
ntl(mat2.inputs[0],mat1.outputs[0])
ntl(mat4.inputs[0],mat3.outputs[0])
ntl(mat1.inputs[0],cr3.outputs[0])
ntl(mat3.inputs[0],cr2.outputs[0])
ntl(mat2.inputs[0], mat1.outputs[0])
ntl(mat4.inputs[0], mat3.outputs[0])
ntl(mat1.inputs[0], cr3.outputs[0])
ntl(mat3.inputs[0], cr2.outputs[0])
soft = nt.nodes.new(type = "ShaderNodeMixRGB")
soft_1 = nt.nodes.new(type = "ShaderNodeMixRGB")
soft = nt.nodes.new(type="ShaderNodeMixRGB")
soft_1 = nt.nodes.new(type="ShaderNodeMixRGB")
soft.inputs[0].default_value = 1
soft_1.inputs[0].default_value = 0.466
ntl(soft.inputs[1],mat2.outputs[0])
ntl(soft.inputs[2],mat4.outputs[0])
ntl(soft_1.inputs[1],mat2.outputs[0])
ntl(soft_1.inputs[2],cr2.outputs[0])
ntl(soft.inputs[1], mat2.outputs[0])
ntl(soft.inputs[2], mat4.outputs[0])
ntl(soft_1.inputs[1], mat2.outputs[0])
ntl(soft_1.inputs[2], cr2.outputs[0])
mix1 = nt.nodes.new(type = "ShaderNodeMixRGB")
mix1 = nt.nodes.new(type="ShaderNodeMixRGB")
mix1.blend_type = 'MULTIPLY'
mix1.inputs[0].default_value = 1
mix1_1 = nt.nodes.new(type = "ShaderNodeMixRGB")
mix1_1 = nt.nodes.new(type="ShaderNodeMixRGB")
mix1_1.blend_type = 'MULTIPLY'
mix1_1.inputs[0].default_value = 1
mix2 = nt.nodes.new(type = "ShaderNodeMixRGB")
mix2_1 = nt.nodes.new(type = "ShaderNodeMixRGB")
mix2 = nt.nodes.new(type="ShaderNodeMixRGB")
mix2_1 = nt.nodes.new(type="ShaderNodeMixRGB")
mix2.inputs[1].default_value = (0, 0, 0, 1)
mix2.inputs[2].default_value = (32, 22, 14, 200)
mix2_1.inputs[1].default_value = (0, 0, 0, 1)
mix2_1.inputs[2].default_value = (1, 0.820, 0.650,1)
mix2_1.inputs[2].default_value = (1, 0.820, 0.650, 1)
ntl(mix1.inputs[1],soft.outputs[0])
ntl(mix1_1.inputs[1],soft_1.outputs[0])
ntl(mix2.inputs[0],mix1.outputs[0])
ntl(mix2_1.inputs[0],mix1_1.outputs[0])
ntl(mix1.inputs[1], soft.outputs[0])
ntl(mix1_1.inputs[1], soft_1.outputs[0])
ntl(mix2.inputs[0], mix1.outputs[0])
ntl(mix2_1.inputs[0], mix1_1.outputs[0])
gam = nt.nodes.new(type = "ShaderNodeGamma")
gam = nt.nodes.new(type="ShaderNodeGamma")
gam.inputs[1].default_value = 2.3
gam2 = nt.nodes.new(type = "ShaderNodeGamma")
gam2 = nt.nodes.new(type="ShaderNodeGamma")
gam2.inputs[1].default_value = 1
gam3 = nt.nodes.new(type = "ShaderNodeGamma")
gam3 = nt.nodes.new(type="ShaderNodeGamma")
gam3.inputs[1].default_value = 1
sunopa = nt.nodes.new(type = "ShaderNodeMixRGB")
sunopa = nt.nodes.new(type="ShaderNodeMixRGB")
sunopa.blend_type = 'ADD'
sunopa.inputs[0].default_value = 1
sunopa_1 = nt.nodes.new(type = "ShaderNodeMixRGB")
sunopa_1 = nt.nodes.new(type="ShaderNodeMixRGB")
sunopa_1.blend_type = 'ADD'
sunopa_1.inputs[0].default_value = 1
combine = nt.nodes.new(type = "ShaderNodeMixRGB")
ntl(combine.inputs[1],sunopa.outputs[0])
ntl(combine.inputs[2],sunopa_1.outputs[0])
lp = nt.nodes.new(type = "ShaderNodeLightPath")
ntl(combine.inputs[0],lp.outputs[0])
combine = nt.nodes.new(type="ShaderNodeMixRGB")
ntl(combine.inputs[1], sunopa.outputs[0])
ntl(combine.inputs[2], sunopa_1.outputs[0])
lp = nt.nodes.new(type="ShaderNodeLightPath")
ntl(combine.inputs[0], lp.outputs[0])
ntl(gam2.inputs[0],gam.outputs[0])
ntl(gam.inputs[0],mix2.outputs[0])
ntl(bg.inputs[0],combine.outputs[0])
ntl(gam2.inputs[0], gam.outputs[0])
ntl(gam.inputs[0], mix2.outputs[0])
ntl(bg.inputs[0], combine.outputs[0])
map2 = nt.nodes.new(type = "ShaderNodeMapping")
map2 = nt.nodes.new(type="ShaderNodeMapping")
map2.scale[2] = 6.00
map2.scale[0] = 1.5
map2.scale[1] = 1.5
n1 = nt.nodes.new(type = "ShaderNodeTexNoise")
n1 = nt.nodes.new(type="ShaderNodeTexNoise")
n1.inputs[1].default_value = 3.8
n1.inputs[2].default_value = 2.4
n1.inputs[3].default_value = 0.5
n2 = nt.nodes.new(type = "ShaderNodeTexNoise")
n2 = nt.nodes.new(type="ShaderNodeTexNoise")
n2.inputs[1].default_value = 2.0
n2.inputs[2].default_value = 10
n2.inputs[3].default_value = 0.2
ntl(n2.inputs[0],map2.outputs[0])
ntl(n1.inputs[0],map2.outputs[0])
ntl(n2.inputs[0], map2.outputs[0])
ntl(n1.inputs[0], map2.outputs[0])
sc1 = nt.nodes.new(type = "ShaderNodeValToRGB")
sc2 = nt.nodes.new(type = "ShaderNodeValToRGB")
sc3 = nt.nodes.new(type = "ShaderNodeValToRGB")
sc3_1 = nt.nodes.new(type = "ShaderNodeValToRGB")
sc4 = nt.nodes.new(type = "ShaderNodeValToRGB")
sc1 = nt.nodes.new(type="ShaderNodeValToRGB")
sc2 = nt.nodes.new(type="ShaderNodeValToRGB")
sc3 = nt.nodes.new(type="ShaderNodeValToRGB")
sc3_1 = nt.nodes.new(type="ShaderNodeValToRGB")
sc4 = nt.nodes.new(type="ShaderNodeValToRGB")
sc1.color_ramp.elements[1].position = 0.649
sc1.color_ramp.elements[0].position = 0.408
......@@ -200,12 +232,12 @@ class dsky(bpy.types.Operator):
sc3_1.color_ramp.elements[0].color = (0, 0, 0, 0)
sc3_1.color_ramp.elements[0].position = 0.0
smix1 = nt.nodes.new(type = "ShaderNodeMixRGB")
smix2 = nt.nodes.new(type = "ShaderNodeMixRGB")
smix2_1 = nt.nodes.new(type = "ShaderNodeMixRGB")
smix3 = nt.nodes.new(type = "ShaderNodeMixRGB")
smix4 = nt.nodes.new(type = "ShaderNodeMixRGB")
smix5 = nt.nodes.new(type = "ShaderNodeMixRGB")
smix1 = nt.nodes.new(type="ShaderNodeMixRGB")
smix2 = nt.nodes.new(type="ShaderNodeMixRGB")
smix2_1 = nt.nodes.new(type="ShaderNodeMixRGB")
smix3 = nt.nodes.new(type="ShaderNodeMixRGB")
smix4 = nt.nodes.new(type="ShaderNodeMixRGB")
smix5 = nt.nodes.new(type="ShaderNodeMixRGB")
smix1.inputs[1].default_value = (1, 1, 1, 1)
smix1.inputs[2].default_value = (0, 0, 0, 1)
......@@ -221,65 +253,124 @@ class dsky(bpy.types.Operator):
smix5.blend_type = 'SCREEN'
smix5.inputs[0].default_value = 1
srgb = nt.nodes.new(type = "ShaderNodeSeparateRGB")
aniadd = nt.nodes.new(type = "ShaderNodeMath")
crgb = nt.nodes.new(type = "ShaderNodeCombineRGB")
sunrgb = nt.nodes.new(type = "ShaderNodeMixRGB")
srgb = nt.nodes.new(type="ShaderNodeSeparateRGB")
aniadd = nt.nodes.new(type="ShaderNodeMath")
crgb = nt.nodes.new(type="ShaderNodeCombineRGB")
sunrgb = nt.nodes.new(type="ShaderNodeMixRGB")
sunrgb.blend_type = 'MULTIPLY'
sunrgb.inputs[2].default_value = (32, 30, 30, 200)
sunrgb.inputs[0].default_value = 1
ntl(mix2.inputs[2],sunrgb.outputs[0])
ntl(smix1.inputs[0],sc2.outputs[0])
ntl(smix2.inputs[1],smix1.outputs[0])
ntl(smix2.inputs[2],sc1.outputs[0])
ntl(smix2_1.inputs[2],sc3_1.outputs[0])
ntl(smix3.inputs[0],sc4.outputs[0])
ntl(smix4.inputs[2],smix3.outputs[0])
ntl(smix4.inputs[1],sc3.outputs[0])
ntl(smix5.inputs[1],smix4.outputs[0])
ntl(smix2_1.inputs[1],smix2.outputs[0])
ntl(smix5.inputs[2],smix2_1.outputs[0])
ntl(sunopa.inputs[1],gam3.outputs[0])
ntl(gam3.inputs[0],smix5.outputs[0])
ntl(mix1.inputs[2],sc3.outputs[0])
ntl(sunopa.inputs[2],gam2.outputs[0])
ntl(sc1.inputs[0],n1.outputs[0])
ntl(sc2.inputs[0],n2.outputs[0])
skynor = nt.nodes.new(type = "ShaderNodeNormal")
ntl(sc3.inputs[0],skynor.outputs[1])
ntl(sc4.inputs[0],skynor.outputs[1])
ntl(sc3_1.inputs[0],skynor.outputs[1])
ntl(map2.inputs[0],crgb.outputs[0])
ntl(skynor.inputs[0],tcor.outputs[0])
ntl(mix1_1.inputs[2],sc3.outputs[0])
ntl(srgb.inputs[0],tcor.outputs[0])
ntl(crgb.inputs[1],srgb.outputs[1])
ntl(crgb.inputs[2],srgb.outputs[2])
ntl(aniadd.inputs[1],srgb.outputs[0])
ntl(crgb.inputs[0],aniadd.outputs[0])
#-------------
ntl(cr1.inputs[0],nor.outputs[1])
ntl(cr2.inputs[0],cr1.outputs[0])
ntl(cr3.inputs[0],nor.outputs[1])
ntl(nor.inputs[0],map.outputs[0])
ntl(map.inputs[0],tcor.outputs[0])
ntl(sunopa_1.inputs[1],smix5.outputs[0])
ntl(sunopa_1.inputs[2],mix2_1.outputs[0])
dynamic()
ntl(mix2.inputs[2], sunrgb.outputs[0])
ntl(smix1.inputs[0], sc2.outputs[0])
ntl(smix2.inputs[1], smix1.outputs[0])
ntl(smix2.inputs[2], sc1.outputs[0])
ntl(smix2_1.inputs[2], sc3_1.outputs[0])
ntl(smix3.inputs[0], sc4.outputs[0])
ntl(smix4.inputs[2], smix3.outputs[0])
ntl(smix4.inputs[1], sc3.outputs[0])
ntl(smix5.inputs[1], smix4.outputs[0])
ntl(smix2_1.inputs[1], smix2.outputs[0])
ntl(smix5.inputs[2], smix2_1.outputs[0])
ntl(sunopa.inputs[1], gam3.outputs[0])
ntl(gam3.inputs[0], smix5.outputs[0])
ntl(mix1.inputs[2], sc3.outputs[0])
ntl(sunopa.inputs[2], gam2.outputs[0])
ntl(sc1.inputs[0], n1.outputs[0])
ntl(sc2.inputs[0], n2.outputs[0])
skynor = nt.nodes.new(type="ShaderNodeNormal")
ntl(sc3.inputs[0], skynor.outputs[1])
ntl(sc4.inputs[0], skynor.outputs[1])
ntl(sc3_1.inputs[0], skynor.outputs[1])
ntl(map2.inputs[0], crgb.outputs[0])
ntl(skynor.inputs[0], tcor.outputs[0])
ntl(mix1_1.inputs[2], sc3.outputs[0])
ntl(srgb.inputs[0], tcor.outputs[0])
ntl(crgb.inputs[1], srgb.outputs[1])
ntl(crgb.inputs[2], srgb.outputs[2])
ntl(aniadd.inputs[1], srgb.outputs[0])
ntl(crgb.inputs[0], aniadd.outputs[0])
ntl(cr1.inputs[0], nor.outputs[1])
ntl(cr2.inputs[0], cr1.outputs[0])
ntl(cr3.inputs[0], nor.outputs[1])
ntl(nor.inputs[0], map.outputs[0])
ntl(map.inputs[0], tcor.outputs[0])
ntl(sunopa_1.inputs[1], smix5.outputs[0])
ntl(sunopa_1.inputs[2], mix2_1.outputs[0])
except Exception as e:
error_handlers(self, e, "Make a Procedural sky has failed")
return {"CANCELLED"}
return {'FINISHED'}
class Dynapanel(bpy.types.Panel):
def draw_world_settings(col, context):
get_world = context.scene.world
stored_name = context.scene.dynamic_sky_name
get_world_keys = bpy.data.worlds.keys()
if stored_name not in get_world_keys or len(get_world_keys) < 1:
col.label(text="The {} World could not".format(stored_name),
icon="INFO")
col.label(text="be found in the Worlds' Data", icon="BLANK1")
return
elif not (get_world and get_world.name == stored_name):
col.label(text="Please select the World", icon="INFO")
col.label(text="named {}".format(stored_name), icon="BLANK1")
col.label(text="from the Properties > World", icon="BLANK1")
return
pick_world = bpy.data.worlds[stored_name]
try:
m = pick_world.node_tree.nodes[28]
m = pick_world.node_tree.nodes['Mix.012'].inputs[1]
n = pick_world.node_tree.nodes['Mix.012'].inputs[2]
o = pick_world.node_tree.nodes['Mix.014'].inputs[0]
d = pick_world.node_tree.nodes['Mix.010'].inputs[0]
so = pick_world.node_tree.nodes['Gamma.001'].inputs[1]
so2 = pick_world.node_tree.nodes['Gamma.002'].inputs[1]
# sc = pick_world.node_tree.nodes['Mix.004'].inputs[2]
no = pick_world.node_tree.nodes['Normal'].outputs[0]
sof = pick_world.node_tree.nodes['Mix'].inputs[0]
bgp = pick_world.node_tree.nodes['Background'].inputs[1]
suc = pick_world.node_tree.nodes['Mix.015'].inputs[1]
except:
col.label(text="Please Create a new World", icon="INFO")
col.label(text="seems that there was already", icon="BLANK1")
col.label(text="one called {}".format(stored_name), icon="BLANK1")
return
col.label("World: %s" % stored_name)
col.separator()
col.label("Scene Control")
col.prop(bgp, "default_value", text="Brightness")
col.prop(so2, "default_value", text="Shadow color saturation")
col.label("Sky Control")
col.prop(m, "default_value", text="Cloud color")
col.prop(n, "default_value", text="Horizon Color")
col.prop(o, "default_value", text="Cloud opacity")
col.prop(d, "default_value", text="Cloud density")
col.label("Sun Control")
col.prop(suc, "default_value", text="")
col.prop(so, "default_value", text="Sun value")
col.prop(sof, "default_value", text="Soft hard")
col.prop(no, "default_value", text="")
class Dynapanel(Panel):
bl_label = "Dynamic sky"
bl_idname = "SCENE_PT_layout"
bl_space_type = 'VIEW_3D'
......@@ -289,60 +380,26 @@ class Dynapanel(bpy.types.Panel):
def draw(self, context):
layout = self.layout
scene = context.scene
layout.operator("sky.dyn", text="Create", icon='MAT_SPHERE_SKY')
layout.operator("sky.dyn", text = "Create", icon='MAT_SPHERE_SKY')
if bpy.data.worlds['Dynamic']:
col = layout.column()
m = bpy.data.worlds['Dynamic'].node_tree.nodes[28]
m = bpy.data.worlds['Dynamic'].node_tree.nodes['Mix.012'].inputs[1]
n = bpy.data.worlds['Dynamic'].node_tree.nodes['Mix.012'].inputs[2]
o = bpy.data.worlds['Dynamic'].node_tree.nodes['Mix.014'].inputs[0]
d = bpy.data.worlds['Dynamic'].node_tree.nodes['Mix.010'].inputs[0]
so = bpy.data.worlds['Dynamic'].node_tree.nodes['Gamma.001'].inputs[1]
so2 = bpy.data.worlds['Dynamic'].node_tree.nodes['Gamma.002'].inputs[1]
sc = bpy.data.worlds['Dynamic'].node_tree.nodes['Mix.004'].inputs[2]
no = bpy.data.worlds['Dynamic'].node_tree.nodes['Normal'].outputs[0]
sof = bpy.data.worlds['Dynamic'].node_tree.nodes['Mix'].inputs[0]
bgp = bpy.data.worlds['Dynamic'].node_tree.nodes['Background'].inputs[1]
suc = bpy.data.worlds['Dynamic'].node_tree.nodes['Mix.015'].inputs[1]
col.label("Scene Control")
col.prop(bgp, "default_value", text="Brightness")
col.prop(so2, "default_value", text="Shadow color saturation")
col.label("---------------------------------------------------------")
col.label("Sky Control")
col.prop(m,"default_value", text="Cloud color")
col.prop(n, "default_value", text="Horizon Color")
col.prop(o, "default_value", text="Cloud opacity")
col.prop(d, "default_value", text="Cloud density")
col.label("---------------------------------------------------------")
col.label("Sun Control")
col.prop(suc, "default_value", text="")
col.prop(so, "default_value", text="Sun value")
col.prop(sof, "default_value", text="Soft hard")
col.prop(no, "default_value", text="")
else:
col = layout.column()
col.label("---------------------------------------------------------")
col = layout.column()
draw_world_settings(col, context)
def register():
bpy.utils.register_class(Dynapanel)
bpy.utils.register_class(dsky)
bpy.types.Scene.dynamic_sky_name = StringProperty(
name="",
default="Dynamic"
)
def unregister():
bpy.utils.unregister_class(Dynapanel)
bpy.utils.unregister_class(dsky)
del bpy.types.Scene.dynamic_sky_name
if __name__ == "__main__":
register()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment