Newer
Older
# ##### 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 2
# 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, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
"""Import, export and render to POV engines.
These engines can be POV-Ray or Uberpov but others too, since POV is a
Scene Description Language. The script has been split in as few files
Provide property buttons for the user to set up the variables
scenography_properties.py
Initialize properties for translating Blender cam/light/environment parameters to pov
scenography_gui.py
Display cam/light/environment properties from situation_properties.py for user to change them
scenography.py
Translate cam/light/environment properties to corresponding pov features
object_properties.py :
nitialize properties for translating Blender objects parameters to pov
object_primitives.py :
Display some POV native primitives in 3D view for input and output
object_mesh_topology.py :
Translate to POV the meshes geometries
object_curve_topology.py :
Translate to POV the curve based geometries
object_particles.py :
Translate to POV the particle based geometries
object_gui.py :
Display properties from object_properties.py for user to change them
shading_properties.py
Initialize properties for translating Blender materials parameters to pov
shading_nodes.py
Translate node trees to the pov file
shading_gui.py
Display properties from shading_properties.py for user to change them
Translate shading properties to declared textures at the top of a pov file
texturing_properties.py
Initialize properties for translating Blender materials /world... texture influences to pov
texturing_gui.py
Display properties from texturing_properties.py for user to change them
texturing.py
Translate blender texture influences into POV
render_properties.py :
Initialize properties for render parameters (Blender and POV native)
render_gui.py :
Display properties from render_properties.py for user to change them
Translate render properties (Blender and POV native) to POV, ini file and bash
scripting_properties.py :
Initialize properties for scene description language parameters (POV native)
scripting_gui.py :
Display properties from scripting_properties.py for user to add his custom POV code
scripting.py :
Insert POV native scene description elements into blender scene or to exported POV file
df3_library.py
Render smoke to *.df3 files
update_files.py
Update new variables to values from older API. This file needs an update
Along these essential files also coexist a few additional libraries to help make
Blender stand up to other POV IDEs such as povwin or QTPOV
apple.py ; chicken.py ; cream.py ; Ketchup.py ; marble.py ;
potato.py ; skim_milk.py ; skin1.py ; skin2.py ; whole_milk.py
Radiosity
01_Debug.py ; 02_Fast.py ; 03_Normal.py ; 04_Two_Bounces.py ;
05_Final.py ; 06_Outdoor_Low_Quality.py ; 07_Outdoor_High_Quality.py ;
08_Outdoor(Sun)Light.py ; 09_Indoor_Low_Quality.py ;
10_Indoor_High_Quality.py ;
World
01_Clear_Blue_Sky.py ; 02_Partly_Hazy_Sky.py ; 03_Overcast_Sky.py ;
04_Cartoony_Sky.py ; 05_Under_Water.py ;
Light
01_(4800K)_Direct_Sun.py ;
02_(5400K)_High_Noon_Sun.py ;
03_(6000K)_Daylight_Window.py ;
04_(6000K)_2500W_HMI_(Halogen_Metal_Iodide).py ;
05_(4000K)_100W_Metal_Halide.py ;
06_(3200K)_100W_Quartz_Halogen.py ;
07_(2850K)_100w_Tungsten.py ;
08_(2600K)_40w_Tungsten.py ;
09_(5000K)_75W_Full_Spectrum_Fluorescent_T12.py ;
10_(4300K)_40W_Vintage_Fluorescent_T12.py ;
11_(5000K)_18W_Standard_Fluorescent_T8 ;
12_(4200K)_18W_Cool_White_Fluorescent_T8.py ;
14_(6500K)_54W_Grow_Light_Fluorescent_T5-HO.py ;
15_(3200K)_40W_Induction_Fluorescent.py ;
16_(2100K)_150W_High_Pressure_Sodium.py ;
17_(1700K)_135W_Low_Pressure_Sodium.py ;
18_(6800K)_175W_Mercury_Vapor.py ;
19_(5200K)_700W_Carbon_Arc.py ;
20_(6500K)_15W_LED_Spot.py ;
21_(2700K)_7W_OLED_Panel.py ;
23_(30000K)_40W_Black_Light_Bulb.py;
24_(1850K)_Candle.py
templates:
abyss.pov ; biscuit.pov ; bsp_Tango.pov ; chess2.pov ;
cornell.pov ; diffract.pov ; diffuse_back.pov ; float5 ;
gamma_showcase.pov ; grenadine.pov ; isocacti.pov ;
mediasky.pov ; patio-radio.pov ; subsurface.pov ; wallstucco.pov
"""
"name": "Persistence of Vision",
"author": "Campbell Barton, "
"Maurice Raybaud, "
"Leonid Desyatkov, "
"Bastien Montagne, "
"Constantin Rahn, "
"Silvio Falcinelli,"
"Paco García",
"version": (0, 1, 2),
"location": "Render Properties > Render Engine > Persistence of Vision",
"description": "Persistence of Vision integration for blender",
"doc_url": "{BLENDER_MANUAL_URL}/addons/render/povray.html",
"category": "Render",
# Other occasional contributors, more or less in chronological order:
# Luca Bonavita ; Shane Ambler ; Brendon Murphy ; Doug Hammond ;
# Thomas Dinges ; Jonathan Smith ; Sebastian Nell ; Philipp Oeser ;
# Sybren A. Stüvel ; Dalai Felinto ; Sergey Sharybin ; Brecht Van Lommel ;
# Stephen Leger ; Rune Morling ; Aaron Carlisle ; Ankit Meel ;
importlib.reload(base_ui)
importlib.reload(shading_nodes)
importlib.reload(scenography_properties)
importlib.reload(scenography)
importlib.reload(render_properties)
importlib.reload(render_gui)
importlib.reload(render)
importlib.reload(shading_properties)
importlib.reload(shading_gui)
importlib.reload(texturing_properties)
importlib.reload(texturing_gui)
importlib.reload(texturing)
importlib.reload(object_properties)
importlib.reload(object_gui)
importlib.reload(object_mesh_topology)
importlib.reload(object_curve_topology)
importlib.reload(object_primitives)
importlib.reload(scripting_gui)
importlib.reload(update_files)
from bpy.utils import register_class, unregister_class
from bpy.props import StringProperty, BoolProperty, EnumProperty
from . import (
base_ui,
render_properties,
scenography_properties,
shading_properties,
texturing_properties,
object_properties,
scripting_properties,
render,
object_primitives, # for import and export of POV specific primitives
)
# ---------------------------------------------------------------- #
# ---------------------------------------------------------------- #
class POV_OT_update_addon(bpy.types.Operator):
"""Update this addon to the latest version."""
bl_idname = "pov.update_addon"
bl_label = "Update POV addon"
def execute(self, context): # sourcery no-metrics
import os
import tempfile
import shutil
import urllib.request
import urllib.error
import zipfile
def recursive_overwrite(src, dest, ignore=None):
if os.path.isdir(src):
if not os.path.isdir(dest):
os.makedirs(dest)
files = os.listdir(src)
if ignore is not None:
ignored = ignore(src, files)
else:
ignored = set()
for f in files:
if f not in ignored:
recursive_overwrite(os.path.join(src, f), os.path.join(dest, f), ignore)
else:
shutil.copyfile(src, dest)
print('-' * 20)
print('Updating POV addon...')
with tempfile.TemporaryDirectory() as temp_dir_path:
temp_zip_path = os.path.join(temp_dir_path, 'master.zip')
# Download zip archive of latest addons master branch commit
# More work needed so we also get files from the shared addons presets /pov folder
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# switch this URL back to the BF hosted one as soon as gitweb snapshot gets fixed
url = 'https://github.com/blender/blender-addons/archive/refs/heads/master.zip'
try:
print('Downloading', url)
with urllib.request.urlopen(url, timeout=60) as url_handle, open(
temp_zip_path, 'wb'
) as file_handle:
file_handle.write(url_handle.read())
except urllib.error.URLError as err:
self.report({'ERROR'}, 'Could not download: %s' % err)
# Extract the zip
print('Extracting ZIP archive')
with zipfile.ZipFile(temp_zip_path) as zip:
for member in zip.namelist():
if 'blender-addons-master/render_povray' in member:
# Remove the first directory and the filename
# e.g. blender-addons-master/render_povray/shading_nodes.py
# becomes render_povray/shading_nodes.py
target_path = os.path.join(
temp_dir_path, os.path.join(*member.split('/')[1:-1])
)
filename = os.path.basename(member)
# Skip directories
if len(filename) == 0:
continue
# Create the target directory if necessary
if not os.path.exists(target_path):
os.makedirs(target_path)
source = zip.open(member)
target = open(os.path.join(target_path, filename), "wb")
with source, target:
shutil.copyfileobj(source, target)
print('copying', source, 'to', target)
extracted_render_povray_path = os.path.join(temp_dir_path, 'render_povray')
if not os.path.exists(extracted_render_povray_path):
self.report({'ERROR'}, 'Could not extract ZIP archive! Aborting.')
return {'FINISHED'}
# Find the old POV addon files
render_povray_dir = os.path.abspath(os.path.dirname(__file__))
print('POV addon addon folder:', render_povray_dir)
# TODO: Create backup
# Delete old POV addon files
# (only directories and *.py files, user might have other stuff in there!)
print('Deleting old POV addon files')
# remove __init__.py
os.remove(os.path.join(render_povray_dir, '__init__.py'))
# remove all folders
DIRNAMES = 1
for dir in next(os.walk(render_povray_dir))[DIRNAMES]:
shutil.rmtree(os.path.join(render_povray_dir, dir))
print('Copying new POV addon files')
# copy new POV addon files
# copy __init__.py
shutil.copy2(
os.path.join(extracted_render_povray_path, '__init__.py'), render_povray_dir
# copy all folders
recursive_overwrite(extracted_render_povray_path, render_povray_dir)
bpy.ops.preferences.addon_refresh()
print('POV addon update finished, restart Blender for the changes to take effect.')
print('-' * 20)
self.report({'WARNING'}, 'Restart Blender!')
return {'FINISHED'}
# ---------------------------------------------------------------- #
# ---------------------------------------------------------------- #
class PovrayPreferences(bpy.types.AddonPreferences):
"""Declare preference variables to set up POV binary."""
branch_feature_set_povray: EnumProperty(
name="Feature Set",
description="Choose between official (POV-Ray) or (UberPOV) "
"development branch features to write in the pov file",
("povray", "Official POV-Ray", "", "PLUGIN", 0),
("uberpov", "Unofficial UberPOV", "", "PLUGIN", 1),
filepath_povray: StringProperty(
name="Binary Location", description="Path to renderer executable", subtype="FILE_PATH"
docpath_povray: StringProperty(
name="Includes Location", description="Path to Insert Menu files", subtype="FILE_PATH"
use_sounds: BoolProperty(
name="Use Sound",
description="Signaling end of the render process at various"
"stages can help if you're away from monitor",
Maurice Raybaud
committed
# TODO: Auto find POV sound directory as it does for binary
# And implement the three cases, left uncommented for a dummy
# interface in case some doc screenshots get made for that area
filepath_complete_sound: StringProperty(
name="Finish Render Sound",
description="Path to finished render sound file",
subtype="FILE_PATH",
filepath_parse_error_sound: StringProperty(
name="Parse Error Sound",
description="Path to parsing time error sound file",
subtype="FILE_PATH",
Maurice Raybaud
committed
filepath_cancel_sound: StringProperty(
name="Cancel Render Sound",
description="Path to cancelled or render time error sound file",
subtype="FILE_PATH",
def draw(self, context):
layout = self.layout
layout.prop(self, "branch_feature_set_povray")
layout.prop(self, "filepath_povray")
layout.prop(self, "docpath_povray")
layout.prop(self, "filepath_complete_sound")
layout.prop(self, "filepath_parse_error_sound")
layout.prop(self, "filepath_cancel_sound")
layout.prop(self, "use_sounds", icon="SOUND")
layout.operator("pov.update_addon", icon='FILE_REFRESH')
classes = (
POV_OT_update_addon,
PovrayPreferences,
)
def register():
for cls in classes:
register_class(cls)
render_properties.register()
scenography_properties.register()
shading_properties.register()
texturing_properties.register()
object_properties.register()
scripting_properties.register()
render.register()
base_ui.register()
object_primitives.register()
def unregister():
object_primitives.unregister()
base_ui.unregister()
render.unregister()
scripting_properties.unregister()
object_properties.unregister()
texturing_properties.unregister()
shading_properties.unregister()
scenography_properties.unregister()
render_properties.unregister()
# ------------8<---------[ BREAKPOINT ]--------------8<----------- # Move this snippet around
# __import__('code').interact(local=dict(globals(), **locals())) # < and uncomment this line
# ---------------------------------------------------------------- # to inspect from Terminal