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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/blender/addon')
-rw-r--r--intern/cycles/blender/addon/__init__.py19
-rw-r--r--intern/cycles/blender/addon/engine.py59
-rw-r--r--intern/cycles/blender/addon/osl.py2
-rw-r--r--intern/cycles/blender/addon/presets.py2
-rw-r--r--intern/cycles/blender/addon/properties.py112
-rw-r--r--intern/cycles/blender/addon/ui.py237
-rw-r--r--intern/cycles/blender/addon/version_update.py85
7 files changed, 445 insertions, 71 deletions
diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py
index 415f6e81be8..7a9caa7b06b 100644
--- a/intern/cycles/blender/addon/__init__.py
+++ b/intern/cycles/blender/addon/__init__.py
@@ -11,7 +11,7 @@
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
-# limitations under the License
+# limitations under the License.
#
# <pep8 compliant>
@@ -49,26 +49,23 @@ class CyclesRender(bpy.types.RenderEngine):
# final render
def update(self, data, scene):
- if self.is_preview:
- if not self.session:
+ if not self.session:
+ if self.is_preview:
cscene = bpy.context.scene.cycles
use_osl = cscene.shading_system and cscene.device == 'CPU'
engine.create(self, data, scene,
None, None, None, use_osl)
- else:
- if not self.session:
- engine.create(self, data, scene)
else:
- engine.reset(self, data, scene)
-
- engine.update(self, data, scene)
+ engine.create(self, data, scene)
+ else:
+ engine.reset(self, data, scene)
def render(self, scene):
engine.render(self)
- def bake(self, scene, obj, pass_type, pixel_array, num_pixels, depth, result):
- engine.bake(self, obj, pass_type, pixel_array, num_pixels, depth, result)
+ def bake(self, scene, obj, pass_type, object_id, pixel_array, num_pixels, depth, result):
+ engine.bake(self, obj, pass_type, object_id, pixel_array, num_pixels, depth, result)
# viewport render
def view_update(self, context):
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index 18235eca790..030f0dbbf14 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -11,21 +11,67 @@
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
-# limitations under the License
+# limitations under the License.
#
# <pep8 compliant>
+def _is_using_buggy_driver():
+ import bgl
+ # We need to be conservative here because in multi-GPU systems display card
+ # might be quite old, but others one might be just good.
+ #
+ # So We shouldn't disable possible good dedicated cards just because display
+ # card seems weak. And instead we only blacklist configurations which are
+ # proven to cause problems.
+ if bgl.glGetString(bgl.GL_VENDOR) == "ATI Technologies Inc.":
+ import re
+ version = bgl.glGetString(bgl.GL_VERSION)
+ if version.endswith("Compatibility Profile Context"):
+ # Old HD 4xxx and 5xxx series drivers did not have driver version
+ # in the version string, but those cards do not quite work and
+ # causing crashes.
+ return True
+ regex = re.compile(".*Compatibility Profile Context ([0-9]+(\.[0-9]+)+)$")
+ if not regex.match(version):
+ # Skip cards like FireGL
+ return False
+ version = regex.sub("\\1", version).split('.')
+ return int(version[0]) == 8
+ return False
+
+
+def _workaround_buggy_drivers():
+ if _is_using_buggy_driver():
+ import _cycles
+ if hasattr(_cycles, "opencl_disable"):
+ print("Cycles: OpenGL driver known to be buggy, disabling OpenCL platform.")
+ _cycles.opencl_disable()
+
+
def init():
import bpy
import _cycles
import os.path
+ # Workaround possibly buggy legacy drivers which crashes on the OpenCL
+ # device enumeration.
+ #
+ # This checks are not really correct because they might still fail
+ # in the case of multiple GPUs. However, currently buggy drivers
+ # are really old and likely to be used in single GPU systems only
+ # anyway.
+ #
+ # Can't do it in the background mode, so we hope OpenCL is no enabled
+ # in the user preferences.
+ if not bpy.app.background:
+ _workaround_buggy_drivers()
+
path = os.path.dirname(__file__)
user_path = os.path.dirname(os.path.abspath(bpy.utils.user_resource('CONFIG', '')))
- _cycles.init(path, user_path)
+ _cycles.init(path, user_path, bpy.app.background)
def create(engine, data, scene, region=None, v3d=None, rv3d=None, preview_osl=False):
@@ -59,11 +105,11 @@ def render(engine):
_cycles.render(engine.session)
-def bake(engine, obj, pass_type, pixel_array, num_pixels, depth, result):
+def bake(engine, obj, pass_type, object_id, pixel_array, num_pixels, depth, result):
import _cycles
session = getattr(engine, "session", None)
if session is not None:
- _cycles.bake(engine.session, obj.as_pointer(), pass_type, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer())
+ _cycles.bake(engine.session, obj.as_pointer(), pass_type, object_id, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer())
def reset(engine, data, scene):
@@ -100,3 +146,8 @@ def with_osl():
def with_network():
import _cycles
return _cycles.with_network
+
+
+def system_info():
+ import _cycles
+ return _cycles.system_info()
diff --git a/intern/cycles/blender/addon/osl.py b/intern/cycles/blender/addon/osl.py
index c5f9d93013e..f4aaaab5eab 100644
--- a/intern/cycles/blender/addon/osl.py
+++ b/intern/cycles/blender/addon/osl.py
@@ -11,7 +11,7 @@
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
-# limitations under the License
+# limitations under the License.
#
# <pep8 compliant>
diff --git a/intern/cycles/blender/addon/presets.py b/intern/cycles/blender/addon/presets.py
index 2ec65d7183a..f97b51b629d 100644
--- a/intern/cycles/blender/addon/presets.py
+++ b/intern/cycles/blender/addon/presets.py
@@ -11,7 +11,7 @@
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
-# limitations under the License
+# limitations under the License.
#
# <pep8 compliant>
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 12c1cd820be..c130594dbf7 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -11,7 +11,7 @@
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
-# limitations under the License
+# limitations under the License.
#
# <pep8 compliant>
@@ -59,7 +59,7 @@ enum_filter_types = (
enum_aperture_types = (
('RADIUS', "Radius", "Directly change the size of the aperture"),
- ('FSTOP', "F/stop", "Change the size of the aperture by f/stops"),
+ ('FSTOP', "F-stop", "Change the size of the aperture by f-stop"),
)
enum_panorama_types = (
@@ -67,6 +67,7 @@ enum_panorama_types = (
('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions"),
('FISHEYE_EQUISOLID', "Fisheye Equisolid",
"Similar to most fisheye modern lens, takes sensor dimensions into consideration"),
+ ('MIRRORBALL', "Mirror Ball", "Uses the mirror ball mapping"),
)
enum_curve_primitives = (
@@ -115,6 +116,11 @@ enum_volume_sampling = (
('MULTIPLE_IMPORTANCE', "Multiple Importance", "Combine distance and equi-angular sampling for volumes where neither method is ideal"),
)
+enum_volume_interpolation = (
+ ('LINEAR', "Linear", "Good smoothness and speed"),
+ ('CUBIC', "Cubic", "Smoothed high quality interpolation, but slower")
+ )
+
class CyclesRenderSettings(bpy.types.PropertyGroup):
@classmethod
@@ -346,7 +352,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
description="Distance between volume shader samples when rendering the volume "
"(lower values give more accurate and detailed results, but also increased render time)",
default=0.1,
- min=0.0000001, max=100000.0
+ min=0.0000001, max=100000.0, soft_min=0.01, soft_max=1.0
)
cls.volume_max_steps = IntProperty(
@@ -389,6 +395,12 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
default=0,
)
+ cls.use_animated_seed = BoolProperty(
+ name="Use Animated Seed",
+ description="Use different seed values (and hence noise patterns) at different frames",
+ default=False,
+ )
+
cls.sample_clamp_direct = FloatProperty(
name="Clamp Direct",
description="If non-zero, the maximum value for a direct sample, "
@@ -452,11 +464,6 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
description="Use BVH spatial splits: longer builder time, faster render",
default=False,
)
- cls.use_cache = BoolProperty(
- name="Cache BVH",
- description="Cache last built BVH to disk for faster re-render if no geometry changed",
- default=False,
- )
cls.tile_order = EnumProperty(
name="Tile Order",
description="Tile order for rendering",
@@ -477,7 +484,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
name="Bake Type",
default='COMBINED',
description="Type of pass to bake",
- items = (
+ items=(
('COMBINED', "Combined", ""),
('AO', "Ambient Occlusion", ""),
('SHADOW', "Shadow", ""),
@@ -500,6 +507,19 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
),
)
+ cls.use_camera_cull = BoolProperty(
+ name="Use Camera Cull",
+ description="Allow objects to be culled based on the camera frustum",
+ default=False,
+ )
+
+ cls.camera_cull_margin = FloatProperty(
+ name="Camera Cull Margin",
+ description="Margin for the camera space culling",
+ default=0.1,
+ min=0.0, max=5.0
+ )
+
@classmethod
def unregister(cls):
del bpy.types.Scene.cycles
@@ -518,13 +538,13 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
cls.aperture_type = EnumProperty(
name="Aperture Type",
- description="Use F/stop number or aperture radius",
+ description="Use f-stop number or aperture radius",
items=enum_aperture_types,
default='RADIUS',
)
cls.aperture_fstop = FloatProperty(
- name="Aperture F/stop",
- description="F/stop ratio (lower numbers give more defocus, higher numbers give a sharper image)",
+ name="Aperture f-stop",
+ description="F-stop ratio (lower numbers give more defocus, higher numbers give a sharper image)",
min=0.0, soft_min=0.1, soft_max=64.0,
default=5.6,
step=10,
@@ -578,6 +598,34 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
min=0.01, soft_max=15.0, max=100.0,
default=10.5,
)
+ cls.latitude_min = FloatProperty(
+ name="Min Latitude",
+ description="Minimum latitude (vertical angle) for the equirectangular lens",
+ min=-0.5 * math.pi, max=0.5 * math.pi,
+ subtype='ANGLE',
+ default=-0.5 * math.pi,
+ )
+ cls.latitude_max = FloatProperty(
+ name="Max Latitude",
+ description="Maximum latitude (vertical angle) for the equirectangular lens",
+ min=-0.5 * math.pi, max=0.5 * math.pi,
+ subtype='ANGLE',
+ default=0.5 * math.pi,
+ )
+ cls.longitude_min = FloatProperty(
+ name="Min Longitude",
+ description="Minimum longitude (horizontal angle) for the equirectangular lens",
+ min=-math.pi, max=math.pi,
+ subtype='ANGLE',
+ default=-math.pi,
+ )
+ cls.longitude_max = FloatProperty(
+ name="Max Longitude",
+ description="Maximum longitude (horizontal angle) for the equirectangular lens",
+ min=-math.pi, max=math.pi,
+ subtype='ANGLE',
+ default=math.pi,
+ )
cls.nodes = StringProperty(
name="nodes",
description="Camera ray nodes")
@@ -621,6 +669,13 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup):
default='DISTANCE',
)
+ cls.volume_interpolation = EnumProperty(
+ name="Volume Interpolation",
+ description="Interpolation method to use for smoke/fire volumes",
+ items=enum_volume_interpolation,
+ default='LINEAR',
+ )
+
@classmethod
def unregister(cls):
del bpy.types.Material.cycles
@@ -645,12 +700,24 @@ class CyclesLampSettings(bpy.types.PropertyGroup):
min=1, max=10000,
default=1,
)
+ cls.max_bounces = IntProperty(
+ name="Max Bounces",
+ description="Maximum number of bounces the light will contribute to the render",
+ min=0, max=1024,
+ default=1024,
+ )
cls.use_multiple_importance_sampling = BoolProperty(
name="Multiple Importance Sample",
description="Use multiple importance sampling for the lamp, "
"reduces noise for area lamps and sharp glossy materials",
default=False,
)
+ cls.is_portal = BoolProperty(
+ name="Is Portal",
+ description="Use this area lamp to guide sampling of the background, "
+ "note that this will make the lamp invisible",
+ default=False,
+ )
@classmethod
def unregister(cls):
@@ -675,7 +742,7 @@ class CyclesWorldSettings(bpy.types.PropertyGroup):
name="Map Resolution",
description="Importance map size is resolution x resolution; "
"higher values potentially produce less noise, at the cost of memory and speed",
- min=4, max=8096,
+ min=4, max=8192,
default=256,
)
cls.samples = IntProperty(
@@ -684,6 +751,12 @@ class CyclesWorldSettings(bpy.types.PropertyGroup):
min=1, max=10000,
default=4,
)
+ cls.max_bounces = IntProperty(
+ name="Max Bounces",
+ description="Maximum number of bounces the background light will contribute to the render",
+ min=0, max=1024,
+ default=1024,
+ )
cls.homogeneous_volume = BoolProperty(
name="Homogeneous Volume",
description="When using volume rendering, assume volume has the same density everywhere"
@@ -697,6 +770,13 @@ class CyclesWorldSettings(bpy.types.PropertyGroup):
default='EQUIANGULAR',
)
+ cls.volume_interpolation = EnumProperty(
+ name="Volume Interpolation",
+ description="Interpolation method to use for volumes",
+ items=enum_volume_interpolation,
+ default='LINEAR',
+ )
+
@classmethod
def unregister(cls):
del bpy.types.World.cycles
@@ -828,6 +908,12 @@ class CyclesObjectBlurSettings(bpy.types.PropertyGroup):
default=1,
)
+ cls.use_camera_cull = BoolProperty(
+ name="Use Camera Cull",
+ description="Allow this object and its duplicators to be culled by camera space culling",
+ default=False,
+ )
+
@classmethod
def unregister(cls):
del bpy.types.Object.cycles
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index b544c476c11..a44a0b46960 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -11,14 +11,18 @@
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
-# limitations under the License
+# limitations under the License.
#
# <pep8 compliant>
import bpy
-from bpy.types import Panel, Menu, Operator
+from bpy.types import (
+ Panel,
+ Menu,
+ Operator,
+ )
class CYCLES_MT_sampling_presets(Menu):
@@ -37,7 +41,7 @@ class CYCLES_MT_integrator_presets(Menu):
draw = Menu.draw_preset
-class CyclesButtonsPanel():
+class CyclesButtonsPanel:
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
@@ -56,7 +60,15 @@ def use_cpu(context):
return (device_type == 'NONE' or cscene.device == 'CPU')
-def draw_samples_info(layout, cscene):
+def use_branched_path(context):
+ cscene = context.scene.cycles
+ device_type = context.user_preferences.system.compute_device_type
+
+ return (cscene.progressive == 'BRANCHED_PATH' and device_type != 'OPENCL')
+
+
+def draw_samples_info(layout, context):
+ cscene = context.scene.cycles
integrator = cscene.progressive
# Calculate sample values
@@ -86,7 +98,7 @@ def draw_samples_info(layout, cscene):
# Draw interface
# Do not draw for progressive, when Square Samples are disabled
- if (integrator == 'BRANCHED_PATH') or (cscene.use_square_samples and integrator == 'PATH'):
+ if use_branched_path(context) or (cscene.use_square_samples and integrator == 'PATH'):
col = layout.column(align=True)
col.scale_y = 0.6
col.label("Total Samples:")
@@ -110,6 +122,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
scene = context.scene
cscene = scene.cycles
+ device_type = context.user_preferences.system.compute_device_type
row = layout.row(align=True)
row.menu("CYCLES_MT_sampling_presets", text=bpy.types.CYCLES_MT_sampling_presets.bl_label)
@@ -117,7 +130,9 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
row.operator("render.cycles_sampling_preset_add", text="", icon="ZOOMOUT").remove_active = True
row = layout.row()
- row.prop(cscene, "progressive", text="")
+ sub = row.row()
+ sub.active = device_type != 'OPENCL'
+ sub.prop(cscene, "progressive", text="")
row.prop(cscene, "use_square_samples")
split = layout.split()
@@ -125,11 +140,15 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
col = split.column()
sub = col.column(align=True)
sub.label("Settings:")
- sub.prop(cscene, "seed")
+
+ seed_sub = sub.row(align=True)
+ seed_sub.prop(cscene, "seed")
+ seed_sub.prop(cscene, "use_animated_seed", text="", icon="TIME")
+
sub.prop(cscene, "sample_clamp_direct")
sub.prop(cscene, "sample_clamp_indirect")
- if cscene.progressive == 'PATH':
+ if cscene.progressive == 'PATH' or use_branched_path(context) == False:
col = split.column()
sub = col.column(align=True)
sub.label(text="Samples:")
@@ -163,7 +182,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
layout.row().prop(cscene, "use_layer_samples")
break
- draw_samples_info(layout, cscene)
+ draw_samples_info(layout, context)
class CyclesRender_PT_volume_sampling(CyclesButtonsPanel, Panel):
@@ -313,7 +332,6 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
col.separator()
col.label(text="Final Render:")
- col.prop(cscene, "use_cache")
col.prop(rd, "use_persistent_data", text="Persistent Images")
col.separator()
@@ -412,6 +430,52 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
col.prop(rl, "use_pass_emit", text="Emission")
col.prop(rl, "use_pass_environment")
+ if hasattr(rd, "debug_pass_type"):
+ layout.prop(rd, "debug_pass_type")
+
+
+class CyclesRender_PT_views(CyclesButtonsPanel, Panel):
+ bl_label = "Views"
+ bl_context = "render_layer"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw_header(self, context):
+ rd = context.scene.render
+ self.layout.prop(rd, "use_multiview", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+ rd = scene.render
+ rv = rd.views.active
+
+ layout.active = rd.use_multiview
+ basic_stereo = (rd.views_format == 'STEREO_3D')
+
+ row = layout.row()
+ row.prop(rd, "views_format", expand=True)
+
+ if basic_stereo:
+ row = layout.row()
+ row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "stereo_views", rd.views, "active_index", rows=2)
+
+ row = layout.row()
+ row.label(text="File Suffix:")
+ row.prop(rv, "file_suffix", text="")
+
+ else:
+ row = layout.row()
+ row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2)
+
+ col = row.column(align=True)
+ col.operator("scene.render_view_add", icon='ZOOMIN', text="")
+ col.operator("scene.render_view_remove", icon='ZOOMOUT', text="")
+
+ row = layout.row()
+ row.label(text="Camera Suffix:")
+ row.prop(rv, "camera_suffix", text="")
+
class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
bl_label = "Post Processing"
@@ -445,6 +509,7 @@ class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
cam = context.camera
ccam = cam.cycles
+ dof_options = cam.gpu_dof
split = layout.split()
@@ -456,6 +521,16 @@ class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
sub.active = cam.dof_object is None
sub.prop(cam, "dof_distance", text="Distance")
+ hq_support = dof_options.is_hq_supported
+ sub = col.column(align=True)
+ sub.label("Viewport:")
+ subhq = sub.column()
+ subhq.active = hq_support
+ subhq.prop(dof_options, "use_high_quality")
+ sub.prop(dof_options, "fstop")
+ if dof_options.use_high_quality and hq_support:
+ sub.prop(dof_options, "blades")
+
col = split.column()
col.label("Aperture:")
@@ -506,11 +581,16 @@ class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
ob = context.object
slot = context.material_slot
space = context.space_data
+ is_sortable = len(ob.material_slots) > 1
if ob:
+ rows = 1
+ if (is_sortable):
+ rows = 4
+
row = layout.row()
- row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=1)
+ row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows)
col = row.column(align=True)
col.operator("object.material_slot_add", icon='ZOOMIN', text="")
@@ -518,6 +598,12 @@ class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
+ if is_sortable:
+ col.separator()
+
+ col.operator("object.material_slot_move", icon='TRIA_UP', text="").direction = 'UP'
+ col.operator("object.material_slot_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
+
if ob.mode == 'EDIT':
row = layout.row(align=True)
row.operator("object.material_slot_assign", text="Assign")
@@ -579,7 +665,13 @@ class CyclesObject_PT_motion_blur(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
ob = context.object
- return CyclesButtonsPanel.poll(context) and ob and ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META'}
+ if CyclesButtonsPanel.poll(context) and ob:
+ if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META'}:
+ return True
+ if ob.dupli_type == 'GROUP' and ob.dupli_group:
+ return True
+ # TODO(sergey): More duplicator types here?
+ return False
def draw_header(self, context):
layout = self.layout
@@ -613,8 +705,8 @@ class CyclesObject_PT_motion_blur(CyclesButtonsPanel, Panel):
sub.prop(cob, "motion_steps", text="Steps")
-class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
- bl_label = "Ray Visibility"
+class CyclesObject_PT_cycles_settings(CyclesButtonsPanel, Panel):
+ bl_label = "Cycles Settings"
bl_context = "object"
bl_options = {'DEFAULT_CLOSED'}
@@ -622,15 +714,19 @@ class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
def poll(cls, context):
ob = context.object
return (CyclesButtonsPanel.poll(context) and
- ob and ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LAMP'} or
- ob and ob.dupli_type == 'GROUP' and ob.dupli_group)
+ ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LAMP'}) or
+ (ob.dupli_type == 'GROUP' and ob.dupli_group)))
def draw(self, context):
layout = self.layout
+ scene = context.scene
+ cscene = scene.cycles
ob = context.object
+ cob = ob.cycles
visibility = ob.cycles_visibility
+ layout.label(text="Ray Visibility:")
flow = layout.column_flow()
flow.prop(visibility, "camera")
@@ -642,6 +738,12 @@ class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
if ob.type != 'LAMP':
flow.prop(visibility, "shadow")
+ col = layout.column()
+ col.label(text="Performance:")
+ row = col.row()
+ row.active = scene.render.use_simplify and cscene.use_camera_cull
+ row.prop(cob, "use_camera_cull")
+
class CYCLES_OT_use_shading_nodes(Operator):
"""Enable nodes on a material, world or lamp"""
@@ -668,9 +770,14 @@ def find_node(material, nodetype):
if material and material.node_tree:
ntree = material.node_tree
+ active_output_node = None
for node in ntree.nodes:
if getattr(node, "type", None) == nodetype:
- return node
+ if getattr(node, "is_active_output", True):
+ return node
+ if not active_output_node:
+ active_output_node = node
+ return active_output_node
return None
@@ -707,7 +814,10 @@ class CyclesLamp_PT_preview(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
- return context.lamp and CyclesButtonsPanel.poll(context)
+ return context.lamp and \
+ not (context.lamp.type == 'AREA' and
+ context.lamp.cycles.is_portal) \
+ and CyclesButtonsPanel.poll(context)
def draw(self, context):
self.layout.template_preview(context.lamp)
@@ -745,13 +855,21 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
sub.prop(lamp, "size", text="Size X")
sub.prop(lamp, "size_y", text="Size Y")
- if cscene.progressive == 'BRANCHED_PATH':
- col.prop(clamp, "samples")
+ if not (lamp.type == 'AREA' and clamp.is_portal):
+ sub = col.column(align=True)
+ if use_branched_path(context):
+ sub.prop(clamp, "samples")
+ sub.prop(clamp, "max_bounces")
col = split.column()
- col.prop(clamp, "cast_shadow")
- layout.prop(clamp, "use_multiple_importance_sampling")
+ sub = col.column(align=True)
+ sub.active = not (lamp.type == 'AREA' and clamp.is_portal)
+ sub.prop(clamp, "cast_shadow")
+ sub.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance")
+
+ if lamp.type == 'AREA':
+ col.prop(clamp, "is_portal", text="Portal")
if lamp.type == 'HEMI':
layout.label(text="Not supported, interpreted as sun lamp")
@@ -763,7 +881,9 @@ class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
- return context.lamp and CyclesButtonsPanel.poll(context)
+ return context.lamp and not (context.lamp.type == 'AREA' and
+ context.lamp.cycles.is_portal) and \
+ CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
@@ -946,14 +1066,16 @@ class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
sub = col.column(align=True)
sub.active = cworld.sample_as_light
sub.prop(cworld, "sample_map_resolution")
- if cscene.progressive == 'BRANCHED_PATH':
+ if use_branched_path(context):
sub.prop(cworld, "samples")
+ sub.prop(cworld, "max_bounces")
col = split.column()
col.label(text="Volume:")
sub = col.column()
sub.active = use_cpu(context)
sub.prop(cworld, "volume_sampling", text="")
+ sub.prop(cworld, "volume_interpolation", text="")
col.prop(cworld, "homogeneous_volume", text="Homogeneous")
@@ -1037,17 +1159,6 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
cmat = mat.cycles
split = layout.split()
-
- col = split.column(align=True)
- col.prop(mat, "diffuse_color", text="Viewport Color")
- col.prop(mat, "alpha")
-
- col = split.column(align=True)
- col.label()
- col.prop(mat, "pass_index")
-
- split = layout.split()
-
col = split.column()
col.label(text="Surface:")
col.prop(cmat, "sample_as_light", text="Multiple Importance")
@@ -1058,8 +1169,29 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
sub = col.column()
sub.active = use_cpu(context)
sub.prop(cmat, "volume_sampling", text="")
+ sub.prop(cmat, "volume_interpolation", text="")
col.prop(cmat, "homogeneous_volume", text="Homogeneous")
+ layout.separator()
+ split = layout.split()
+
+ col = split.column(align=True)
+ col.label("Viewport Color:")
+ col.prop(mat, "diffuse_color", text="")
+ col.prop(mat, "alpha")
+
+ col.separator()
+ col.label("Viewport Alpha:")
+ col.prop(mat.game_settings, "alpha_blend", text="")
+
+ col = split.column(align=True)
+ col.label("Viewport Specular:")
+ col.prop(mat, "specular_color", text="")
+ col.prop(mat, "specular_hardness", text="Hardness")
+
+ col.separator()
+ col.prop(mat, "pass_index")
+
class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
bl_label = ""
@@ -1126,7 +1258,8 @@ class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
node = context.texture_node
- return node and CyclesButtonsPanel.poll(context)
+ # TODO(sergey): perform a faster/nicer check?
+ return node and hasattr(node, 'texture_mapping') and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
@@ -1350,13 +1483,28 @@ class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
- rd = context.scene.render
+ scene = context.scene
+ rd = scene.render
+ cscene = scene.cycles
layout.active = rd.use_simplify
+ split = layout.split()
- row = layout.row()
- row.prop(rd, "simplify_subdivision", text="Subdivision")
- row.prop(rd, "simplify_child_particles", text="Child Particles")
+ col = split.column()
+ col.label(text="Viewport:")
+ col.prop(rd, "simplify_subdivision", text="Subdivision")
+ col.prop(rd, "simplify_child_particles", text="Child Particles")
+
+ col = split.column()
+ col.label(text="Render:")
+ col.prop(rd, "simplify_subdivision_render", text="Subdivision")
+ col.prop(rd, "simplify_child_particles_render", text="Child Particles")
+
+ col = layout.column()
+ col.prop(cscene, "use_camera_cull")
+ subsub = col.column()
+ subsub.active = cscene.use_camera_cull
+ subsub.prop(cscene, "camera_cull_margin")
def draw_device(self, context):
@@ -1399,7 +1547,11 @@ def get_panels():
"RENDER_PT_encoding",
"RENDER_PT_dimensions",
"RENDER_PT_stamp",
+ "RENDER_PT_freestyle",
"RENDERLAYER_PT_layers",
+ "RENDERLAYER_PT_freestyle",
+ "RENDERLAYER_PT_freestyle_lineset",
+ "RENDERLAYER_PT_freestyle_linestyle",
"SCENE_PT_scene",
"SCENE_PT_color_management",
"SCENE_PT_custom_props",
@@ -1424,6 +1576,8 @@ def get_panels():
"DATA_PT_vertex_colors",
"DATA_PT_camera",
"DATA_PT_camera_display",
+ "DATA_PT_camera_stereoscopy",
+ "DATA_PT_camera_safe_areas",
"DATA_PT_lens",
"DATA_PT_speaker",
"DATA_PT_distance",
@@ -1437,6 +1591,7 @@ def get_panels():
"DATA_PT_custom_props_curve",
"DATA_PT_custom_props_lattice",
"DATA_PT_custom_props_metaball",
+ "TEXTURE_PT_preview",
"TEXTURE_PT_custom_props",
"TEXTURE_PT_clouds",
"TEXTURE_PT_wood",
@@ -1454,6 +1609,7 @@ def get_panels():
"TEXTURE_PT_pointdensity",
"TEXTURE_PT_pointdensity_turbulence",
"TEXTURE_PT_mapping",
+ "TEXTURE_PT_ocean",
"TEXTURE_PT_influence",
"TEXTURE_PT_colors",
"PARTICLE_PT_context_particles",
@@ -1475,6 +1631,7 @@ def get_panels():
"PARTICLE_PT_force_fields",
"PARTICLE_PT_vertexgroups",
"MATERIAL_PT_custom_props",
+ "MATERIAL_PT_freestyle_line",
"BONE_PT_custom_props",
"OBJECT_PT_custom_props",
]
diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py
index eaeec703ff5..2fbb01ba5b8 100644
--- a/intern/cycles/blender/addon/version_update.py
+++ b/intern/cycles/blender/addon/version_update.py
@@ -11,7 +11,7 @@
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
-# limitations under the License
+# limitations under the License.
#
# <pep8 compliant>
@@ -21,6 +21,85 @@ import bpy
from bpy.app.handlers import persistent
+def check_is_new_shading_ntree(node_tree):
+ for node in node_tree.nodes:
+ # If material has any node with ONLY new shading system
+ # compatibility then it's considered a Cycles material
+ # and versioning code would need to perform on it.
+ #
+ # We can not check for whether NEW_SHADING in compatibility
+ # because some nodes could have compatibility with both old
+ # and new shading system and they can't be used for any
+ # decision here.
+ if node.shading_compatibility == {'NEW_SHADING'}:
+ return True
+
+ # If node is only compatible with old shading system
+ # then material can not be Cycles material and we
+ # can stopiterating nodes now.
+ if node.shading_compatibility == {'OLD_SHADING'}:
+ return False
+ return False
+
+
+def check_is_new_shading_material(material):
+ if not material.node_tree:
+ return False
+ return check_is_new_shading_ntree(material.node_tree)
+
+
+def check_is_new_shading_world(world):
+ if not world.node_tree:
+ return False
+ return check_is_new_shading_ntree(world.node_tree)
+
+
+def check_is_new_shading_lamp(lamp):
+ if not lamp.node_tree:
+ return False
+ return check_is_new_shading_ntree(lamp.node_tree)
+
+
+def foreach_notree_node(nodetree, callback, traversed):
+ if nodetree in traversed:
+ return
+ traversed.add(nodetree)
+ for node in nodetree.nodes:
+ callback(node)
+ if node.bl_idname == 'ShaderNodeGroup':
+ foreach_notree_node(node.node_tree, callback, traversed)
+
+
+def foreach_cycles_node(callback):
+ traversed = set()
+ for material in bpy.data.materials:
+ if check_is_new_shading_material(material):
+ foreach_notree_node(material.node_tree,
+ callback,
+ traversed)
+ for world in bpy.data.worlds:
+ if check_is_new_shading_world(world):
+ foreach_notree_node(world.node_tree,
+ callback,
+ traversed)
+ for lamp in bpy.data.lamps:
+ if check_is_new_shading_world(lamp):
+ foreach_notree_node(lamp.node_tree,
+ callback,
+ traversed)
+
+
+def mapping_node_order_flip(node):
+ """
+ Flip euler order of mapping shader node
+ """
+ if node.bl_idname == 'ShaderNodeMapping':
+ rot = node.rotation.copy()
+ rot.order = 'ZYX'
+ quat = rot.to_quaternion()
+ node.rotation = quat.to_euler('XYZ')
+
+
@persistent
def do_versions(self):
# We don't modify startup file because it assumes to
@@ -57,3 +136,7 @@ def do_versions(self):
cscene.caustics_reflective = False
cscene.caustics_refractive = False
+
+ # Euler order was ZYX in previous versions.
+ if bpy.data.version <= (2, 73, 4):
+ foreach_cycles_node(mapping_node_order_flip)