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:
authorMaurice Raybaud <mauriceraybaud@hotmail.fr>2020-08-02 01:07:39 +0300
committerMaurice Raybaud <mauriceraybaud@hotmail.fr>2020-08-02 01:07:39 +0300
commite44e5845ee2b9e8de3b06d5678f60eb0ea09bc4f (patch)
treebc80272aebedd622f523addb9953c3f92fcf80fe
parent120f9d548a92c583b656775068df2d7b20f5a5ef (diff)
fix: Texture slots for world and materials
fix: Orthographic and perspective camera view angle thanks to Iari Marino add: some numpy functions to export mesh possibly faster in next version fix: parametric surfaces much accelerated and now actually usable (max gradient defaults were wrong from the time of their implementation in most pov literature. Thanks to William F. Pokorny for finding this out! add: very basic "blurry reflection" hack for when using plain official POV add: push of (as of yet badly formatted) feedback to interactive console add: POV centric workspace, default when addon is left activated from previous session. add: Sound signal support on finished render (set from addon preferences) add: support for pov 3.8 and decremented in a few areas, waiting for the release add: freestyle interface with convoluted workflow currently but preparing for next release. fix: commented out Charset feature because POV 3.8 auto detects encoding fix: a few dot notation look ups aliased and removed fix: restored some more removed properties from 2.79 ( a few remain to do) fix: texture mapped specular max value increased fix: faster defaults for radiosity fix: many default texture influences switched to 1 because boolean enabling is required anyway so 0 was a bad default fix: some icons were missing since 2.8 fix: some formatting improvement was started
-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.py753
6 files changed, 1303 insertions, 402 deletions
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..9ac79067 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,139 @@ 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
+
+#Use some delay?
+#https://blenderartists.org/t/restrictdata-object-has-no-attribute-scenes-how-to-avoid-it/579885/4
+############# POV-Centric WORSPACE #############
+@persistent
+def povCentricWorkspace(dummy):
+ """Set up a POV centric Workspace if addon was left activate from previous session
+
+ 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.
+ """
+
+ #bpy.context.scene.render.engine = 'POVRAY_RENDER'
+ wsp = bpy.data.workspaces.get('Scripting')
+ context = bpy.context
+ if wsp is not None:
+ 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')
+ #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 +398,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 +460,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 +518,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 +831,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 +1257,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 +1273,7 @@ class RENDER_PT_POV_export_settings(RenderButtonsPanel, Panel):
)
def draw(self, context):
+
layout = self.layout
scene = context.scene
@@ -1143,25 +1286,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 +1557,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 +1705,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 +2015,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 +2321,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 +2334,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 +2369,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 +2398,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 +2457,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 +2474,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 +2495,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 +2728,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 +2738,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 +2770,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 +2816,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 +2861,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 +3142,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 +3256,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 +3279,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 +4094,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 +4115,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 +4197,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 +4248,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 +4394,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 +4454,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 +4471,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 +4492,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 +4625,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 +4670,14 @@ 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_context,
+ #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 +4696,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 +4720,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)