Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archipack/archipack_object.py2
-rw-r--r--archipack/archipack_wall2.py2
-rw-r--r--blenderkit/ui.py2
-rwxr-xr-xio_scene_gltf2/__init__.py2
-rw-r--r--measureit/measureit_geometry.py4
-rw-r--r--render_povray/__init__.py358
-rw-r--r--render_povray/nodes.py33
-rw-r--r--render_povray/primitives.py55
-rw-r--r--render_povray/render.py362
-rw-r--r--render_povray/shading.py144
-rw-r--r--render_povray/ui.py749
11 files changed, 1305 insertions, 408 deletions
diff --git a/archipack/archipack_object.py b/archipack/archipack_object.py
index 8c908214..f513b506 100644
--- a/archipack/archipack_object.py
+++ b/archipack/archipack_object.py
@@ -259,7 +259,7 @@ class ArchipackDrawTool(ArchipackCollectionManager):
view_vector_mouse = region_2d_to_vector_3d(region, rv3d, co2d)
ray_origin_mouse = region_2d_to_origin_3d(region, rv3d, co2d)
res, pos, normal, face_index, object, matrix_world = context.scene.ray_cast(
- view_layer=context.view_layer,
+ depsgraph=context.view_layer.depsgraph,
origin=ray_origin_mouse,
direction=view_vector_mouse)
return res, pos, normal, face_index, object, matrix_world
diff --git a/archipack/archipack_wall2.py b/archipack/archipack_wall2.py
index d9a486eb..53375992 100644
--- a/archipack/archipack_wall2.py
+++ b/archipack/archipack_wall2.py
@@ -1639,7 +1639,7 @@ class archipack_wall2(ArchipackObject, Manipulable, PropertyGroup):
# prevent self intersect
o.hide_viewport = True
res, pos, normal, face_index, r, matrix_world = context.scene.ray_cast(
- view_layer=context.view_layer,
+ depsgraph=context.view_layer.depsgraph,
origin=p,
direction=up)
diff --git a/blenderkit/ui.py b/blenderkit/ui.py
index 5333b65e..47bf1a51 100644
--- a/blenderkit/ui.py
+++ b/blenderkit/ui.py
@@ -927,7 +927,7 @@ def mouse_raycast(context, mx, my):
vec = ray_target - ray_origin
has_hit, snapped_location, snapped_normal, face_index, object, matrix = bpy.context.scene.ray_cast(
- bpy.context.view_layer, ray_origin, vec)
+ bpy.context.view_layer.depsgraph, ray_origin, vec)
# rote = mathutils.Euler((0, 0, math.pi))
randoffset = math.pi
diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py
index bcdb9cf0..bafd7501 100755
--- a/io_scene_gltf2/__init__.py
+++ b/io_scene_gltf2/__init__.py
@@ -15,7 +15,7 @@
bl_info = {
'name': 'glTF 2.0 format',
'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
- "version": (1, 3, 44),
+ "version": (1, 4, 2),
'blender': (2, 90, 0),
'location': 'File > Import-Export',
'description': 'Import-Export as glTF 2.0',
diff --git a/measureit/measureit_geometry.py b/measureit/measureit_geometry.py
index 1f314f7f..998bc038 100644
--- a/measureit/measureit_geometry.py
+++ b/measureit/measureit_geometry.py
@@ -413,7 +413,7 @@ def draw_segments(context, myobj, op, region, rv3d):
if ms.gltype == 11: # arc
# print length or arc and angle
if ms.glarc_len is True:
- tx_dist = ms.glarc_txlen + format_distance(fmt, units, arc_length)
+ tx_dist = ms.glarc_txlen + format_distance(fmt, units, arc_length * scale)
else:
tx_dist = " "
@@ -453,7 +453,7 @@ def draw_segments(context, myobj, op, region, rv3d):
if scene.measureit_gl_show_d is True and ms.gldist is True and \
ms.glarc_rad is True:
tx_dist = ms.glarc_txradio + format_distance(fmt, units,
- dist * scene.measureit_scale_factor)
+ dist * scene.measureit_scale_factor * scale)
else:
tx_dist = " "
if ms.gltype == 2:
diff --git a/render_povray/__init__.py b/render_povray/__init__.py
index 7a6332ee..fded5cff 100644
--- a/render_povray/__init__.py
+++ b/render_povray/__init__.py
@@ -25,16 +25,16 @@ Scene Description Language. The script has been split in as few files
as possible :
___init__.py :
- Initialize variables
+ Initialize properties
update_files.py
- Update new variables to values from older API. This file needs an update.
+ Update new variables to values from older API. This file needs an update
ui.py :
- Provide property buttons for the user to set up the variables.
+ Provide property buttons for the user to set up the variables
primitives.py :
- Display some POV native primitives in 3D view for input and output.
+ Display some POV native primitives in 3D view for input and output
shading.py
Translate shading properties to declared textures at the top of a pov file
@@ -50,7 +50,7 @@ render.py :
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.
+Blender stand up to other POV IDEs such as povwin or QTPOV
presets :
Material (sss)
apple.py ; chicken.py ; cream.py ; Ketchup.py ; marble.py ;
@@ -64,11 +64,14 @@ Blender stand up to other POV IDEs such as povwin or QTPOV.
01_Clear_Blue_Sky.py ; 02_Partly_Hazy_Sky.py ; 03_Overcast_Sky.py ;
04_Cartoony_Sky.py ; 05_Under_Water.py ;
Light
- 01_(5400K)_Direct_Sun.py ; 02_(5400K)_High_Noon_Sun.py ;
+ 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 ;
+ 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 ;
@@ -78,10 +81,13 @@ Blender stand up to other POV IDEs such as povwin or QTPOV.
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 ;
+ 18_(6800K)_175W_Mercury_Vapor.py ;
+ 19_(5200K)_700W_Carbon_Arc.py ;
+ 20_(6500K)_15W_LED_Spot.py ;
+ 21_(2700K)_7W_OLED_Panel.py ;
22_(30000K)_40W_Black_Light_Fluorescent.py ;
- 23_(30000K)_40W_Black_Light_Bulb.py; 24_(1850K)_Candle.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 ;
@@ -98,20 +104,23 @@ bl_info = {
"Bastien Montagne, "
"Constantin Rahn, "
"Silvio Falcinelli",
- "version": (0, 1, 0),
+ "version": (0, 1, 1),
"blender": (2, 81, 0),
"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",
+ "warning": "Under active development, seeking co-maintainer(s)",
}
if "bpy" in locals():
import importlib
importlib.reload(ui)
+ importlib.reload(nodes)
importlib.reload(render)
importlib.reload(shading)
+ importlib.reload(primitives)
importlib.reload(update_files)
else:
@@ -121,13 +130,18 @@ else:
import nodeitems_utils # for Nodes
from nodeitems_utils import NodeCategory, NodeItem # for Nodes
from bl_operators.presets import AddPresetBase
- from bpy.types import AddonPreferences, PropertyGroup
+ from bpy.types import (
+ AddonPreferences,
+ PropertyGroup,
+ NodeSocket,
+ )
+
from bpy.props import (
+ FloatVectorProperty,
StringProperty,
BoolProperty,
IntProperty,
FloatProperty,
- FloatVectorProperty,
EnumProperty,
PointerProperty,
CollectionProperty,
@@ -137,39 +151,94 @@ else:
def string_strip_hyphen(name):
- """Remove hyphen characters from a string to avoid POV errors."""
+ """Remove hyphen characters from a string to avoid POV errors"""
return name.replace("-", "")
+def pov_context_tex_datablock(context):
+ """Texture context type recreated as deprecated in blender 2.8"""
+
+ idblock = context.brush
+ if idblock and context.scene.texture_context == 'OTHER':
+ return idblock
+
+ # idblock = bpy.context.active_object.active_material
+ idblock = context.view_layer.objects.active.active_material
+ if idblock and context.scene.texture_context == 'MATERIAL':
+ return idblock
+
+ idblock = context.world
+ if idblock and context.scene.texture_context == 'WORLD':
+ return idblock
+
+ idblock = context.light
+ if idblock and context.scene.texture_context == 'LIGHT':
+ return idblock
+
+ if context.particle_system and context.scene.texture_context == 'PARTICLES':
+ idblock = context.particle_system.settings
+
+ return idblock
+
+ idblock = context.line_style
+ if idblock and context.scene.texture_context == 'LINESTYLE':
+ return idblock
+
+def brush_texture_update(self, context):
+
+ """Brush texture rolldown must show active slot texture props"""
+ idblock = pov_context_tex_datablock(context)
+ if idblock is not None:
+ #mat = context.view_layer.objects.active.active_material
+ idblock = pov_context_tex_datablock(context)
+ slot = idblock.pov_texture_slots[idblock.pov.active_texture_index]
+ tex = slot.texture
+
+ if tex:
+ # Switch paint brush to active texture so slot and settings remain contextual
+ bpy.context.tool_settings.image_paint.brush.texture = bpy.data.textures[tex]
+ bpy.context.tool_settings.image_paint.brush.mask_texture = bpy.data.textures[tex]
def active_texture_name_from_uilist(self, context):
- mat = context.scene.view_layers["View Layer"].objects.active.active_material
- index = mat.pov.active_texture_index
- name = mat.pov_texture_slots[index].name
- newname = mat.pov_texture_slots[index].texture
- tex = bpy.data.textures[name]
- tex.name = newname
- mat.pov_texture_slots[index].name = newname
+
+ idblock = pov_context_tex_datablock(context)
+ #mat = context.view_layer.objects.active.active_material
+ if idblock is not None:
+ index = idblock.pov.active_texture_index
+ name = idblock.pov_texture_slots[index].name
+ newname = idblock.pov_texture_slots[index].texture
+ tex = bpy.data.textures[name]
+ tex.name = newname
+ idblock.pov_texture_slots[index].name = newname
def active_texture_name_from_search(self, context):
- mat = context.scene.view_layers["View Layer"].objects.active.active_material
- index = mat.pov.active_texture_index
- name = mat.pov_texture_slots[index].texture_search
+ """Texture rolldown to change the data linked by an existing texture"""
+ idblock = pov_context_tex_datablock(context)
+ #mat = context.view_layer.objects.active.active_material
+ if idblock is not None:
+ index = idblock.pov.active_texture_index
+ slot = idblock.pov_texture_slots[index]
+ name = slot.texture_search
+
try:
tex = bpy.data.textures[name]
- mat.pov_texture_slots[index].name = name
- mat.pov_texture_slots[index].texture = name
+ slot.name = name
+ slot.texture = name
+ # Switch paint brush to this texture so settings remain contextual
+ #bpy.context.tool_settings.image_paint.brush.texture = tex
+ #bpy.context.tool_settings.image_paint.brush.mask_texture = tex
except:
pass
+
###############################################################################
# Scene POV properties.
###############################################################################
class RenderPovSettingsScene(PropertyGroup):
- """Declare scene level properties controllable in UI and translated to POV."""
+ """Declare scene level properties controllable in UI and translated to POV"""
# Linux SDL-window enable
sdl_window_enable: BoolProperty(
@@ -770,7 +839,7 @@ class RenderPovSettingsScene(PropertyGroup):
name="Error Bound",
description="One of the two main speed/quality tuning values, "
"lower values are more accurate",
- min=0.0, max=1000.0, soft_min=0.1, soft_max=10.0, default=1.8
+ min=0.0, max=1000.0, soft_min=0.1, soft_max=10.0, default=10.0
)
radio_gray_threshold: FloatProperty(
@@ -837,14 +906,15 @@ class RenderPovSettingsScene(PropertyGroup):
name="Pretrace Start",
description="Fraction of the screen width which sets the size of the "
"blocks in the mosaic preview first pass",
- min=0.01, max=1.00, soft_min=0.02, soft_max=1.0, default=0.08
+ min=0.005, max=1.00, soft_min=0.02, soft_max=1.0, default=0.04
)
-
+ # XXX TODO set automatically to pretrace_end = 8 / max (image_width, image_height)
+ # for non advanced mode
radio_pretrace_end: FloatProperty(
name="Pretrace End",
description="Fraction of the screen width which sets the size of the blocks "
"in the mosaic preview last pass",
- min=0.000925, max=1.00, soft_min=0.01, soft_max=1.00, default=0.04, precision=3
+ min=0.000925, max=1.00, soft_min=0.01, soft_max=1.00, default=0.004, precision=3
)
###############################################################################
@@ -856,19 +926,28 @@ class MaterialTextureSlot(PropertyGroup):
bl_idname="pov_texture_slots",
bl_description="Texture_slots from Blender-2.79",
+ # Adding a "real" texture datablock as property is not possible
+ # (or at least not easy through a dynamically populated EnumProperty).
+ # That's why we'll use a prop_search() UILayout function in ui.py.
+ # So we'll assign the name of the needed texture datablock to the below StringProperty.
texture : StringProperty(update=active_texture_name_from_uilist)
- texture_search : StringProperty(update=active_texture_name_from_search)
+ # and use another temporary StringProperty to change the linked data
+ texture_search : StringProperty(
+ name="",
+ update = active_texture_name_from_search,
+ description = "Browse Texture to be linked",
+ )
alpha_factor: FloatProperty(
name="Alpha",
description="Amount texture affects alpha",
- default = 0.0,
+ default = 1.0,
)
ambient_factor: FloatProperty(
name="",
description="Amount texture affects ambient",
- default = 0.0,
+ default = 1.0,
)
bump_method: EnumProperty(
@@ -897,49 +976,49 @@ class MaterialTextureSlot(PropertyGroup):
density_factor: FloatProperty(
name="",
description="Amount texture affects density",
- default = 0.0,
+ default = 1.0,
)
diffuse_color_factor: FloatProperty(
name="",
description="Amount texture affects diffuse color",
- default = 0.0,
+ default = 1.0,
)
diffuse_factor: FloatProperty(
name="",
description="Amount texture affects diffuse reflectivity",
- default = 0.0,
+ default = 1.0,
)
displacement_factor: FloatProperty(
name="",
description="Amount texture displaces the surface",
- default = 0.0,
+ default = 0.2,
)
emission_color_factor: FloatProperty(
name="",
description="Amount texture affects emission color",
- default = 0.0,
+ default = 1.0,
)
emission_factor: FloatProperty(
name="",
description="Amount texture affects emission",
- default = 0.0,
+ default = 1.0,
)
emit_factor: FloatProperty(
name="",
description="Amount texture affects emission",
- default = 0.0,
+ default = 1.0,
)
hardness_factor: FloatProperty(
name="",
description="Amount texture affects hardness",
- default = 0.0,
+ default = 1.0,
)
mapping: EnumProperty(
@@ -985,13 +1064,13 @@ class MaterialTextureSlot(PropertyGroup):
mirror_factor: FloatProperty(
name="",
description="Amount texture affects mirror color",
- default = 0.0,
+ default = 1.0,
)
normal_factor: FloatProperty(
name="",
description="Amount texture affects normal values",
- default = 0.0,
+ default = 1.0,
)
normal_map_space: EnumProperty(
@@ -1013,39 +1092,65 @@ class MaterialTextureSlot(PropertyGroup):
raymir_factor: FloatProperty(
name="",
description="Amount texture affects ray mirror",
- default = 0.0,
+ default = 1.0,
)
reflection_color_factor: FloatProperty(
name="",
description="Amount texture affects color of out-scattered light",
- default = 0.0,
+ default = 1.0,
)
reflection_factor: FloatProperty(
name="",
description="Amount texture affects brightness of out-scattered light",
- default = 0.0,
+ default = 1.0,
)
scattering_factor: FloatProperty(
name="",
description="Amount texture affects scattering",
- default = 0.0,
+ default = 1.0,
)
specular_color_factor: FloatProperty(
name="",
description="Amount texture affects specular color",
- default = 0.0,
+ default = 1.0,
)
specular_factor: FloatProperty(
name="",
description="Amount texture affects specular reflectivity",
- default = 0.0,
+ default = 1.0,
+ )
+
+ offset: FloatVectorProperty(
+ name="Offset",
+ description=("Fine tune of the texture mapping X, Y and Z locations "),
+ precision=4,
+ step=0.1,
+ soft_min= -100.0,
+ soft_max=100.0,
+ default=(0.0,0.0,0.0),
+ options={'ANIMATABLE'},
+ subtype='TRANSLATION',
)
+ scale: FloatVectorProperty(
+ name="Size",
+ subtype='XYZ',
+ size=3,
+ description="Set scaling for the texture’s X, Y and Z sizes ",
+ precision=4,
+ step=0.1,
+ soft_min= -100.0,
+ soft_max=100.0,
+ default=(1.0,1.0,1.0),
+ options={'ANIMATABLE'},
+ )
+
+
texture_coords: EnumProperty(
name="",
description="",
@@ -1068,13 +1173,13 @@ class MaterialTextureSlot(PropertyGroup):
translucency_factor: FloatProperty(
name="",
description="Amount texture affects translucency",
- default = 0.0,
+ default = 1.0,
)
transmission_color_factor: FloatProperty(
name="",
description="Amount texture affects result color after light has been scattered/absorbed",
- default = 0.0,
+ default = 1.0,
)
use: BoolProperty(
@@ -1095,6 +1200,12 @@ class MaterialTextureSlot(PropertyGroup):
default = False,
)
+ use_interpolation: BoolProperty(
+ name="",
+ description="Interpolates pixels using selected filter ",
+ default = False,
+ )
+
use_map_alpha: BoolProperty(
name="",
description="Causes the texture to affect the alpha value",
@@ -1110,7 +1221,7 @@ class MaterialTextureSlot(PropertyGroup):
use_map_color_diffuse: BoolProperty(
name="",
description="Causes the texture to affect basic color of the material",
- default = False,
+ default = True,
)
use_map_color_emission: BoolProperty(
@@ -1234,7 +1345,7 @@ class MaterialTextureSlot(PropertyGroup):
)
-#######################################"
+#######################################
blend_factor: FloatProperty(
name="Blend",
@@ -1328,10 +1439,10 @@ bpy.types.ID.texture_context = EnumProperty(
default = 'MATERIAL',
)
-bpy.types.ID.active_texture_index = IntProperty(
- name = "Index for texture_slots",
- default = 0,
-)
+# bpy.types.ID.active_texture_index = IntProperty(
+ # name = "Index for texture_slots",
+ # default = 0,
+# )
class RenderPovSettingsMaterial(PropertyGroup):
"""Declare material level properties controllable in UI and translated to POV."""
@@ -1360,6 +1471,7 @@ class RenderPovSettingsMaterial(PropertyGroup):
active_texture_index: IntProperty(
name = "Index for texture_slots",
default = 0,
+ update = brush_texture_update
)
transparency_method: EnumProperty(
@@ -2123,7 +2235,7 @@ class MaterialRaytraceTransparency(PropertyGroup):
gloss_samples: IntProperty(
name="Samples",
- description="Number of cone samples averaged for blurry refractions",
+ description="frequency of the noise sample used for blurry refractions",
min=0, max=1024, default=18
)
@@ -2205,8 +2317,8 @@ class MaterialRaytraceMirror(PropertyGroup):
)
gloss_samples: IntProperty(
- name="Samples",
- description="Number of cone samples averaged for blurry reflections",
+ name="Noise",
+ description="Frequency of the noise pattern bumps averaged for blurry reflections",
min=0, max=1024, default=18,
)
@@ -3223,7 +3335,7 @@ class MaterialStrandSettings(PropertyGroup):
# Povray Nodes
###############################################################################
-class PovraySocketUniversal(bpy.types.NodeSocket):
+class PovraySocketUniversal(NodeSocket):
bl_idname = 'PovraySocketUniversal'
bl_label = 'Povray Socket'
value_unlimited: bpy.props.FloatProperty(default=0.0)
@@ -3276,7 +3388,7 @@ class PovraySocketUniversal(bpy.types.NodeSocket):
def draw_color(self, context, node):
return (1, 0, 0, 1)
-class PovraySocketFloat_0_1(bpy.types.NodeSocket):
+class PovraySocketFloat_0_1(NodeSocket):
bl_idname = 'PovraySocketFloat_0_1'
bl_label = 'Povray Socket'
default_value: bpy.props.FloatProperty(description="Input node Value_0_1",min=0,max=1,default=0)
@@ -3289,7 +3401,7 @@ class PovraySocketFloat_0_1(bpy.types.NodeSocket):
def draw_color(self, context, node):
return (0.5, 0.7, 0.7, 1)
-class PovraySocketFloat_0_10(bpy.types.NodeSocket):
+class PovraySocketFloat_0_10(NodeSocket):
bl_idname = 'PovraySocketFloat_0_10'
bl_label = 'Povray Socket'
default_value: bpy.props.FloatProperty(description="Input node Value_0_10",min=0,max=10,default=0)
@@ -3304,7 +3416,7 @@ class PovraySocketFloat_0_10(bpy.types.NodeSocket):
def draw_color(self, context, node):
return (0.65, 0.65, 0.65, 1)
-class PovraySocketFloat_10(bpy.types.NodeSocket):
+class PovraySocketFloat_10(NodeSocket):
bl_idname = 'PovraySocketFloat_10'
bl_label = 'Povray Socket'
default_value: bpy.props.FloatProperty(description="Input node Value_10",min=-10,max=10,default=0)
@@ -3319,7 +3431,7 @@ class PovraySocketFloat_10(bpy.types.NodeSocket):
def draw_color(self, context, node):
return (0.65, 0.65, 0.65, 1)
-class PovraySocketFloatPositive(bpy.types.NodeSocket):
+class PovraySocketFloatPositive(NodeSocket):
bl_idname = 'PovraySocketFloatPositive'
bl_label = 'Povray Socket'
default_value: bpy.props.FloatProperty(description="Input Node Value Positive", min=0.0, default=0)
@@ -3331,7 +3443,7 @@ class PovraySocketFloatPositive(bpy.types.NodeSocket):
def draw_color(self, context, node):
return (0.045, 0.005, 0.136, 1)
-class PovraySocketFloat_000001_10(bpy.types.NodeSocket):
+class PovraySocketFloat_000001_10(NodeSocket):
bl_idname = 'PovraySocketFloat_000001_10'
bl_label = 'Povray Socket'
default_value: bpy.props.FloatProperty(min=0.000001,max=10,default=0.000001)
@@ -3343,7 +3455,7 @@ class PovraySocketFloat_000001_10(bpy.types.NodeSocket):
def draw_color(self, context, node):
return (1, 0, 0, 1)
-class PovraySocketFloatUnlimited(bpy.types.NodeSocket):
+class PovraySocketFloatUnlimited(NodeSocket):
bl_idname = 'PovraySocketFloatUnlimited'
bl_label = 'Povray Socket'
default_value: bpy.props.FloatProperty(default = 0.0)
@@ -3355,7 +3467,7 @@ class PovraySocketFloatUnlimited(bpy.types.NodeSocket):
def draw_color(self, context, node):
return (0.7, 0.7, 1, 1)
-class PovraySocketInt_1_9(bpy.types.NodeSocket):
+class PovraySocketInt_1_9(NodeSocket):
bl_idname = 'PovraySocketInt_1_9'
bl_label = 'Povray Socket'
default_value: bpy.props.IntProperty(description="Input node Value_1_9",min=1,max=9,default=6)
@@ -3367,7 +3479,7 @@ class PovraySocketInt_1_9(bpy.types.NodeSocket):
def draw_color(self, context, node):
return (1, 0.7, 0.7, 1)
-class PovraySocketInt_0_256(bpy.types.NodeSocket):
+class PovraySocketInt_0_256(NodeSocket):
bl_idname = 'PovraySocketInt_0_256'
bl_label = 'Povray Socket'
default_value: bpy.props.IntProperty(min=0,max=255,default=0)
@@ -3380,7 +3492,7 @@ class PovraySocketInt_0_256(bpy.types.NodeSocket):
return (0.5, 0.5, 0.5, 1)
-class PovraySocketPattern(bpy.types.NodeSocket):
+class PovraySocketPattern(NodeSocket):
bl_idname = 'PovraySocketPattern'
bl_label = 'Povray Socket'
@@ -3417,7 +3529,7 @@ class PovraySocketPattern(bpy.types.NodeSocket):
def draw_color(self, context, node):
return (1, 1, 1, 1)
-class PovraySocketColor(bpy.types.NodeSocket):
+class PovraySocketColor(NodeSocket):
bl_idname = 'PovraySocketColor'
bl_label = 'Povray Socket'
@@ -3434,7 +3546,7 @@ class PovraySocketColor(bpy.types.NodeSocket):
def draw_color(self, context, node):
return (1, 1, 0, 1)
-class PovraySocketColorRGBFT(bpy.types.NodeSocket):
+class PovraySocketColorRGBFT(NodeSocket):
bl_idname = 'PovraySocketColorRGBFT'
bl_label = 'Povray Socket'
@@ -3452,7 +3564,7 @@ class PovraySocketColorRGBFT(bpy.types.NodeSocket):
def draw_color(self, context, node):
return (1, 1, 0, 1)
-class PovraySocketTexture(bpy.types.NodeSocket):
+class PovraySocketTexture(NodeSocket):
bl_idname = 'PovraySocketTexture'
bl_label = 'Povray Socket'
default_value: bpy.props.IntProperty()
@@ -3464,7 +3576,7 @@ class PovraySocketTexture(bpy.types.NodeSocket):
-class PovraySocketTransform(bpy.types.NodeSocket):
+class PovraySocketTransform(NodeSocket):
bl_idname = 'PovraySocketTransform'
bl_label = 'Povray Socket'
default_value: bpy.props.IntProperty(min=0,max=255,default=0)
@@ -3474,7 +3586,7 @@ class PovraySocketTransform(bpy.types.NodeSocket):
def draw_color(self, context, node):
return (99/255, 99/255, 199/255, 1)
-class PovraySocketNormal(bpy.types.NodeSocket):
+class PovraySocketNormal(NodeSocket):
bl_idname = 'PovraySocketNormal'
bl_label = 'Povray Socket'
default_value: bpy.props.IntProperty(min=0,max=255,default=0)
@@ -3484,7 +3596,7 @@ class PovraySocketNormal(bpy.types.NodeSocket):
def draw_color(self, context, node):
return (0.65, 0.65, 0.65, 1)
-class PovraySocketSlope(bpy.types.NodeSocket):
+class PovraySocketSlope(NodeSocket):
bl_idname = 'PovraySocketSlope'
bl_label = 'Povray Socket'
default_value: bpy.props.FloatProperty(min = 0.0, max = 1.0)
@@ -3500,7 +3612,7 @@ class PovraySocketSlope(bpy.types.NodeSocket):
def draw_color(self, context, node):
return (0, 0, 0, 1)
-class PovraySocketMap(bpy.types.NodeSocket):
+class PovraySocketMap(NodeSocket):
bl_idname = 'PovraySocketMap'
bl_label = 'Povray Socket'
default_value: bpy.props.StringProperty()
@@ -3774,7 +3886,7 @@ class RenderPovSettingsTexture(PropertyGroup):
('checker', "Checker", "", 'PLUGIN', 34),
('hexagon', "Hexagon", "", 'PLUGIN', 35),
('object', "Mesh", "", 'PLUGIN', 36),
- ('emulator', "Internal Emulator", "", 'PLUG', 37)
+ ('emulator', "Blender Type Emulator", "", 'SCRIPTPLUGINS', 37)
),
default='emulator',
)
@@ -5167,7 +5279,7 @@ class RenderPovSettingsWorld(PropertyGroup):
items=(
('MATERIAL', "", "Show material textures", "MATERIAL",0), # "Show material textures"
('WORLD', "", "Show world textures", "WORLD",1), # "Show world textures"
- ('LAMP', "", "Show lamp textures", "LIGHT",2), # "Show lamp textures"
+ ('LIGHT', "", "Show lamp textures", "LIGHT",2), # "Show lamp textures"
('PARTICLES', "", "Show particles textures", "PARTICLES",3), # "Show particles textures"
('LINESTYLE', "", "Show linestyle textures", "LINE_DATA",4), # "Show linestyle textures"
('OTHER', "", "Show other data textures", "TEXTURE_DATA",5), # "Show other data textures"
@@ -5215,12 +5327,27 @@ class RenderPovSettingsWorld(PropertyGroup):
)
active_texture_index: IntProperty(
name = "Index for texture_slots",
- default = 0
+ default = 0,
+ update = brush_texture_update
)
-
class WorldTextureSlot(PropertyGroup):
- """Declare world texture slot properties controllable in UI and translated to POV."""
+ """Declare world texture slot level properties for UI and translated to POV."""
+
+ bl_idname="pov_texture_slots",
+ bl_description="Texture_slots from Blender-2.79",
+
+ # Adding a "real" texture datablock as property is not possible
+ # (or at least not easy through a dynamically populated EnumProperty).
+ # That's why we'll use a prop_search() UILayout function in ui.py.
+ # So we'll assign the name of the needed texture datablock to the below StringProperty.
+ texture : StringProperty(update=active_texture_name_from_uilist)
+ # and use another temporary StringProperty to change the linked data
+ texture_search : StringProperty(
+ name="",
+ update = active_texture_name_from_search,
+ description = "Browse Texture to be linked",
+ )
blend_factor: FloatProperty(
name="Blend",
@@ -5241,6 +5368,31 @@ class WorldTextureSlot(PropertyGroup):
default="",
)
+ offset: FloatVectorProperty(
+ name="Offset",
+ description=("Fine tune of the texture mapping X, Y and Z locations "),
+ precision=4,
+ step=0.1,
+ soft_min= -100.0,
+ soft_max=100.0,
+ default=(0.0,0.0,0.0),
+ options={'ANIMATABLE'},
+ subtype='TRANSLATION',
+ )
+
+ scale: FloatVectorProperty(
+ name="Size",
+ subtype='XYZ',
+ size=3,
+ description="Set scaling for the texture’s X, Y and Z sizes ",
+ precision=4,
+ step=0.1,
+ soft_min= -100.0,
+ soft_max=100.0,
+ default=(1.0,1.0,1.0),
+ options={'ANIMATABLE'},
+ )
+
texture_coords: EnumProperty(
name="Coordinates",
description="Texture coordinates used to map the texture onto the background",
@@ -5308,7 +5460,7 @@ for i in range(18): # length of world texture slots
class MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist(bpy.types.UIList):
# texture_slots:
- index: bpy.props.IntProperty(name='index')
+ #index: bpy.props.IntProperty(name='index')
# foo = random prop
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
ob = data
@@ -5385,11 +5537,44 @@ class PovrayPreferences(AddonPreferences):
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",
+ default=False,
+ )
+
+ # 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',
+ )
+
+ filepath_cancel_sound: StringProperty(
+ name="Cancel Render Sound",
+ description="Path to cancelled or render time error sound file",
+ subtype='FILE_PATH',
+ )
+
+ #shall we not move this to UI file?
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')
classes = (
@@ -5451,7 +5636,7 @@ def register():
bpy.types.Light.pov = PointerProperty(type=RenderPovSettingsLight)
bpy.types.World.pov = PointerProperty(type=RenderPovSettingsWorld)
bpy.types.Material.pov_texture_slots = CollectionProperty(type=MaterialTextureSlot)
- bpy.types.World.texture_slots = CollectionProperty(type=WorldTextureSlot)
+ bpy.types.World.pov_texture_slots = CollectionProperty(type=WorldTextureSlot)
bpy.types.Text.pov = PointerProperty(type=RenderPovSettingsText)
@@ -5468,6 +5653,7 @@ def unregister():
del bpy.types.Camera.pov
del bpy.types.Light.pov
del bpy.types.World.pov
+ del bpy.types.World.pov_texture_slots
del bpy.types.Material.pov_texture_slots
del bpy.types.Text.pov
diff --git a/render_povray/nodes.py b/render_povray/nodes.py
index be535db3..bbdb9754 100644
--- a/render_povray/nodes.py
+++ b/render_povray/nodes.py
@@ -21,7 +21,14 @@
import bpy
from bpy.utils import register_class
-from bpy.types import Node, ShaderNodeTree, CompositorNodeTree, TextureNodeTree#, NodeSocket
+from bpy.types import (
+ Node,
+ ShaderNodeTree,
+ CompositorNodeTree,
+ TextureNodeTree,
+ #NodeSocket,
+ Operator,
+ )
from bpy.props import (
StringProperty,
BoolProperty,
@@ -1025,7 +1032,7 @@ class TextureOutputNode(Node, TextureNodeTree):
##################################################################################
-class NODE_OT_iso_add(bpy.types.Operator):
+class NODE_OT_iso_add(Operator):
bl_idname = "pov.nodeisoadd"
bl_label = "Create iso props"
@@ -1042,7 +1049,7 @@ class NODE_OT_iso_add(bpy.types.Operator):
isonode.label = ob.name
return {'FINISHED'}
-class NODE_OT_map_create(bpy.types.Operator):
+class NODE_OT_map_create(Operator):
bl_idname = "node.map_create"
bl_label = "Create map"
@@ -1067,7 +1074,7 @@ class NODE_OT_map_create(bpy.types.Operator):
mat = context.object.active_material
layout.prop(mat.pov,"inputs_number")
-class NODE_OT_povray_node_texture_map_add(bpy.types.Operator):
+class NODE_OT_povray_node_texture_map_add(Operator):
bl_idname = "pov.nodetexmapadd"
bl_label = "Texture map"
@@ -1091,7 +1098,7 @@ class NODE_OT_povray_node_texture_map_add(bpy.types.Operator):
return {'FINISHED'}
-class NODE_OT_povray_node_output_add(bpy.types.Operator):
+class NODE_OT_povray_node_output_add(Operator):
bl_idname = "pov.nodeoutputadd"
bl_label = "Output"
@@ -1105,7 +1112,7 @@ class NODE_OT_povray_node_output_add(bpy.types.Operator):
tmap.label="Output"
return {'FINISHED'}
-class NODE_OT_povray_node_layered_add(bpy.types.Operator):
+class NODE_OT_povray_node_layered_add(Operator):
bl_idname = "pov.nodelayeredadd"
bl_label = "Layered material"
@@ -1116,7 +1123,7 @@ class NODE_OT_povray_node_layered_add(bpy.types.Operator):
tmap.label="Layered material"
return {'FINISHED'}
-class NODE_OT_povray_input_add(bpy.types.Operator):
+class NODE_OT_povray_input_add(Operator):
bl_idname = "pov.nodeinputadd"
bl_label = "Add entry"
@@ -1141,7 +1148,7 @@ class NODE_OT_povray_input_add(bpy.types.Operator):
return {'FINISHED'}
-class NODE_OT_povray_input_remove(bpy.types.Operator):
+class NODE_OT_povray_input_remove(Operator):
bl_idname = "pov.nodeinputremove"
bl_label = "Remove input"
@@ -1159,7 +1166,7 @@ class NODE_OT_povray_input_remove(bpy.types.Operator):
els.remove(el)
return {'FINISHED'}
-class NODE_OT_povray_image_open(bpy.types.Operator):
+class NODE_OT_povray_image_open(Operator):
bl_idname = "pov.imageopen"
bl_label = "Open"
@@ -1181,7 +1188,7 @@ class NODE_OT_povray_image_open(bpy.types.Operator):
return {'FINISHED'}
-# class TEXTURE_OT_povray_open_image(bpy.types.Operator):
+# class TEXTURE_OT_povray_open_image(Operator):
# bl_idname = "pov.openimage"
# bl_label = "Open Image"
@@ -1204,7 +1211,7 @@ class NODE_OT_povray_image_open(bpy.types.Operator):
# view_layer.update()
# return {'FINISHED'}
-class PovrayPatternNode(bpy.types.Operator):
+class PovrayPatternNode(Operator):
bl_idname = "pov.patternnode"
bl_label = "Pattern"
@@ -1259,7 +1266,7 @@ class PovrayPatternNode(bpy.types.Operator):
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
-class UpdatePreviewMaterial(bpy.types.Operator):
+class UpdatePreviewMaterial(Operator):
'''Operator update preview material'''
bl_idname = "node.updatepreview"
bl_label = "Update preview"
@@ -1283,7 +1290,7 @@ class UpdatePreviewMaterial(bpy.types.Operator):
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
-class UpdatePreviewKey(bpy.types.Operator):
+class UpdatePreviewKey(Operator):
'''Operator update preview keymap'''
bl_idname = "wm.updatepreviewkey"
bl_label = "Activate RMB"
diff --git a/render_povray/primitives.py b/render_povray/primitives.py
index a9d68d44..6d864220 100644
--- a/render_povray/primitives.py
+++ b/render_povray/primitives.py
@@ -26,7 +26,7 @@ from bpy_extras.io_utils import ImportHelper
from bpy_extras import object_utils
from bpy.utils import register_class
from math import atan, pi, degrees, sqrt, cos, sin
-
+from bpy.types import Operator
from bpy.props import (
StringProperty,
@@ -41,6 +41,7 @@ from bpy.props import (
from mathutils import Vector, Matrix
+
# import collections
@@ -60,7 +61,7 @@ def pov_define_mesh(mesh, verts, edges, faces, name, hide_geometry=True):
return mesh
-class POVRAY_OT_lathe_add(bpy.types.Operator):
+class POVRAY_OT_lathe_add(Operator):
"""Add the representation of POV lathe using a screw modifier."""
bl_idname = "pov.addlathe"
@@ -212,7 +213,7 @@ def pov_superellipsoid_define(context, op, ob):
bpy.ops.object.mode_set(mode="OBJECT")
-class POVRAY_OT_superellipsoid_add(bpy.types.Operator):
+class POVRAY_OT_superellipsoid_add(Operator):
"""Add the representation of POV superellipsoid using the pov_superellipsoid_define() function."""
bl_idname = "pov.addsuperellipsoid"
@@ -286,7 +287,7 @@ class POVRAY_OT_superellipsoid_add(bpy.types.Operator):
return {'FINISHED'}
-class POVRAY_OT_superellipsoid_update(bpy.types.Operator):
+class POVRAY_OT_superellipsoid_update(Operator):
"""Update the superellipsoid.
Delete its previous proxy geometry and rerun pov_superellipsoid_define() function
@@ -455,7 +456,7 @@ def pov_supertorus_define(context, op, ob):
ob.pov.st_edit = st_edit
-class POVRAY_OT_supertorus_add(bpy.types.Operator):
+class POVRAY_OT_supertorus_add(Operator):
"""Add the representation of POV supertorus using the pov_supertorus_define() function."""
bl_idname = "pov.addsupertorus"
@@ -530,7 +531,7 @@ class POVRAY_OT_supertorus_add(bpy.types.Operator):
return {'FINISHED'}
-class POVRAY_OT_supertorus_update(bpy.types.Operator):
+class POVRAY_OT_supertorus_update(Operator):
"""Update the supertorus.
Delete its previous proxy geometry and rerun pov_supetorus_define() function
@@ -566,7 +567,7 @@ class POVRAY_OT_supertorus_update(bpy.types.Operator):
#########################################################################################################
-class POVRAY_OT_loft_add(bpy.types.Operator):
+class POVRAY_OT_loft_add(Operator):
"""Create the representation of POV loft using Blender curves."""
bl_idname = "pov.addloft"
@@ -695,7 +696,7 @@ class POVRAY_OT_loft_add(bpy.types.Operator):
return {'FINISHED'}
-class POVRAY_OT_plane_add(bpy.types.Operator):
+class POVRAY_OT_plane_add(Operator):
"""Add the representation of POV infinite plane using just a very big Blender Plane.
Flag its primitive type with a specific pov.object_as attribute and lock edit mode
@@ -725,7 +726,7 @@ class POVRAY_OT_plane_add(bpy.types.Operator):
return {'FINISHED'}
-class POVRAY_OT_box_add(bpy.types.Operator):
+class POVRAY_OT_box_add(Operator):
"""Add the representation of POV box using a simple Blender mesh cube.
Flag its primitive type with a specific pov.object_as attribute and lock edit mode
@@ -796,7 +797,7 @@ def pov_cylinder_define(context, op, ob, radius, loc, loc_cap):
bpy.ops.object.shade_smooth()
-class POVRAY_OT_cylinder_add(bpy.types.Operator):
+class POVRAY_OT_cylinder_add(Operator):
"""Add the representation of POV cylinder using pov_cylinder_define() function.
Use imported_cyl_loc when this operator is run by POV importer."""
@@ -846,7 +847,7 @@ class POVRAY_OT_cylinder_add(bpy.types.Operator):
return {'FINISHED'}
-class POVRAY_OT_cylinder_update(bpy.types.Operator):
+class POVRAY_OT_cylinder_update(Operator):
"""Update the POV cylinder.
Delete its previous proxy geometry and rerun pov_cylinder_define() function
@@ -932,7 +933,7 @@ def pov_sphere_define(context, op, ob, loc):
bpy.ops.object.mode_set(mode="OBJECT")
-class POVRAY_OT_sphere_add(bpy.types.Operator):
+class POVRAY_OT_sphere_add(Operator):
"""Add the representation of POV sphere using pov_sphere_define() function.
Use imported_loc when this operator is run by POV importer."""
@@ -989,7 +990,7 @@ class POVRAY_OT_sphere_add(bpy.types.Operator):
# return {'FINISHED'}
-class POVRAY_OT_sphere_update(bpy.types.Operator):
+class POVRAY_OT_sphere_update(Operator):
"""Update the POV sphere.
Delete its previous proxy geometry and rerun pov_sphere_define() function
@@ -1084,7 +1085,7 @@ def pov_cone_define(context, op, ob):
ob.pov.cone_cap_z = zc
-class POVRAY_OT_cone_add(bpy.types.Operator):
+class POVRAY_OT_cone_add(Operator):
"""Add the representation of POV cone using pov_cone_define() function."""
bl_idname = "pov.cone_add"
@@ -1139,7 +1140,7 @@ class POVRAY_OT_cone_add(bpy.types.Operator):
return {'FINISHED'}
-class POVRAY_OT_cone_update(bpy.types.Operator):
+class POVRAY_OT_cone_update(Operator):
"""Update the POV cone.
Delete its previous proxy geometry and rerun pov_cone_define() function
@@ -1177,7 +1178,7 @@ class POVRAY_OT_cone_update(bpy.types.Operator):
########################################ISOSURFACES##################################
-class POVRAY_OT_isosurface_box_add(bpy.types.Operator):
+class POVRAY_OT_isosurface_box_add(Operator):
"""Add the representation of POV isosurface box using also just a Blender mesh cube.
Flag its primitive type with a specific pov.object_as attribute and lock edit mode
@@ -1207,7 +1208,7 @@ class POVRAY_OT_isosurface_box_add(bpy.types.Operator):
return {'FINISHED'}
-class POVRAY_OT_isosurface_sphere_add(bpy.types.Operator):
+class POVRAY_OT_isosurface_sphere_add(Operator):
"""Add the representation of POV isosurface sphere by a Blender mesh icosphere.
Flag its primitive type with a specific pov.object_as attribute and lock edit mode
@@ -1238,7 +1239,7 @@ class POVRAY_OT_isosurface_sphere_add(bpy.types.Operator):
return {'FINISHED'}
-class POVRAY_OT_sphere_sweep_add(bpy.types.Operator):
+class POVRAY_OT_sphere_sweep_add(Operator):
"""Add the representation of POV sphere_sweep using a Blender NURBS curve.
Flag its primitive type with a specific ob.pov.curveshape attribute and
@@ -1264,7 +1265,7 @@ class POVRAY_OT_sphere_sweep_add(bpy.types.Operator):
return {'FINISHED'}
-class POVRAY_OT_blob_add(bpy.types.Operator):
+class POVRAY_OT_blob_add(Operator):
"""Add the representation of POV blob using a Blender meta ball.
No need to flag its primitive type as meta are exported to blobs
@@ -1284,7 +1285,7 @@ class POVRAY_OT_blob_add(bpy.types.Operator):
return {'FINISHED'}
-class POVRAY_OT_rainbow_add(bpy.types.Operator):
+class POVRAY_OT_rainbow_add(Operator):
"""Add the representation of POV rainbow using a Blender spot light.
Rainbows indeed propagate along a visibility cone.
@@ -1334,7 +1335,7 @@ class POVRAY_OT_height_field_add(bpy.types.Operator, ImportHelper):
bl_idname = "pov.addheightfield"
bl_label = "Height Field"
- bl_description = "Add Height Field "
+ bl_description = "Add Height Field"
bl_options = {'REGISTER', 'UNDO'}
# XXX Keep it in sync with __init__'s hf Primitive
@@ -1470,7 +1471,7 @@ def pov_torus_define(context, op, ob):
bpy.ops.object.mode_set(mode="OBJECT")
-class POVRAY_OT_torus_add(bpy.types.Operator):
+class POVRAY_OT_torus_add(Operator):
"""Add the representation of POV torus using using pov_torus_define() function."""
bl_idname = "pov.addtorus"
@@ -1503,7 +1504,7 @@ class POVRAY_OT_torus_add(bpy.types.Operator):
return {'FINISHED'}
-class POVRAY_OT_torus_update(bpy.types.Operator):
+class POVRAY_OT_torus_update(Operator):
"""Update the POV torus.
Delete its previous proxy geometry and rerun pov_torus_define() function
@@ -1536,7 +1537,7 @@ class POVRAY_OT_torus_update(bpy.types.Operator):
###################################################################################
-class POVRAY_OT_prism_add(bpy.types.Operator):
+class POVRAY_OT_prism_add(Operator):
"""Add the representation of POV prism using using an extruded curve."""
bl_idname = "pov.addprism"
@@ -1662,7 +1663,7 @@ def pov_parametric_define(context, op, ob):
bpy.ops.object.mode_set(mode="OBJECT")
-class POVRAY_OT_parametric_add(bpy.types.Operator):
+class POVRAY_OT_parametric_add(Operator):
"""Add the representation of POV parametric surfaces using pov_parametric_define() function."""
bl_idname = "pov.addparametric"
@@ -1698,7 +1699,7 @@ class POVRAY_OT_parametric_add(bpy.types.Operator):
return {'FINISHED'}
-class POVRAY_OT_parametric_update(bpy.types.Operator):
+class POVRAY_OT_parametric_update(Operator):
"""Update the representation of POV parametric surfaces.
Delete its previous proxy geometry and rerun pov_parametric_define() function
@@ -1731,7 +1732,7 @@ class POVRAY_OT_parametric_update(bpy.types.Operator):
#######################################################################
-class POVRAY_OT_shape_polygon_to_circle_add(bpy.types.Operator):
+class POVRAY_OT_shape_polygon_to_circle_add(Operator):
"""Add the proxy mesh for POV Polygon to circle lofting macro"""
bl_idname = "pov.addpolygontocircle"
diff --git a/render_povray/render.py b/render_povray/render.py
index 6efe7291..f9de22e4 100644
--- a/render_povray/render.py
+++ b/render_povray/render.py
@@ -24,6 +24,10 @@ import os
import sys
import time
from math import atan, pi, degrees, sqrt, cos, sin
+####################
+## Faster mesh export
+import numpy as np
+####################
import re
import random
import platform #
@@ -69,6 +73,7 @@ def imageFormat(imgF):
def imgMap(ts):
"""Translate mapping type from Blender UI to POV syntax and return that string."""
image_map = ""
+ texdata = bpy.data.textures[ts.texture]
if ts.mapping == 'FLAT':
image_map = "map_type 0 "
elif ts.mapping == 'SPHERE':
@@ -82,9 +87,9 @@ def imgMap(ts):
# image_map = " map_type 3 "
# elif ts.mapping=="?":
# image_map = " map_type 4 "
- if ts.texture.use_interpolation:
+ if ts.use_interpolation: # Available if image sampling class reactivated?
image_map += " interpolate 2 "
- if ts.texture.extension == 'CLIP':
+ if texdata.extension == 'CLIP':
image_map += " once "
# image_map += "}"
# if ts.mapping=='CUBE':
@@ -110,12 +115,12 @@ def imgMapTransforms(ts):
image_map_transforms = (
"scale <%.4g,%.4g,%.4g> translate <%.4g,%.4g,%.4g>"
% (
- 1.0 / ts.scale.x,
- 1.0 / ts.scale.y,
- 1.0 / ts.scale.z,
- 0.5 - (0.5 / ts.scale.x) - (ts.offset.x),
- 0.5 - (0.5 / ts.scale.y) - (ts.offset.y),
- ts.offset.z,
+ ts.scale[0],
+ ts.scale[1],
+ ts.scale[2],
+ ts.offset[0],
+ ts.offset[1],
+ ts.offset[2],
)
)
# image_map_transforms = (" translate <-0.5,-0.5,0.0> scale <%.4g,%.4g,%.4g> translate <%.4g,%.4g,%.4g>" % \
@@ -137,6 +142,7 @@ def imgMapTransforms(ts):
def imgMapBG(wts):
"""Translate world mapping from Blender UI to POV syntax and return that string."""
+ tex = bpy.data.textures[wts.texture]
image_mapBG = ""
# texture_coords refers to the mapping of world textures:
if wts.texture_coords == 'VIEW' or wts.texture_coords == 'GLOBAL':
@@ -146,9 +152,9 @@ def imgMapBG(wts):
elif wts.texture_coords == 'TUBE':
image_mapBG = " map_type 2 "
- if wts.texture.use_interpolation:
+ if tex.use_interpolation:
image_mapBG += " interpolate 2 "
- if wts.texture.extension == 'CLIP':
+ if tex.extension == 'CLIP':
image_mapBG += " once "
# image_mapBG += "}"
# if wts.mapping == 'CUBE':
@@ -386,6 +392,7 @@ def write_object_modifiers(scene, ob, File):
def write_pov(filename, scene=None, info_callback=None):
"""Main export process from Blender UI to POV syntax and write to exported file """
+
import mathutils
# file = filename
@@ -690,7 +697,7 @@ def write_pov(filename, scene=None, info_callback=None):
tabWrite("right <%s, 0, 0>\n" % -Qsize)
tabWrite("up <0, 1, 0>\n")
tabWrite(
- "angle %f\n" % (360.0 * atan(16.0 / camera.data.lens) / pi)
+ "angle %f\n" % ( 2 * atan(camera.data.sensor_width / 2 / camera.data.lens) * 180.0 / pi )
)
tabWrite(
@@ -737,6 +744,7 @@ def write_pov(filename, scene=None, info_callback=None):
def exportLamps(lamps):
"""Translate lights from Blender UI to POV syntax and write to exported file."""
+
# Incremented after each lamp export to declare its target
# currently used for Fresnel diffuse shader as their slope vector:
global lampCount
@@ -2346,6 +2354,64 @@ def write_pov(filename, scene=None, info_callback=None):
def exportMeshes(scene, sel, csg):
"""write all meshes as POV mesh2{} syntax to exported file """
+ #some numpy functions to speed up mesh export
+
+ # TODO: also write a numpy function to read matrices at object level?
+ # feed below with mesh object.data, but only after doing data.calc_loop_triangles()
+ def read_verts_co(self, mesh):
+ #'float64' would be a slower 64-bit floating-point number numpy datatype
+ # using 'float32' vert coordinates for now until any issue is reported
+ mverts_co = np.zeros((len(mesh.vertices)*3), dtype=np.float32)
+ mesh.vertices.foreach_get("co", mverts_co)
+ return np.reshape(mverts_co, (len(mesh.vertices), 3))
+
+ def read_verts_idx(self, mesh):
+ mverts_idx = np.zeros((len(mesh.vertices)), dtype=np.int64)
+ mesh.vertices.foreach_get("index", mverts_idx)
+ return np.reshape(mverts_idx, (len(mesh.vertices), 1))
+
+ def read_verts_norms(self, mesh):
+ #'float64' would be a slower 64-bit floating-point number numpy datatype
+ # using less accurate 'float16' normals for now until any issue is reported
+ mverts_no = np.zeros((len(mesh.vertices)*3), dtype=np.float16)
+ mesh.vertices.foreach_get("normal", mverts_no)
+ return np.reshape(mverts_no, (len(mesh.vertices), 3))
+
+ def read_faces_idx(self, mesh):
+ mfaces_idx = np.zeros((len(mesh.loop_triangles)), dtype=np.int64)
+ mesh.loop_triangles.foreach_get("index", mfaces_idx)
+ return np.reshape(mfaces_idx, (len(mesh.loop_triangles), 1))
+
+ def read_faces_verts_indices(self, mesh):
+ mfaces_verts_idx = np.zeros((len(mesh.loop_triangles)*3), dtype=np.int64)
+ mesh.loop_triangles.foreach_get("vertices", mfaces_verts_idx)
+ return np.reshape(mfaces_verts_idx, (len(mesh.loop_triangles), 3))
+
+ #Why is below different from verex indices?
+ def read_faces_verts_loops(self, mesh):
+ mfaces_verts_loops = np.zeros((len(mesh.loop_triangles)*3), dtype=np.int64)
+ mesh.loop_triangles.foreach_get("loops", mfaces_verts_loops)
+ return np.reshape(mfaces_verts_loops, (len(mesh.loop_triangles), 3))
+
+ def read_faces_norms(self, mesh):
+ #'float64' would be a slower 64-bit floating-point number numpy datatype
+ # using less accurate 'float16' normals for now until any issue is reported
+ mfaces_no = np.zeros((len(mesh.loop_triangles)*3), dtype=np.float16)
+ mesh.loop_triangles.foreach_get("normal", mfaces_no)
+ return np.reshape(mfaces_no, (len(mesh.loop_triangles), 3))
+
+ def read_faces_smooth(self, mesh):
+ mfaces_smth = np.zeros((len(mesh.loop_triangles)*1), dtype=np.bool)
+ mesh.loop_triangles.foreach_get("use_smooth", mfaces_smth)
+ return np.reshape(mfaces_smth, (len(mesh.loop_triangles), 1))
+
+ def read_faces_material_indices(self, mesh):
+ mfaces_mats_idx = np.zeros((len(mesh.loop_triangles)), dtype=np.int16)
+ mesh.loop_triangles.foreach_get("material_index", mfaces_mats_idx)
+ return np.reshape(mfaces_mats_idx, (len(mesh.loop_triangles), 1))
+
+
+
# obmatslist = []
# def hasUniqueMaterial():
# # Grab materials attached to object instances ...
@@ -2684,6 +2750,7 @@ def write_pov(filename, scene=None, info_callback=None):
pmaterial = ob.material_slots[
pSys.settings.material - 1
].material
+ #XXX Todo: replace by pov_(Particles?)_texture_slot
for th in pmaterial.texture_slots:
if th and th.use:
if (
@@ -3411,6 +3478,8 @@ def write_pov(filename, scene=None, info_callback=None):
ob.pov.v_max,
)
)
+ # Previous to 3.8 default max_gradient 1.0 was too slow
+ tabWrite("max_gradient 0.001\n")
if ob.pov.contained_by == "sphere":
tabWrite("contained_by { sphere{0, 2} }\n")
else:
@@ -3593,6 +3662,14 @@ def write_pov(filename, scene=None, info_callback=None):
me.calc_loop_triangles()
me_materials = me.materials
me_faces = me.loop_triangles[:]
+ ## numpytest
+ #me_looptris = me.loops
+
+ ## otypes = ['int32'] is a 32-bit signed integer number numpy datatype
+ #get_v_index = np.vectorize(lambda l: l.vertex_index, otypes = ['int32'], cache = True)
+ #faces_verts_idx = get_v_index(me_looptris)
+
+
# if len(me_faces)==0:
# tabWrite("\n//dummy sphere to represent empty mesh location\n")
# tabWrite("#declare %s =sphere {<0, 0, 0>,0 pigment{rgbt 1} no_image no_reflection no_radiosity photons{pass_through collect off} hollow}\n" % povdataname)
@@ -4092,6 +4169,7 @@ def write_pov(filename, scene=None, info_callback=None):
else:
shading.writeTextureInfluence(
+ using_uberpov,
mater,
materialNames,
LocalMaterialNames,
@@ -4581,89 +4659,91 @@ def write_pov(filename, scene=None, info_callback=None):
for (
t
) in (
- world.texture_slots
+ world.pov_texture_slots
): # risk to write several sky_spheres but maybe ok.
- if t and t.texture.type is not None:
+ if t:
+ tex = bpy.data.textures[t.texture]
+ if tex.type is not None:
worldTexCount += 1
- # XXX No enable checkbox for world textures yet (report it?)
- # if t and t.texture.type == 'IMAGE' and t.use:
- if t and t.texture.type == 'IMAGE':
- image_filename = path_image(t.texture.image)
- if t.texture.image.filepath != image_filename:
- t.texture.image.filepath = image_filename
- if image_filename != "" and t.use_map_blend:
- texturesBlend = image_filename
- # colvalue = t.default_value
- t_blend = t
-
- # Commented below was an idea to make the Background image oriented as camera
- # taken here:
- # http://news.pov.org/pov.newusers/thread/%3Cweb.4a5cddf4e9c9822ba2f93e20@news.pov.org%3E/
- # Replace 4/3 by the ratio of each image found by some custom or existing
- # function
- # mappingBlend = (" translate <%.4g,%.4g,%.4g> rotate z*degrees" \
- # "(atan((camLocation - camLookAt).x/(camLocation - " \
- # "camLookAt).y)) rotate x*degrees(atan((camLocation - " \
- # "camLookAt).y/(camLocation - camLookAt).z)) rotate y*" \
- # "degrees(atan((camLocation - camLookAt).z/(camLocation - " \
- # "camLookAt).x)) scale <%.4g,%.4g,%.4g>b" % \
- # (t_blend.offset.x / 10 , t_blend.offset.y / 10 ,
- # t_blend.offset.z / 10, t_blend.scale.x ,
- # t_blend.scale.y , t_blend.scale.z))
- # using camera rotation valuesdirectly from blender seems much easier
- if t_blend.texture_coords == 'ANGMAP':
- mappingBlend = ""
- else:
- # POV-Ray "scale" is not a number of repetitions factor, but its
- # inverse, a standard scale factor.
- # 0.5 Offset is needed relatively to scale because center of the
- # UV scale is 0.5,0.5 in blender and 0,0 in POV
- # Further Scale by 2 and translate by -1 are
- # required for the sky_sphere not to repeat
-
- mappingBlend = (
- "scale 2 scale <%.4g,%.4g,%.4g> translate -1 "
- "translate <%.4g,%.4g,%.4g> rotate<0,0,0> "
+ # XXX No enable checkbox for world textures yet (report it?)
+ # if t and tex.type == 'IMAGE' and t.use:
+ if tex.type == 'IMAGE':
+ image_filename = path_image(tex.image)
+ if tex.image.filepath != image_filename:
+ tex.image.filepath = image_filename
+ if image_filename != "" and t.use_map_blend:
+ texturesBlend = image_filename
+ # colvalue = t.default_value
+ t_blend = t
+
+ # Commented below was an idea to make the Background image oriented as camera
+ # taken here:
+ # http://news.pov.org/pov.newusers/thread/%3Cweb.4a5cddf4e9c9822ba2f93e20@news.pov.org%3E/
+ # Replace 4/3 by the ratio of each image found by some custom or existing
+ # function
+ # mappingBlend = (" translate <%.4g,%.4g,%.4g> rotate z*degrees" \
+ # "(atan((camLocation - camLookAt).x/(camLocation - " \
+ # "camLookAt).y)) rotate x*degrees(atan((camLocation - " \
+ # "camLookAt).y/(camLocation - camLookAt).z)) rotate y*" \
+ # "degrees(atan((camLocation - camLookAt).z/(camLocation - " \
+ # "camLookAt).x)) scale <%.4g,%.4g,%.4g>b" % \
+ # (t_blend.offset.x / 10 , t_blend.offset.y / 10 ,
+ # t_blend.offset.z / 10, t_blend.scale.x ,
+ # t_blend.scale.y , t_blend.scale.z))
+ # using camera rotation valuesdirectly from blender seems much easier
+ if t_blend.texture_coords == 'ANGMAP':
+ mappingBlend = ""
+ else:
+ # POV-Ray "scale" is not a number of repetitions factor, but its
+ # inverse, a standard scale factor.
+ # 0.5 Offset is needed relatively to scale because center of the
+ # UV scale is 0.5,0.5 in blender and 0,0 in POV
+ # Further Scale by 2 and translate by -1 are
+ # required for the sky_sphere not to repeat
+
+ mappingBlend = (
+ "scale 2 scale <%.4g,%.4g,%.4g> translate -1 "
+ "translate <%.4g,%.4g,%.4g> rotate<0,0,0> "
+ % (
+ (1.0 / t_blend.scale.x),
+ (1.0 / t_blend.scale.y),
+ (1.0 / t_blend.scale.z),
+ 0.5
+ - (0.5 / t_blend.scale.x)
+ - t_blend.offset.x,
+ 0.5
+ - (0.5 / t_blend.scale.y)
+ - t_blend.offset.y,
+ t_blend.offset.z,
+ )
+ )
+
+ # The initial position and rotation of the pov camera is probably creating
+ # the rotation offset should look into it someday but at least background
+ # won't rotate with the camera now.
+ # Putting the map on a plane would not introduce the skysphere distortion and
+ # allow for better image scale matching but also some waay to chose depth and
+ # size of the plane relative to camera.
+ tabWrite("sky_sphere {\n")
+ tabWrite("pigment {\n")
+ tabWrite(
+ "image_map{%s \"%s\" %s}\n"
% (
- (1.0 / t_blend.scale.x),
- (1.0 / t_blend.scale.y),
- (1.0 / t_blend.scale.z),
- 0.5
- - (0.5 / t_blend.scale.x)
- - t_blend.offset.x,
- 0.5
- - (0.5 / t_blend.scale.y)
- - t_blend.offset.y,
- t_blend.offset.z,
+ imageFormat(texturesBlend),
+ texturesBlend,
+ imgMapBG(t_blend),
)
)
-
- # The initial position and rotation of the pov camera is probably creating
- # the rotation offset should look into it someday but at least background
- # won't rotate with the camera now.
- # Putting the map on a plane would not introduce the skysphere distortion and
- # allow for better image scale matching but also some waay to chose depth and
- # size of the plane relative to camera.
- tabWrite("sky_sphere {\n")
- tabWrite("pigment {\n")
- tabWrite(
- "image_map{%s \"%s\" %s}\n"
- % (
- imageFormat(texturesBlend),
- texturesBlend,
- imgMapBG(t_blend),
+ tabWrite("}\n")
+ tabWrite("%s\n" % (mappingBlend))
+ # The following layered pigment opacifies to black over the texture for
+ # transmit below 1 or otherwise adds to itself
+ tabWrite(
+ "pigment {rgb 0 transmit %s}\n" % (tex.intensity)
)
- )
- tabWrite("}\n")
- tabWrite("%s\n" % (mappingBlend))
- # The following layered pigment opacifies to black over the texture for
- # transmit below 1 or otherwise adds to itself
- tabWrite(
- "pigment {rgb 0 transmit %s}\n" % (t.texture.intensity)
- )
- tabWrite("}\n")
- # tabWrite("scale 2\n")
- # tabWrite("translate -1\n")
+ tabWrite("}\n")
+ # tabWrite("scale 2\n")
+ # tabWrite("translate -1\n")
# For only Background gradient
@@ -4910,7 +4990,8 @@ def write_pov(filename, scene=None, info_callback=None):
"//--Exported with POV-Ray exporter for Blender--\n"
"//----------------------------------------------\n\n"
)
- file.write("#version 3.7;\n")
+ file.write("#version 3.7;\n") #Switch below as soon as 3.8 beta gets easy linked
+ #file.write("#version 3.8;\n")
file.write(
"#declare Default_texture = texture{pigment {rgb 0.8} "
"finish {brilliance 3.8} }\n\n"
@@ -5066,7 +5147,11 @@ def write_pov(filename, scene=None, info_callback=None):
if comments:
file.write("//--Mesh objects--\n")
+
+ #tbefore = time.time()
exportMeshes(scene, sel, csg)
+ #totime = time.time() - tbefore
+ #print("exportMeshes took" + str(totime))
# What follow used to happen here:
# exportCamera()
@@ -5097,7 +5182,7 @@ def write_pov_ini(
y = int(render.resolution_y * render.resolution_percentage * 0.01)
file = open(filename_ini, "w")
- file.write("Version=3.7\n")
+ file.write("Version=3.8\n")
# write povray text stream to temporary file of same name with _log suffix
# file.write("All_File='%s'\n" % filename_log)
# DEBUG.OUT log if none specified:
@@ -5797,15 +5882,106 @@ class PovrayRender(bpy.types.RenderEngine):
# print(filename_log) #bring the pov log to blender console with proper path?
with open(
- self._temp_file_log
+ self._temp_file_log,
+ encoding='utf-8'
) as f: # The with keyword automatically closes the file when you are done
- print(f.read())
+ msg = f.read()
+ #if isinstance(msg, str):
+ #stdmsg = msg
+ #decoded = False
+ #else:
+ #if type(msg) == bytes:
+ #stdmsg = msg.split('\n')
+ #stdmsg = msg.encode('utf-8', "replace")
+ #stdmsg = msg.encode("utf-8", "replace")
+
+ #stdmsg = msg.decode(encoding)
+ #decoded = True
+ #msg.encode('utf-8').decode('utf-8')
+ print(msg)
+ # Also print to the interactive console used in POV centric workspace
+ # To do: get a grip on new line encoding
+ # and make this a function to be used elsewhere
+ for win in bpy.context.window_manager.windows:
+ if win.screen != None:
+ scr = win.screen
+ for area in scr.areas:
+ if area.type == 'CONSOLE':
+ #context override
+ #ctx = {'window': win, 'screen': scr, 'area':area}#bpy.context.copy()
+ ctx = {}
+ ctx['area'] = area
+ ctx['region'] = area.regions[-1]
+ ctx['space_data'] = area.spaces.active
+ ctx['screen'] = scr#C.screen
+ ctx['window'] = win
+
+ #bpy.ops.console.banner(ctx, text = "Hello world")
+ bpy.ops.console.clear_line(ctx)
+ stdmsg = msg.split('\n') #XXX todo , test and see
+ for i in stdmsg:
+ bpy.ops.console.insert(ctx, text = i)
self.update_stats("", "")
if scene.pov.tempfiles_enable or scene.pov.deletefiles_enable:
self._cleanup()
+ sound_on = bpy.context.preferences.addons[
+ __package__
+ ].preferences.use_sounds
+
+ if sys.platform[:3] == "win" and sound_on:
+ # Could not find tts Windows command so playing beeps instead :-)
+ # "Korobeiniki"(Коробе́йники)
+ # aka "A-Type" Tetris theme
+ import winsound
+ winsound.Beep(494,250) #B
+ winsound.Beep(370,125) #F
+ winsound.Beep(392,125) #G
+ winsound.Beep(440,250) #A
+ winsound.Beep(392,125) #G
+ winsound.Beep(370,125) #F#
+ winsound.Beep(330,275) #E
+ winsound.Beep(330,125) #E
+ winsound.Beep(392,125) #G
+ winsound.Beep(494,275) #B
+ winsound.Beep(440,125) #A
+ winsound.Beep(392,125) #G
+ winsound.Beep(370,275) #F
+ winsound.Beep(370,125) #F
+ winsound.Beep(392,125) #G
+ winsound.Beep(440,250) #A
+ winsound.Beep(494,250) #B
+ winsound.Beep(392,250) #G
+ winsound.Beep(330,350) #E
+ time.sleep(0.5)
+ winsound.Beep(440,250) #A
+ winsound.Beep(440,150) #A
+ winsound.Beep(523,125) #D8
+ winsound.Beep(659,250) #E8
+ winsound.Beep(587,125) #D8
+ winsound.Beep(523,125) #C8
+ winsound.Beep(494,250) #B
+ winsound.Beep(494,125) #B
+ winsound.Beep(392,125) #G
+ winsound.Beep(494,250) #B
+ winsound.Beep(440,150) #A
+ winsound.Beep(392,125) #G
+ winsound.Beep(370,250) #F#
+ winsound.Beep(370,125) #F#
+ winsound.Beep(392,125) #G
+ winsound.Beep(440,250) #A
+ winsound.Beep(494,250) #B
+ winsound.Beep(392,250) #G
+ winsound.Beep(330,300) #E
+
+ #Does Linux support say command?
+ elif sys.platform[:3] != "win" :
+ finished_render_message = "\'Render completed\'"
+ # We don't want the say command to block Python,
+ # so we add an ampersand after the message
+ os.system("say %s &" % (finished_render_message))
##################################################################################
#################################Operators########################################
@@ -5833,7 +6009,7 @@ class RenderPovTexturePreview(Operator):
outputPrevFile = os.path.join(preview_dir, texPrevName)
##################### ini ##########################################
fileIni = open("%s" % iniPrevFile, "w")
- fileIni.write('Version=3.7\n')
+ fileIni.write('Version=3.8\n')
fileIni.write('Input_File_Name="%s"\n' % inputPrevFile)
fileIni.write('Output_File_Name="%s.png"\n' % outputPrevFile)
fileIni.write('Library_Path="%s"\n' % preview_dir)
diff --git a/render_povray/shading.py b/render_povray/shading.py
index ac1f923f..a3f907dc 100644
--- a/render_povray/shading.py
+++ b/render_povray/shading.py
@@ -155,7 +155,7 @@ def writeMaterial(using_uberpov, DEF_MAT_NAME, scene, tabWrite, safety, comments
elif Level == 1:
if (material.pov.specular_shader == 'COOKTORR' or
material.pov.specular_shader == 'PHONG'):
- tabWrite("phong %.3g\n" % (material.pov.specular_intensity/5))
+ tabWrite("phong 0\n")#%.3g\n" % (material.pov.specular_intensity/5))
tabWrite("phong_size %.3g\n" % (material.pov.specular_hardness /3.14))
# POV-Ray 'specular' keyword corresponds to a Blinn model, without the ior.
@@ -183,8 +183,10 @@ def writeMaterial(using_uberpov, DEF_MAT_NAME, scene, tabWrite, safety, comments
# specular for some values.
tabWrite("brilliance %.4g\n" % (1.8 - material.pov.specular_slope * 1.8))
elif Level == 3:
- tabWrite("specular %.3g\n" % ((material.pov.specular_intensity*material.pov.specular_color.v)*5))
- tabWrite("roughness %.3g\n" % (1.1/material.pov.specular_hardness))
+ # Spec must be Max at Level 3 so that white of mixing texture always shows specularity
+ # That's why it's multiplied by 255. maybe replace by texture's brightest pixel value?
+ tabWrite("specular %.3g\n" % ((material.pov.specular_intensity*material.pov.specular_color.v)*(255* slot.specular_factor)))
+ tabWrite("roughness %.3g\n" % (1/material.pov.specular_hardness))
tabWrite("diffuse %.3g %.3g\n" % (frontDiffuse, backDiffuse))
tabWrite("ambient %.3g\n" % material.pov.ambient)
@@ -265,12 +267,12 @@ def writeMaterial(using_uberpov, DEF_MAT_NAME, scene, tabWrite, safety, comments
if material:
special_texture_found = False
- idx = -1
+ tmpidx = -1
for t in material.pov_texture_slots:
- idx += 1
+ tmpidx += 1
# index = material.pov.active_texture_index
- slot = material.pov_texture_slots[idx] # [index]
- povtex = slot.name
+ slot = material.pov_texture_slots[tmpidx] # [index]
+ povtex = slot.texture # slot.name
tex = bpy.data.textures[povtex]
if t and t.use and tex is not None:
@@ -777,7 +779,7 @@ def exportPattern(texture, string_strip_hyphen):
return(texStrg)
-def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image, lampCount,
+def writeTextureInfluence(using_uberpov, mater, materialNames, LocalMaterialNames, path_image, lampCount,
imageFormat, imgMap, imgMapTransforms, tabWrite, comments,
string_strip_hyphen, safety, col, os, preview_dir, unpacked_images):
"""Translate Blender texture influences to various POV texture tricks and write to pov file."""
@@ -805,14 +807,15 @@ def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image,
texturesNorm = ""
texturesAlpha = ""
#proceduralFlag=False
+ tmpidx = -1
for t in mater.pov_texture_slots:
- idx = -1
- for t in mater.pov_texture_slots:
- idx += 1
- # index = mater.pov.active_texture_index
- slot = mater.pov_texture_slots[idx] # [index]
- povtex = slot.name
- tex = bpy.data.textures[povtex]
+
+
+ tmpidx += 1
+ # index = mater.pov.active_texture_index
+ slot = mater.pov_texture_slots[tmpidx] # [index]
+ povtex = slot.texture # slot.name
+ tex = bpy.data.textures[povtex]
if t and (t.use and (tex is not None)):
# 'NONE' ('NONE' type texture is different from no texture covered above)
@@ -876,11 +879,13 @@ def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image,
# IMAGE SEQUENCE ENDS
imgGamma = ""
if image_filename:
+ texdata = bpy.data.textures[t.texture]
if t.use_map_color_diffuse:
texturesDif = image_filename
# colvalue = t.default_value # UNUSED
t_dif = t
- if t_dif.texture.pov.tex_gamma_enable:
+ print (texdata)
+ if texdata.pov.tex_gamma_enable:
imgGamma = (" gamma %.3g " % t_dif.texture.pov.tex_gamma_value)
if t.use_map_specular or t.use_map_raymir:
texturesSpec = image_filename
@@ -913,6 +918,7 @@ def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image,
if mater.pov.replacement_text != "":
tabWrite("%s\n" % mater.pov.replacement_text)
#################################################################################
+ # XXX TODO: replace by new POV MINNAERT rather than aoi
if mater.pov.diffuse_shader == 'MINNAERT':
tabWrite("\n")
tabWrite("aoi\n")
@@ -1056,12 +1062,36 @@ def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image,
mappingNor =imgMapTransforms(t_nor)
if texturesNorm and texturesNorm.startswith("PAT_"):
- tabWrite("normal{function{f%s(x,y,z).grey} bump_size %.4g %s}\n" %(texturesNorm, t_nor.normal_factor, mappingNor))
+ tabWrite("normal{function{f%s(x,y,z).grey} bump_size %.4g %s}\n" %(texturesNorm, ( - t_nor.normal_factor * 9.5), mappingNor))
else:
- tabWrite("normal {uv_mapping bump_map " \
- "{%s \"%s\" %s bump_size %.4g }%s}\n" % \
+ tabWrite("normal {\n")
+ # XXX TODO: fix and propagate the micro normals reflection blur below to non textured materials
+ if (mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov):
+ tabWrite("average\n")
+ tabWrite("normal_map{\n")
+ # 0.5 for entries below means a 50 percent mix
+ # between the micro normal and user bump map
+ # order seems indifferent as commutative
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(10/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.1]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.15]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.2]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.25]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.3]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.35]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.4]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.45]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.5]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[1.0 ") # Proceed with user bump...
+ tabWrite("uv_mapping bump_map " \
+ "{%s \"%s\" %s bump_size %.4g }%s" % \
(imageFormat(texturesNorm), texturesNorm, imgMap(t_nor),
- t_nor.normal_factor, mappingNor))
+ ( - t_nor.normal_factor * 9.5), mappingNor))
+ # ...Then close its last entry and the the normal_map itself
+ if (mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov):
+ tabWrite("]}}\n")
+ else:
+ tabWrite("]}\n")
if texturesSpec != "":
tabWrite("]\n")
##################Second index for mapping specular max value###############
@@ -1094,6 +1124,35 @@ def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image,
# Level 3 is full specular
tabWrite("finish {%s}\n" % (safety(material_finish, Level=3)))
+ if mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov:
+ tabWrite("normal {\n")
+ tabWrite("average\n")
+ tabWrite("normal_map{\n")
+ # 0.5 for entries below means a 50 percent mix
+ # between the micro normal and user bump map
+ # order seems indifferent as commutative
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(10/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.1]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.15]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.2]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.25]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.3]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.35]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.4]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.45]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.5]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ #XXX IF USER BUMP_MAP
+ if texturesNorm != "":
+ tabWrite("[1.0 ") # Blurry reflection or not Proceed with user bump in either case...
+ tabWrite("uv_mapping bump_map " \
+ "{%s \"%s\" %s bump_size %.4g }%s]\n" % \
+ (imageFormat(texturesNorm), texturesNorm, imgMap(t_nor),
+ ( - t_nor.normal_factor * 9.5), mappingNor))
+ # ...Then close the normal_map itself if blurry reflection
+ if mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov:
+ tabWrite("}}\n")
+ else:
+ tabWrite("}\n")
elif colored_specular_found:
# Level 1 is no specular
tabWrite("finish {%s}\n" % (safety(material_finish, Level=1)))
@@ -1166,11 +1225,36 @@ def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image,
mappingNor =imgMapTransforms(t_nor)
if texturesNorm and texturesNorm.startswith("PAT_"):
- tabWrite("normal{function{f%s(x,y,z).grey} bump_size %.4g %s}\n" %(texturesNorm, t_nor.normal_factor, mappingNor))
+ tabWrite("normal{function{f%s(x,y,z).grey} bump_size %.4g %s}\n" %(texturesNorm, ( - t_nor.normal_factor * 9.5), mappingNor))
else:
- tabWrite("normal {uv_mapping bump_map {%s \"%s\" %s bump_size %.4g }%s}\n" % \
+ tabWrite("normal {\n")
+ # XXX TODO: fix and propagate the micro normals reflection blur below to non textured materials
+ if mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov:
+ tabWrite("average\n")
+ tabWrite("normal_map{\n")
+ # 0.5 for entries below means a 50 percent mix
+ # between the micro normal and user bump map
+ # order seems indifferent as commutative
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(10/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.1]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.15]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.2]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.25]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.3]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.35]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.4]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.45]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.5]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring
+ tabWrite("[1.0 ") # Blurry reflection or not Proceed with user bump in either case...
+ tabWrite("uv_mapping bump_map " \
+ "{%s \"%s\" %s bump_size %.4g }%s]\n" % \
(imageFormat(texturesNorm), texturesNorm, imgMap(t_nor),
- t_nor.normal_factor, mappingNor))
+ ( - t_nor.normal_factor * 9.5), mappingNor))
+ # ...Then close the normal_map itself if blurry reflection
+ if mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov:
+ tabWrite("}}\n")
+ else:
+ tabWrite("}\n")
if texturesSpec != "" and mater.pov.replacement_text == "":
tabWrite("]\n")
@@ -1201,12 +1285,12 @@ def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image,
# Write another layered texture using invisible diffuse and metallic trick
# to emulate colored specular highlights
special_texture_found = False
- idx = -1
+ tmpidx = -1
for t in mater.pov_texture_slots:
- idx += 1
+ tmpidx += 1
# index = mater.pov.active_texture_index
- slot = mater.pov_texture_slots[idx] # [index]
- povtex = slot.name
+ slot = mater.pov_texture_slots[tmpidx] # [index]
+ povtex = slot.texture # slot.name
tex = bpy.data.textures[povtex]
if(t and t.use and ((tex.type == 'IMAGE' and tex.image) or tex.type != 'IMAGE') and
(t.use_map_specular or t.use_map_raymir)):
@@ -1240,7 +1324,7 @@ def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image,
if image_filename:
if t.use_map_normal:
texturesNorm = image_filename
- # colvalue = t.normal_factor/10 # UNUSED
+ # colvalue = t.normal_factor/10 # UNUSED XXX *-9.5 !
#textNormName=tex.image.name + ".normal"
#was the above used? --MR
t_nor = t
@@ -1248,13 +1332,13 @@ def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image,
tabWrite("normal{function" \
"{f%s(x,y,z).grey} bump_size %.4g}\n" % \
(texturesNorm,
- t_nor.normal_factor))
+ ( - t_nor.normal_factor * 9.5)))
else:
tabWrite("normal {uv_mapping bump_map " \
"{%s \"%s\" %s bump_size %.4g }%s}\n" % \
(imageFormat(texturesNorm),
texturesNorm, imgMap(t_nor),
- t_nor.normal_factor,
+ ( - t_nor.normal_factor * 9.5),
mappingNor))
tabWrite("}\n") # THEN IT CAN CLOSE LAST LAYER OF TEXTURE
diff --git a/render_povray/ui.py b/render_povray/ui.py
index e15a9374..6bdadccf 100644
--- a/render_povray/ui.py
+++ b/render_povray/ui.py
@@ -22,11 +22,15 @@
import bpy
import sys # really import here and in render.py?
import os # really import here and in render.py?
+import addon_utils
+from time import sleep
from os.path import isfile
+from bpy.app.handlers import persistent
from bl_operators.presets import AddPresetBase
from bpy.utils import register_class, unregister_class
from bpy.types import (
Operator,
+ Menu,
UIList,
Panel,
Brush,
@@ -43,17 +47,29 @@ from bl_ui import properties_output
for member in dir(properties_output):
subclass = getattr(properties_output, member)
try:
- subclass.COMPAT_ENGINES.add('POVRAY')
+ subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
except:
pass
del properties_output
+from bl_ui import properties_freestyle
+for member in dir(properties_freestyle):
+ subclass = getattr(properties_freestyle, member)
+ try:
+ if not (subclass.bl_space_type == 'PROPERTIES'
+ and subclass.bl_context == "render"):
+ subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
+ #subclass.bl_parent_id = "RENDER_PT_POV_filter"
+ except:
+ pass
+del properties_freestyle
+
from bl_ui import properties_view_layer
for member in dir(properties_view_layer):
subclass = getattr(properties_view_layer, member)
try:
- subclass.COMPAT_ENGINES.add('POVRAY')
+ subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
except:
pass
del properties_view_layer
@@ -242,19 +258,136 @@ for member in dir(
pass
del properties_particle
-# Example of wrapping every class 'as is'
-from bl_ui import properties_output
-for member in dir(properties_output):
- subclass = getattr(properties_output, member)
- try:
- subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
- except:
- pass
-del properties_output
+############# POV-Centric WORSPACE #############
+@persistent
+def povCentricWorkspace(dummy):
+ """Set up a POV centric Workspace if addon was activated and saved as default renderer
+
+ This would bring a ’_RestrictData’ error because UI needs to be fully loaded before
+ workspace changes so registering this function in bpy.app.handlers is needed.
+ By default handlers are freed when loading new files, but here we want the handler
+ to stay running across multiple files as part of this add-on. That is why the the
+ bpy.app.handlers.persistent decorator is used (@persistent) above.
+ """
+
+ wsp = bpy.data.workspaces.get('Scripting')
+ context = bpy.context
+ if wsp is not None and context.scene.render.engine == 'POVRAY_RENDER':
+ new_wsp = bpy.ops.workspace.duplicate({'workspace': wsp})
+ bpy.data.workspaces['Scripting.001'].name='POV'
+ # Already done it would seem, but explicitly make this workspaces the active one
+ context.window.workspace = bpy.data.workspaces['POV']
+ pov_screen = bpy.data.workspaces['POV'].screens[0]
+ pov_workspace = pov_screen.areas
+
+
+ override = bpy.context.copy()
+
+ for area in pov_workspace:
+ if area.type == 'VIEW_3D':
+ for region in [r for r in area.regions if r.type == 'WINDOW']:
+ for space in area.spaces:
+ if space.type == 'VIEW_3D':
+ #override['screen'] = pov_screen
+ override['area'] = area
+ override['region']= region
+ #bpy.data.workspaces['POV'].screens[0].areas[6].spaces[0].width = 333 # Read only, how do we set ?
+ #This has a glitch:
+ #bpy.ops.screen.area_move(override, x=(area.x + area.width), y=(area.y + 5), delta=100)
+ #bpy.ops.screen.area_move(override, x=(area.x + 5), y=area.y, delta=-100)
+
+ bpy.ops.screen.space_type_set_or_cycle(override, space_type = 'TEXT_EDITOR')
+ space.show_region_ui = True
+ #bpy.ops.screen.region_scale(override)
+ #bpy.ops.screen.region_scale()
+ break
+
+ elif area.type == 'CONSOLE':
+ for region in [r for r in area.regions if r.type == 'WINDOW']:
+ for space in area.spaces:
+ if space.type == 'CONSOLE':
+ #override['screen'] = pov_screen
+ override['area'] = area
+ override['region']= region
+ bpy.ops.screen.space_type_set_or_cycle(override, space_type = 'INFO')
+
+ break
+ elif area.type == 'INFO':
+ for region in [r for r in area.regions if r.type == 'WINDOW']:
+ for space in area.spaces:
+ if space.type == 'INFO':
+ #override['screen'] = pov_screen
+ override['area'] = area
+ override['region']= region
+ bpy.ops.screen.space_type_set_or_cycle(override, space_type = 'CONSOLE')
+
+ break
+
+ elif area.type == 'TEXT_EDITOR':
+ for region in [r for r in area.regions if r.type == 'WINDOW']:
+ for space in area.spaces:
+ if space.type == 'TEXT_EDITOR':
+ #override['screen'] = pov_screen
+ override['area'] = area
+ override['region']= region
+ #bpy.ops.screen.space_type_set_or_cycle(space_type='VIEW_3D')
+ #space.type = 'VIEW_3D'
+ bpy.ops.screen.space_type_set_or_cycle(override, space_type = 'VIEW_3D')
+
+ #bpy.ops.screen.area_join(override, cursor=(area.x, area.y + area.height))
+
+ break
+
+
+ if area.type == 'VIEW_3D':
+ for region in [r for r in area.regions if r.type == 'WINDOW']:
+ for space in area.spaces:
+ if space.type == 'VIEW_3D':
+ #override['screen'] = pov_screen
+ override['area'] = area
+ override['region']= region
+ bpy.ops.screen.region_quadview(override)
+ space.region_3d.view_perspective = 'CAMERA'
+ #bpy.ops.screen.space_type_set_or_cycle(override, space_type = 'TEXT_EDITOR')
+ #bpy.ops.screen.region_quadview(override)
+
+
+
+
-class WORLD_MT_POV_presets(bpy.types.Menu):
+ bpy.data.workspaces.update()
+ # Already outliners but invert both types
+ pov_workspace[1].spaces[0].display_mode = 'LIBRARIES'
+ pov_workspace[3].spaces[0].display_mode = 'VIEW_LAYER'
+
+ '''
+ for window in bpy.context.window_manager.windows:
+ for area in [a for a in window.screen.areas if a.type == 'VIEW_3D']:
+ for region in [r for r in area.regions if r.type == 'WINDOW']:
+ context_override = {
+ 'window': window,
+ 'screen': window.screen,
+ 'area': area,
+ 'region': region,
+ 'space_data': area.spaces.active,
+ 'scene': bpy.context.scene
+ }
+ bpy.ops.view3d.camera_to_view(context_override)
+ '''
+
+
+ else:
+ print("default 'Scripting' workspace needed for POV centric Workspace")
+
+
+
+
+
+
+
+class WORLD_MT_POV_presets(Menu):
bl_label = "World Presets"
preset_subdir = "pov/world"
preset_operator = "script.execute_preset"
@@ -262,7 +395,7 @@ class WORLD_MT_POV_presets(bpy.types.Menu):
class WORLD_OT_POV_add_preset(AddPresetBase, Operator):
- '''Add a World Preset'''
+ """Add a World Preset"""
bl_idname = "object.world_preset_add"
bl_label = "Add World Preset"
@@ -324,6 +457,15 @@ def check_add_mesh_extra_objects():
return True
return False
+def check_render_freestyle_svg():
+ """Test if Freestyle SVG Exporter addon is activated
+
+ This addon is currently used to generate the SVG lines file
+ when Freestyle is enabled alongside POV
+ """
+ if "render_freestyle_svg" in bpy.context.preferences.addons.keys():
+ return True
+ return False
def locate_docpath():
"""POV can be installed with some include files.
@@ -373,31 +515,29 @@ def pov_context_tex_datablock(context):
"""Texture context type recreated as deprecated in blender 2.8"""
idblock = context.brush
- if idblock and bpy.context.scene.texture_context == 'OTHER':
+ if idblock and context.scene.texture_context == 'OTHER':
return idblock
# idblock = bpy.context.active_object.active_material
- idblock = bpy.context.scene.view_layers[
- "View Layer"
- ].objects.active.active_material
- if idblock:
+ idblock = context.view_layer.objects.active.active_material
+ if idblock and context.scene.texture_context == 'MATERIAL':
return idblock
- idblock = context.world
- if idblock:
+ idblock = context.scene.world
+ if idblock and context.scene.texture_context == 'WORLD':
return idblock
idblock = context.light
- if idblock:
+ if idblock and context.scene.texture_context == 'LIGHT':
return idblock
- if context.particle_system:
+ if context.particle_system and context.scene.texture_context == 'PARTICLES':
idblock = context.particle_system.settings
return idblock
idblock = context.line_style
- if idblock:
+ if idblock and context.scene.texture_context == 'LINESTYLE':
return idblock
@@ -688,7 +828,7 @@ class LIGHT_PT_POV_light(PovLampButtonsPanel, Panel):
draw = properties_data_light.DATA_PT_light.draw
-class LIGHT_MT_POV_presets(bpy.types.Menu):
+class LIGHT_MT_POV_presets(Menu):
"""Use this class to define preset menu for pov lights."""
bl_label = "Lamp Presets"
@@ -1114,9 +1254,8 @@ class WORLD_PT_POV_mist(WorldButtonsPanel, Panel):
class RENDER_PT_POV_export_settings(RenderButtonsPanel, Panel):
"""Use this class to define pov ini settingss buttons."""
-
- bl_label = "Start Options"
bl_options = {'DEFAULT_CLOSED'}
+ bl_label = "Auto Start"
COMPAT_ENGINES = {'POVRAY_RENDER'}
def draw_header(self, context):
@@ -1131,6 +1270,7 @@ class RENDER_PT_POV_export_settings(RenderButtonsPanel, Panel):
)
def draw(self, context):
+
layout = self.layout
scene = context.scene
@@ -1143,25 +1283,25 @@ class RENDER_PT_POV_export_settings(RenderButtonsPanel, Panel):
col.prop(scene.pov, "command_line_switches", text="")
split = layout.split()
- layout.active = not scene.pov.tempfiles_enable
- # if not scene.pov.tempfiles_enable:
- split.prop(scene.pov, "deletefiles_enable", text="Delete files")
- split.prop(scene.pov, "pov_editor", text="POV Editor")
+ #layout.active = not scene.pov.tempfiles_enable
+ if not scene.pov.tempfiles_enable:
+ split.prop(scene.pov, "deletefiles_enable", text="Delete files")
+ split.prop(scene.pov, "pov_editor", text="POV Editor")
- col = layout.column()
- col.prop(scene.pov, "scene_name", text="Name")
- col.prop(scene.pov, "scene_path", text="Path to files")
- # col.prop(scene.pov, "scene_path", text="Path to POV-file")
- # col.prop(scene.pov, "renderimage_path", text="Path to image")
+ col = layout.column()
+ col.prop(scene.pov, "scene_name", text="Name")
+ col.prop(scene.pov, "scene_path", text="Path to files")
+ # col.prop(scene.pov, "scene_path", text="Path to POV-file")
+ # col.prop(scene.pov, "renderimage_path", text="Path to image")
- split = layout.split()
- split.prop(scene.pov, "indentation_character", text="Indent")
- if scene.pov.indentation_character == 'SPACE':
- split.prop(scene.pov, "indentation_spaces", text="Spaces")
+ split = layout.split()
+ split.prop(scene.pov, "indentation_character", text="Indent")
+ if scene.pov.indentation_character == 'SPACE':
+ split.prop(scene.pov, "indentation_spaces", text="Spaces")
- row = layout.row()
- row.prop(scene.pov, "comments_enable", text="Comments")
- row.prop(scene.pov, "list_lf_enable", text="Line breaks in lists")
+ row = layout.row()
+ row.prop(scene.pov, "comments_enable", text="Comments")
+ row.prop(scene.pov, "list_lf_enable", text="Line breaks in lists")
class RENDER_PT_POV_render_settings(RenderButtonsPanel, Panel):
@@ -1414,7 +1554,7 @@ class RENDER_PT_POV_radiosity(RenderButtonsPanel, Panel):
col.prop(scene.pov, "radio_subsurface")
-class POV_RADIOSITY_MT_presets(bpy.types.Menu):
+class POV_RADIOSITY_MT_presets(Menu):
"""Use this class to define pov radiosity presets menu."""
bl_label = "Radiosity Presets"
@@ -1562,7 +1702,7 @@ class MODIFIERS_PT_POV_modifiers(ModifierButtonsPanel, Panel):
col.prop(ob.pov, "inside_vector")
-class MATERIAL_MT_POV_sss_presets(bpy.types.Menu):
+class MATERIAL_MT_POV_sss_presets(Menu):
"""Use this class to define pov sss preset menu."""
bl_label = "SSS Presets"
@@ -1872,7 +2012,7 @@ class MATERIAL_PT_POV_mirror(MaterialButtonsPanel, Panel):
sub = col.column()
sub.active = raym.gloss_factor < 1.0
sub.prop(raym, "gloss_threshold", text="Threshold")
- sub.prop(raym, "gloss_samples", text="Samples")
+ sub.prop(raym, "gloss_samples", text="Noise")
sub.prop(raym, "gloss_anisotropic", text="Anisotropic")
@@ -2178,7 +2318,7 @@ class MATERIAL_PT_POV_replacement_text(MaterialButtonsPanel, Panel):
col.prop(mat.pov, "replacement_text", text="")
-class TEXTURE_MT_POV_specials(bpy.types.Menu):
+class TEXTURE_MT_POV_specials(Menu):
"""Use this class to define pov texture slot operations buttons."""
bl_label = "Texture Specials"
@@ -2191,14 +2331,20 @@ class TEXTURE_MT_POV_specials(bpy.types.Menu):
layout.operator("texture.slot_paste", icon='PASTEDOWN')
-class TEXTURE_UL_POV_texture_slots(bpy.types.UIList):
- """Use this class to show pov texture slots list.""" # used?
-
- COMPAT_ENGINES = {'POVRAY_RENDER'}
+class WORLD_TEXTURE_SLOTS_UL_POV_layerlist(UIList):
+ """Use this class to show pov texture slots list.""" # XXX Not used yet
+ index: bpy.props.IntProperty(name='index')
def draw_item(
self, context, layout, data, item, icon, active_data, active_propname
):
+ world = context.scene.world # .pov
+ active_data = world.pov
+ # tex = context.texture #may be needed later?
+
+ # We could write some code to decide which icon to use here...
+ custom_icon = 'TEXTURE'
+
ob = data
slot = item
# ma = slot.name
@@ -2220,62 +2366,7 @@ class TEXTURE_UL_POV_texture_slots(bpy.types.UIList):
layout.label(text="", icon_value=icon)
-'''
-class MATERIAL_TEXTURE_SLOTS_UL_List(UIList):
- """Texture Slots UIList."""
-
-
- def draw_item(self, context, layout, material, item, icon, active_data,
- material_texture_list_index, index):
- material = context.material#.pov
- active_data = material
- #tex = context.texture #may be needed later?
-
-
- # We could write some code to decide which icon to use here...
- custom_icon = 'TEXTURE'
-
- # Make sure your code supports all 3 layout types
- if self.layout_type in {'DEFAULT', 'COMPACT'}:
- layout.label(item.name, icon = custom_icon)
-
- elif self.layout_type in {'GRID'}:
- layout.alignment = 'CENTER'
- layout.label("", icon = custom_icon)
-'''
-
-
-class WORLD_TEXTURE_SLOTS_UL_List(UIList):
- """Use this class to show pov texture slots list.""" # XXX Not used yet
-
- def draw_item(
- self,
- context,
- layout,
- world,
- item,
- icon,
- active_data,
- active_texture_index,
- index,
- ):
- world = context.world # .pov
- active_data = world.pov
- # tex = context.texture #may be needed later?
-
- # We could write some code to decide which icon to use here...
- custom_icon = 'TEXTURE'
-
- # Make sure your code supports all 3 layout types
- if self.layout_type in {'DEFAULT', 'COMPACT'}:
- layout.label(item.name, icon=custom_icon)
-
- elif self.layout_type in {'GRID'}:
- layout.alignment = 'CENTER'
- layout.label("", icon=custom_icon)
-
-
-class MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist(bpy.types.UIList):
+class MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist(UIList):
"""Use this class to show pov texture slots list."""
# texture_slots:
@@ -2304,6 +2395,53 @@ class MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist(bpy.types.UIList):
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
+# Rewrite an existing class to modify.
+# register but not unregistered because
+# the modified parts concern only POVRAY_RENDER
+class TEXTURE_PT_context(TextureButtonsPanel, Panel):
+ bl_label = ""
+ bl_context = "texture"
+ bl_options = {'HIDE_HEADER'}
+ COMPAT_ENGINES = {'POVRAY_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+
+ @classmethod
+ def poll(cls, context):
+ return (
+ (context.scene.texture_context
+ not in('MATERIAL','WORLD','LIGHT','PARTICLES','LINESTYLE')
+ or context.scene.render.engine != 'POVRAY_RENDER')
+ )
+ def draw(self, context):
+ layout = self.layout
+ tex = context.texture
+ space = context.space_data
+ pin_id = space.pin_id
+ use_pin_id = space.use_pin_id
+ user = context.texture_user
+
+ col = layout.column()
+
+ if not (use_pin_id and isinstance(pin_id, bpy.types.Texture)):
+ pin_id = None
+
+ if not pin_id:
+ col.template_texture_user()
+
+ if user or pin_id:
+ col.separator()
+
+ if pin_id:
+ col.template_ID(space, "pin_id")
+ else:
+ propname = context.texture_user_property.identifier
+ col.template_ID(user, propname, new="texture.new")
+
+ if tex:
+ col.separator()
+
+ split = col.split(factor=0.2)
+ split.label(text="Type")
+ split.prop(tex, "type", text="")
class TEXTURE_PT_POV_context_texture(TextureButtonsPanel, Panel):
"""Use this class to show pov texture context buttons."""
@@ -2316,11 +2454,11 @@ class TEXTURE_PT_POV_context_texture(TextureButtonsPanel, Panel):
def poll(cls, context):
engine = context.scene.render.engine
return engine in cls.COMPAT_ENGINES
- # if not (hasattr(context, "texture_slot") or hasattr(context, "texture_node")):
+ # if not (hasattr(context, "pov_texture_slot") or hasattr(context, "texture_node")):
# return False
return (
context.material
- or context.world
+ or context.scene.world
or context.light
or context.texture
or context.line_style
@@ -2333,11 +2471,12 @@ class TEXTURE_PT_POV_context_texture(TextureButtonsPanel, Panel):
layout = self.layout
scene = context.scene
+ mat = context.view_layer.objects.active.active_material
+ wld = context.scene.world
+
layout.prop(scene, "texture_context", expand=True)
- if scene.texture_context == 'MATERIAL':
- mat = context.scene.view_layers[
- "View Layer"
- ].objects.active.active_material
+ if scene.texture_context == 'MATERIAL' and mat is not None:
+
row = layout.row()
row.template_list(
"MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist",
@@ -2353,22 +2492,90 @@ class TEXTURE_PT_POV_context_texture(TextureButtonsPanel, Panel):
col = row.column(align=True)
col.operator("pov.textureslotadd", icon='ADD', text='')
col.operator("pov.textureslotremove", icon='REMOVE', text='')
+ #todo: recreate for pov_texture_slots?
+ #col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
+ #col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
col.separator()
if mat.pov_texture_slots:
index = mat.pov.active_texture_index
slot = mat.pov_texture_slots[index]
- povtex = slot.name
+ povtex = slot.texture#slot.name
tex = bpy.data.textures[povtex]
col.prop(tex, 'use_fake_user', text='')
- layout.label(text='Find texture:')
+ #layout.label(text='Linked Texture data browser:')
+ propname = slot.texture_search
+ # if slot.texture was a pointer to texture data rather than just a name string:
+ # layout.template_ID(povtex, "texture", new="texture.new")
+
layout.prop_search(
- slot, 'texture_search', bpy.data, 'textures', text=''
+ slot, 'texture_search', bpy.data, 'textures', text='', icon='TEXTURE'
)
+ try:
+ bpy.context.tool_settings.image_paint.brush.texture = bpy.data.textures[slot.texture_search]
+ bpy.context.tool_settings.image_paint.brush.mask_texture = bpy.data.textures[slot.texture_search]
+ except KeyError:
+ # texture not hand-linked by user
+ pass
+
+ if tex:
+ layout.separator()
+ split = layout.split(factor=0.2)
+ split.label(text="Type")
+ split.prop(tex, "type", text="")
+
# else:
# for i in range(18): # length of material texture slots
# mat.pov_texture_slots.add()
+ elif scene.texture_context == 'WORLD' and wld is not None:
+ row = layout.row()
+ row.template_list(
+ "WORLD_TEXTURE_SLOTS_UL_POV_layerlist",
+ "",
+ wld,
+ "pov_texture_slots",
+ wld.pov,
+ "active_texture_index",
+ rows=2,
+ maxrows=16,
+ type="DEFAULT"
+ )
+ col = row.column(align=True)
+ col.operator("pov.textureslotadd", icon='ADD', text='')
+ col.operator("pov.textureslotremove", icon='REMOVE', text='')
+
+ #todo: recreate for pov_texture_slots?
+ #col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
+ #col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
+ col.separator()
+
+ if wld.pov_texture_slots:
+ index = wld.pov.active_texture_index
+ slot = wld.pov_texture_slots[index]
+ povtex = slot.texture#slot.name
+ tex = bpy.data.textures[povtex]
+ col.prop(tex, 'use_fake_user', text='')
+ #layout.label(text='Linked Texture data browser:')
+ propname = slot.texture_search
+ # if slot.texture was a pointer to texture data rather than just a name string:
+ # layout.template_ID(povtex, "texture", new="texture.new")
+
+ layout.prop_search(
+ slot, 'texture_search', bpy.data, 'textures', text='', icon='TEXTURE'
+ )
+ try:
+ bpy.context.tool_settings.image_paint.brush.texture = bpy.data.textures[slot.texture_search]
+ bpy.context.tool_settings.image_paint.brush.mask_texture = bpy.data.textures[slot.texture_search]
+ except KeyError:
+ # texture not hand-linked by user
+ pass
+
+ if tex:
+ layout.separator()
+ split = layout.split(factor=0.2)
+ split.label(text="Type")
+ split.prop(tex, "type", text="")
# Commented out below is a reminder of what existed in Blender Internal
# attributes need to be recreated
@@ -2518,7 +2725,7 @@ class TEXTURE_PT_colors(TextureButtonsPanel, Panel):
# Texture Slot Panels #
-class MATERIAL_OT_POV_texture_slot_add(Operator):
+class TEXTURE_OT_POV_texture_slot_add(Operator):
"""Use this class for the add texture slot button."""
bl_idname = "pov.textureslotadd"
@@ -2528,18 +2735,29 @@ class MATERIAL_OT_POV_texture_slot_add(Operator):
COMPAT_ENGINES = {'POVRAY_RENDER'}
def execute(self, context):
-
+ idblock = pov_context_tex_datablock(context)
tex = bpy.data.textures.new(name='Texture', type='IMAGE')
- tex.use_fake_user = True
- ob = context.scene.view_layers["View Layer"].objects.active
- slot = ob.active_material.pov_texture_slots.add()
+ #tex.use_fake_user = True
+ #mat = context.view_layer.objects.active.active_material
+ slot = idblock.pov_texture_slots.add()
slot.name = tex.name
slot.texture = tex.name
+ slot.texture_search = tex.name
+ # Switch paint brush and paint brush mask
+ # to this texture so settings remain contextual
+ bpy.context.tool_settings.image_paint.brush.texture = tex
+ bpy.context.tool_settings.image_paint.brush.mask_texture = tex
+ idblock.pov.active_texture_index = (len(idblock.pov_texture_slots)-1)
+
+ #for area in bpy.context.screen.areas:
+ #if area.type in ['PROPERTIES']:
+ #area.tag_redraw()
+
return {'FINISHED'}
-class MATERIAL_OT_POV_texture_slot_remove(Operator):
+class TEXTURE_OT_POV_texture_slot_remove(Operator):
"""Use this class for the remove texture slot button."""
bl_idname = "pov.textureslotremove"
@@ -2549,14 +2767,23 @@ class MATERIAL_OT_POV_texture_slot_remove(Operator):
COMPAT_ENGINES = {'POVRAY_RENDER'}
def execute(self, context):
- pass
- # tex = bpy.data.textures.new()
- # tex_slot = context.object.active_material.pov_texture_slots.add()
- # tex_slot.name = tex.name
+ idblock = pov_context_tex_datablock(context)
+ #mat = context.view_layer.objects.active.active_material
+ tex_slot = idblock.pov_texture_slots.remove(idblock.pov.active_texture_index)
+ if idblock.pov.active_texture_index > 0:
+ idblock.pov.active_texture_index -= 1
+ try:
+ tex = idblock.pov_texture_slots[idblock.pov.active_texture_index].texture
+ except IndexError:
+ # No more slots
+ return {'FINISHED'}
+ # Switch paint brush to previous texture so settings remain contextual
+ # if 'tex' in locals(): # Would test is the tex variable is assigned / exists
+ bpy.context.tool_settings.image_paint.brush.texture = bpy.data.textures[tex]
+ bpy.context.tool_settings.image_paint.brush.mask_texture = bpy.data.textures[tex]
return {'FINISHED'}
-
class TextureSlotPanel(TextureButtonsPanel):
"""Use this class to show pov texture slots panel."""
@@ -2586,7 +2813,7 @@ class TEXTURE_PT_POV_type(TextureButtonsPanel, Panel):
tex = context.texture
split = layout.split(factor=0.2)
- split.label(text="POV:")
+ split.label(text="Pattern")
split.prop(tex.pov, "tex_pattern_type", text="")
# row = layout.row()
@@ -2631,6 +2858,7 @@ class TEXTURE_PT_POV_parameters(TextureButtonsPanel, Panel):
"""Use this class to define pov texture pattern buttons."""
bl_label = "POV Pattern Options"
+ bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'POVRAY_RENDER'}
def draw(self, context):
@@ -2911,6 +3139,112 @@ class TEXTURE_PT_POV_parameters(TextureButtonsPanel, Panel):
row.prop(tex.pov, "warp_turbulence_z", text="Z")
row.prop(tex.pov, "modifier_omega", text="Omega")
+class TEXTURE_PT_POV_mapping(TextureSlotPanel, Panel):
+ """Use this class to define POV texture mapping buttons"""
+ bl_label = "Mapping"
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+
+ @classmethod
+ def poll(cls, context):
+ idblock = pov_context_tex_datablock(context)
+ if isinstance(idblock, Brush) and not context.sculpt_object:
+ return False
+
+ if not getattr(context, "texture_slot", None):
+ return False
+
+ engine = context.scene.render.engine
+ return (engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+
+ idblock = pov_context_tex_datablock(context)
+
+ #tex = context.texture_slot
+ tex = mat.pov_texture_slots[
+ mat.active_texture_index
+ ]
+ if not isinstance(idblock, Brush):
+ split = layout.split(percentage=0.3)
+ col = split.column()
+ col.label(text="Coordinates:")
+ col = split.column()
+ col.prop(tex, "texture_coords", text="")
+
+ if tex.texture_coords == 'ORCO':
+ """
+ ob = context.object
+ if ob and ob.type == 'MESH':
+ split = layout.split(percentage=0.3)
+ split.label(text="Mesh:")
+ split.prop(ob.data, "texco_mesh", text="")
+ """
+ elif tex.texture_coords == 'UV':
+ split = layout.split(percentage=0.3)
+ split.label(text="Map:")
+ ob = context.object
+ if ob and ob.type == 'MESH':
+ split.prop_search(tex, "uv_layer", ob.data, "uv_textures", text="")
+ else:
+ split.prop(tex, "uv_layer", text="")
+
+ elif tex.texture_coords == 'OBJECT':
+ split = layout.split(percentage=0.3)
+ split.label(text="Object:")
+ split.prop(tex, "object", text="")
+
+ elif tex.texture_coords == 'ALONG_STROKE':
+ split = layout.split(percentage=0.3)
+ split.label(text="Use Tips:")
+ split.prop(tex, "use_tips", text="")
+
+ if isinstance(idblock, Brush):
+ if context.sculpt_object or context.image_paint_object:
+ brush_texture_settings(layout, idblock, context.sculpt_object)
+ else:
+ if isinstance(idblock, FreestyleLineStyle):
+ split = layout.split(percentage=0.3)
+ split.label(text="Projection:")
+ split.prop(tex, "mapping", text="")
+
+ split = layout.split(percentage=0.3)
+ split.separator()
+ row = split.row()
+ row.prop(tex, "mapping_x", text="")
+ row.prop(tex, "mapping_y", text="")
+ row.prop(tex, "mapping_z", text="")
+
+ elif isinstance(idblock, Material):
+ split = layout.split(percentage=0.3)
+ split.label(text="Projection:")
+ split.prop(tex, "mapping", text="")
+
+ split = layout.split()
+
+ col = split.column()
+ if tex.texture_coords in {'ORCO', 'UV'}:
+ col.prop(tex, "use_from_dupli")
+ if (idblock.type == 'VOLUME' and tex.texture_coords == 'ORCO'):
+ col.prop(tex, "use_map_to_bounds")
+ elif tex.texture_coords == 'OBJECT':
+ col.prop(tex, "use_from_original")
+ if (idblock.type == 'VOLUME'):
+ col.prop(tex, "use_map_to_bounds")
+ else:
+ col.label()
+
+ col = split.column()
+ row = col.row()
+ row.prop(tex, "mapping_x", text="")
+ row.prop(tex, "mapping_y", text="")
+ row.prop(tex, "mapping_z", text="")
+
+ row = layout.row()
+ row.column().prop(tex, "offset")
+ row.column().prop(tex, "scale")
class TEXTURE_PT_POV_influence(TextureSlotPanel, Panel):
"""Use this class to define pov texture influence buttons."""
@@ -2919,18 +3253,20 @@ class TEXTURE_PT_POV_influence(TextureSlotPanel, Panel):
COMPAT_ENGINES = {'POVRAY_RENDER'}
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
- # bl_context = 'texture'
+ #bl_context = 'texture'
@classmethod
def poll(cls, context):
idblock = pov_context_tex_datablock(context)
if (
- isinstance(idblock, Brush)
- and bpy.context.scene.texture_context == 'OTHER'
+ # isinstance(idblock, Brush) and # Brush used for everything since 2.8
+ context.scene.texture_context == 'OTHER'
): # XXX replace by isinstance(idblock, bpy.types.Brush) and ...
return False
- # if not getattr(context, "pov_texture_slot", None):
- # return False
+ # Specify below also for pov_world_texture_slots, lights etc.
+ # to display for various types of slots but only when any
+ if not getattr(idblock, "pov_texture_slots", None):
+ return False
engine = context.scene.render.engine
return engine in cls.COMPAT_ENGINES
@@ -2940,14 +3276,13 @@ class TEXTURE_PT_POV_influence(TextureSlotPanel, Panel):
layout = self.layout
idblock = pov_context_tex_datablock(context)
-
# tex = context.pov_texture_slot
- mat = bpy.context.active_object.active_material
- texslot = mat.pov_texture_slots[
- mat.active_texture_index
+ #mat = bpy.context.active_object.active_material
+ texslot = idblock.pov_texture_slots[
+ idblock.pov.active_texture_index
] # bpy.data.textures[mat.active_texture_index]
tex = bpy.data.textures[
- mat.pov_texture_slots[mat.active_texture_index].texture
+ idblock.pov_texture_slots[idblock.pov.active_texture_index].texture
]
def factor_but(layout, toggle, factor, name):
@@ -3756,7 +4091,7 @@ class OBJECT_PT_povray_replacement_text(ObjectButtonsPanel, Panel):
###############################################################################
-class VIEW_MT_POV_primitives_add(bpy.types.Menu):
+class VIEW_MT_POV_primitives_add(Menu):
"""Define the primitives menu with presets"""
bl_idname = "VIEW_MT_POV_primitives_add"
@@ -3777,7 +4112,7 @@ class VIEW_MT_POV_primitives_add(bpy.types.Menu):
layout.menu(VIEW_MT_POV_import.bl_idname, text="Import", icon="IMPORT")
-class VIEW_MT_POV_Basic_Shapes(bpy.types.Menu):
+class VIEW_MT_POV_Basic_Shapes(Menu):
"""Use this class to sort simple primitives menu entries."""
bl_idname = "POVRAY_MT_basic_shape_tools"
@@ -3859,7 +4194,7 @@ class VIEW_MT_POV_Basic_Shapes(bpy.types.Menu):
)
-class VIEW_MT_POV_import(bpy.types.Menu):
+class VIEW_MT_POV_import(Menu):
"""Use this class for the import menu."""
bl_idname = "POVRAY_MT_import_tools"
@@ -3910,7 +4245,7 @@ def menu_func_import(self, context):
# return True
-class NODE_MT_POV_map_create(bpy.types.Menu):
+class NODE_MT_POV_map_create(Menu):
"""Create maps"""
bl_idname = "POVRAY_MT_node_map_create"
@@ -4056,7 +4391,7 @@ def validinsert(ext):
return ext in {".txt", ".inc", ".pov"}
-class TEXT_MT_POV_insert(bpy.types.Menu):
+class TEXT_MT_POV_insert(Menu):
"""Use this class to create a menu launcher in text editor for the TEXT_OT_POV_insert operator ."""
bl_label = "Insert"
@@ -4116,10 +4451,10 @@ class TEXT_PT_POV_custom_code(TextButtonsPanel, Panel):
row = box.row()
row.prop(text.pov, "custom_code", expand=True)
if text.pov.custom_code in {'3dview'}:
- box.operator("render.render", icon='OUTLINER_DATA_POSE')
+ box.operator("render.render", icon='OUTLINER_DATA_ARMATURE')
if text.pov.custom_code in {'text'}:
rtext = bpy.context.space_data.text
- box.operator("text.run", icon='POSE_DATA')
+ box.operator("text.run", icon='ARMATURE_DATA')
# layout.prop(text.pov, "custom_code")
elif text.pov.custom_code in {'both'}:
box.operator("render.render", icon='POSE_HLT')
@@ -4133,7 +4468,7 @@ class TEXT_PT_POV_custom_code(TextButtonsPanel, Panel):
# Text editor templates from header menu
-class TEXT_MT_POV_templates(bpy.types.Menu):
+class TEXT_MT_POV_templates(Menu):
"""Use this class to create a menu for the same pov templates scenes as other pov IDEs."""
bl_label = "POV"
@@ -4154,12 +4489,111 @@ def menu_func_templates(self, context):
# Do not depend on POV being active renderer here...
self.layout.menu("TEXT_MT_POV_templates")
+###############################################################################
+# Freestyle
+###############################################################################
+#import addon_utils
+#addon_utils.paths()[0]
+#addon_utils.modules()
+#mod.bl_info['name'] == 'Freestyle SVG Exporter':
+bpy.utils.script_paths("addons")
+#render_freestyle_svg = os.path.join(bpy.utils.script_paths("addons"), "render_freestyle_svg.py")
+
+render_freestyle_svg = bpy.context.preferences.addons.get('render_freestyle_svg')
+ #mpath=addon_utils.paths()[0].render_freestyle_svg
+ #import mpath
+ #from mpath import render_freestyle_svg #= addon_utils.modules(['Freestyle SVG Exporter'])
+ #from scripts\\addons import render_freestyle_svg
+if check_render_freestyle_svg():
+ '''
+ snippetsWIP
+ import myscript
+ import importlib
+
+ importlib.reload(myscript)
+ myscript.main()
+ '''
+ for member in dir(render_freestyle_svg):
+ subclass = getattr(render_freestyle_svg, member)
+ try:
+ subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
+ if subclass.bl_idname == "RENDER_PT_SVGExporterPanel":
+ subclass.bl_parent_id = "RENDER_PT_POV_filter"
+ subclass.bl_options = {'HIDE_HEADER'}
+ #subclass.bl_order = 11
+ print(subclass.bl_info)
+ except:
+ pass
+
+ #del render_freestyle_svg.RENDER_PT_SVGExporterPanel.bl_parent_id
+
+
+class RENDER_PT_POV_filter(RenderButtonsPanel, Panel):
+ """Use this class to invoke stuff like Freestyle UI."""
+
+ bl_label = "Freestyle"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ with_freestyle = bpy.app.build_options.freestyle
+ engine = context.scene.render.engine
+ return(with_freestyle and engine == 'POVRAY_RENDER')
+ def draw_header(self, context):
+
+ #scene = context.scene
+ rd = context.scene.render
+ layout = self.layout
+
+ if rd.use_freestyle:
+ layout.prop(
+ rd, "use_freestyle", text="", icon='LINE_DATA'
+ )
+
+ else:
+ layout.prop(
+ rd, "use_freestyle", text="", icon='OUTLINER_OB_IMAGE'
+ )
+
+ def draw(self, context):
+ rd = context.scene.render
+ layout = self.layout
+ layout.active = rd.use_freestyle
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
+ flow = layout.grid_flow(
+ row_major=True,
+ columns=0,
+ even_columns=True,
+ even_rows=False,
+ align=True,
+ )
+
+ flow.prop(rd, "line_thickness_mode", expand=True)
+
+ if rd.line_thickness_mode == 'ABSOLUTE':
+ flow.prop(rd, "line_thickness")
+
+ # Warning if the Freestyle SVG Exporter addon is not enabled
+ if not check_render_freestyle_svg():
+ # col = box.column()
+ layout.label(
+ text="Please enable Freestyle SVG Exporter addon", icon="INFO"
+ )
+ # layout.separator()
+ layout.operator(
+ "preferences.addon_show",
+ text="Go to Render: Freestyle SVG Exporter addon",
+ icon="PREFERENCES",
+ ).module = "render_freestyle_svg"
classes = (
WORLD_PT_POV_world,
WORLD_MT_POV_presets,
WORLD_OT_POV_add_preset,
- WORLD_TEXTURE_SLOTS_UL_List,
+ WORLD_TEXTURE_SLOTS_UL_POV_layerlist,
+ #WORLD_TEXTURE_SLOTS_UL_List,
WORLD_PT_POV_mist,
# RenderButtonsPanel,
# ModifierButtonsPanel,
@@ -4188,6 +4622,7 @@ classes = (
RENDER_PT_POV_photons,
RENDER_PT_POV_antialias,
RENDER_PT_POV_radiosity,
+ RENDER_PT_POV_filter,
POV_RADIOSITY_MT_presets,
RENDER_OT_POV_radiosity_add_preset,
RENDER_PT_POV_media,
@@ -4232,13 +4667,13 @@ classes = (
TEXT_MT_POV_insert,
TEXT_PT_POV_custom_code,
TEXT_MT_POV_templates,
- # TEXTURE_PT_context,
- # TEXTURE_PT_POV_povray_texture_slots,
- TEXTURE_UL_POV_texture_slots,
+ #TEXTURE_PT_POV_povray_texture_slots,
+ #TEXTURE_UL_POV_texture_slots,
MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist,
- MATERIAL_OT_POV_texture_slot_add,
- MATERIAL_OT_POV_texture_slot_remove,
+ TEXTURE_OT_POV_texture_slot_add,
+ TEXTURE_OT_POV_texture_slot_remove,
TEXTURE_PT_POV_influence,
+ TEXTURE_PT_POV_mapping,
)
@@ -4257,11 +4692,18 @@ def register():
# was used for parametric objects but made the other addon unreachable on
# unregister for other tools to use created a user action call instead
# addon_utils.enable("add_mesh_extra_objects", default_set=False, persistent=True)
-
# bpy.types.TEXTURE_PT_context_texture.prepend(TEXTURE_PT_POV_type)
+ if not povCentricWorkspace in bpy.app.handlers.load_post:
+ print("Adding POV wentric workspace on load handlers list")
+ bpy.app.handlers.load_post.append(povCentricWorkspace)
def unregister():
+ if povCentricWorkspace in bpy.app.handlers.load_post:
+ print("Removing POV wentric workspace from load handlers list")
+ bpy.app.handlers.load_post.remove(povCentricWorkspace)
+
+
# from bpy.utils import unregister_class
# bpy.types.TEXTURE_PT_context_texture.remove(TEXTURE_PT_POV_type)
@@ -4274,4 +4716,5 @@ def unregister():
bpy.types.VIEW3D_MT_add.remove(menu_func_add)
for cls in reversed(classes):
- unregister_class(cls)
+ if cls != TEXTURE_PT_context:
+ unregister_class(cls)