Newer
Older
# SPDX-License-Identifier: GPL-2.0-or-later
"""User interface for texturing tools."""
import bpy
from bpy.utils import register_class, unregister_class
from bpy.types import (
Operator,
Menu,
UIList,
Panel,
Brush,
Material,
Light,
World,
ParticleSettings,
FreestyleLineStyle,
)
# from .ui import TextureButtonsPanel
from .shading_properties import pov_context_tex_datablock
from bl_ui.properties_paint_common import brush_texture_settings
# Example of wrapping every class 'as is'
from bl_ui import properties_texture
# unused, replaced by pov_context_tex_datablock (no way to use?):
# from bl_ui.properties_texture import context_tex_datablock
# from bl_ui.properties_texture import texture_filter_common #unused yet?
for member in dir(properties_texture):
subclass = getattr(properties_texture, member)
subclass.COMPAT_ENGINES.add("POVRAY_RENDER")
del properties_texture
class TextureButtonsPanel:
"""Use this class to define buttons from the texture tab properties."""
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
COMPAT_ENGINES = {"POVRAY_RENDER"}
@classmethod
def poll(cls, context):
tex = context.texture
rd = context.scene.render
return tex and (rd.engine in cls.COMPAT_ENGINES)
class TEXTURE_MT_POV_specials(Menu):
"""Use this class to define pov texture slot operations buttons."""
bl_label = "Texture Specials"
COMPAT_ENGINES = {"POVRAY_RENDER"}
def draw(self, context):
layout = self.layout
layout.operator("texture.slot_copy", icon="COPYDOWN")
layout.operator("texture.slot_paste", icon="PASTEDOWN")
class WORLD_TEXTURE_SLOTS_UL_POV_layerlist(UIList):
"""Use this class to show pov texture slots list."""
index: bpy.props.IntProperty(name="index")
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
# world = context.scene.world # .pov # NOT USED
# active_data = world.pov # NOT USED
# 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
# draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
if self.layout_type in {"DEFAULT", "COMPACT"}:
# You should always start your row layout by a label (icon + text), or a non-embossed text field,
# this will also make the row easily selectable in the list! The later also enables ctrl-click rename.
# We use icon_value of label, as our given icon is an integer value, not an enum ID.
# Note "data" names should never be translated!
if slot:
layout.prop(slot, "texture", text="", emboss=False, icon="TEXTURE")
else:
layout.label(text="New", translate=False, icon_value=icon)
# 'GRID' layout type should be as compact as possible (typically a single icon!).
elif self.layout_type in {"GRID"}:
layout.alignment = "CENTER"
layout.label(text="", icon_value=icon)
class MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist(UIList):
"""Use this class to show pov texture slots list."""
# texture_slots:
index: bpy.props.IntProperty(name="index")
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
# ob = data
slot = item
# ma = slot.name
# draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
if self.layout_type in {"DEFAULT", "COMPACT"}:
# You should always start your row layout by a label (icon + text), or a non-embossed text field,
# this will also make the row easily selectable in the list! The later also enables ctrl-click rename.
# We use icon_value of label, as our given icon is an integer value, not an enum ID.
# Note "data" names should never be translated!
if slot:
layout.prop(slot, "texture", text="", emboss=False, icon="TEXTURE")
else:
layout.label(text="New", translate=False, icon_value=icon)
# 'GRID' layout type should be as compact as possible (typically a single icon!).
elif self.layout_type in {"GRID"}:
layout.alignment = "CENTER"
layout.label(text="", icon_value=icon)
class TEXTURE_PT_context(TextureButtonsPanel, Panel):
"""Rewrite of this existing class to modify it."""
bl_label = ""
bl_context = "texture"
bl_options = {"HIDE_HEADER"}
COMPAT_ENGINES = {"POVRAY_RENDER", "BLENDER_EEVEE", "BLENDER_WORKBENCH"}
# register but not unregistered because
# the modified parts concern only POVRAY_RENDER
@classmethod
def poll(cls, context):
return (
context.scene.texture_context
not in ("MATERIAL", "WORLD", "LIGHT", "PARTICLES", "LINESTYLE")
or context.scene.render.engine != "POVRAY_RENDER"
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
)
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."""
bl_label = ""
bl_options = {"HIDE_HEADER"}
COMPAT_ENGINES = {"POVRAY_RENDER"}
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
# if not (hasattr(context, "pov_texture_slot") or hasattr(context, "texture_node")):
# return False
return (
context.material
or context.scene.world
or context.light
or context.texture
or context.line_style
or context.particle_system
or isinstance(context.space_data.pin_id, ParticleSettings)
or context.texture_user
) and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
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" and mat is not None:
row = layout.row()
row.template_list(
"MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist",
"",
mat,
"pov_texture_slots",
mat.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="")
# XXX 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]
try:
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")
except KeyError:
tex = None
row = layout.row(align=True)
row.prop_search(
slot, "texture_search", bpy.data, "textures", text="", icon="TEXTURE"
row.operator("pov.textureslotupdate", icon="FILE_REFRESH", text="")
# 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 # NOT USED
# 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="")
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
class TEXTURE_OT_POV_context_texture_update(Operator):
"""Use this class for the texture slot update button."""
bl_idname = "pov.textureslotupdate"
bl_label = "Update"
bl_description = "Update texture_slot"
bl_options = {"REGISTER", "UNDO"}
COMPAT_ENGINES = {"POVRAY_RENDER"}
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
mate = context.view_layer.objects.active.active_material
return mate and engine in cls.COMPAT_ENGINES
def execute(self, context):
# tex.use_fake_user = True
mat = context.view_layer.objects.active.active_material
index = mat.pov.active_texture_index
slot = mat.pov_texture_slots[index]
povtex = slot.texture # slot.name
tex = bpy.data.textures[povtex]
# Switch paint brush and paint brush mask
# to this texture so settings remain contextual
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
]
return {"FINISHED"}
# Commented out below is a reminder of what existed in Blender Internal
# attributes need to be recreated
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
slot = getattr(context, "texture_slot", None)
node = getattr(context, "texture_node", None)
space = context.space_data
#attempt at replacing removed space_data
mtl = getattr(context, "material", None)
if mtl != None:
spacedependant = mtl
wld = getattr(context, "world", None)
if wld != None:
spacedependant = wld
lgt = getattr(context, "light", None)
if lgt != None:
spacedependant = lgt
#idblock = context.particle_system.settings
tex = getattr(context, "texture", None)
if tex != None:
spacedependant = tex
scene = context.scene
idblock = scene.pov#pov_context_tex_datablock(context)
pin_id = space.pin_id
#spacedependant.use_limited_texture_context = True
if space.use_pin_id and not isinstance(pin_id, Texture):
idblock = id_tex_datablock(pin_id)
pin_id = None
if not space.use_pin_id:
layout.row().prop(spacedependant, "texture_context", expand=True)
pin_id = None
if spacedependant.texture_context == 'OTHER':
if not pin_id:
layout.template_texture_user()
user = context.texture_user
if user or pin_id:
layout.separator()
row = layout.row()
if pin_id:
row.template_ID(space, "pin_id")
else:
propname = context.texture_user_property.identifier
row.template_ID(user, propname, new="texture.new")
if tex:
split = layout.split(factor=0.2)
if tex.use_nodes:
if slot:
split.label(text="Output:")
split.prop(slot, "output_node", text="")
else:
split.label(text="Type:")
split.prop(tex, "type", text="")
return
tex_collection = (pin_id is None) and (node is None) and (spacedependant.texture_context not in ('LINESTYLE','OTHER'))
if tex_collection:
pov = getattr(context, "pov", None)
active_texture_index = getattr(spacedependant, "active_texture_index", None)
print (pov)
print(idblock)
print(active_texture_index)
row = layout.row()
row.template_list("TEXTURE_UL_texslots", "", idblock, "texture_slots",
idblock, "active_texture_index", rows=2, maxrows=16, type="DEFAULT")
# row.template_list("WORLD_TEXTURE_SLOTS_UL_List", "texture_slots", world,
# world.texture_slots, world, "active_texture_index", rows=2)
col = row.column(align=True)
col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
col.menu("TEXTURE_MT_POV_specials", icon='DOWNARROW_HLT', text="")
if tex_collection:
layout.template_ID(idblock, "active_texture", new="texture.new")
elif node:
layout.template_ID(node, "texture", new="texture.new")
elif idblock:
layout.template_ID(idblock, "texture", new="texture.new")
if pin_id:
layout.template_ID(space, "pin_id")
if tex:
split = layout.split(factor=0.2)
if tex.use_nodes:
if slot:
split.label(text="Output:")
split.prop(slot, "output_node", text="")
else:
split.label(text="Type:")
class TEXTURE_PT_colors(TextureButtonsPanel, Panel):
"""Use this class to show pov color ramps."""
bl_label = "Colors"
bl_options = {"DEFAULT_CLOSED"}
COMPAT_ENGINES = {"POVRAY_RENDER"}
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
def draw(self, context):
layout = self.layout
tex = context.texture
layout.prop(tex, "use_color_ramp", text="Ramp")
if tex.use_color_ramp:
layout.template_color_ramp(tex, "color_ramp", expand=True)
split = layout.split()
col = split.column()
col.label(text="RGB Multiply:")
sub = col.column(align=True)
sub.prop(tex, "factor_red", text="R")
sub.prop(tex, "factor_green", text="G")
sub.prop(tex, "factor_blue", text="B")
col = split.column()
col.label(text="Adjust:")
col.prop(tex, "intensity")
col.prop(tex, "contrast")
col.prop(tex, "saturation")
col = layout.column()
col.prop(tex, "use_clamp", text="Clamp")
# Texture Slot Panels #
class TEXTURE_OT_POV_texture_slot_add(Operator):
"""Use this class for the add texture slot button."""
bl_idname = "pov.textureslotadd"
bl_label = "Add"
bl_description = "Add texture_slot"
bl_options = {"REGISTER", "UNDO"}
COMPAT_ENGINES = {"POVRAY_RENDER"}
def execute(self, context):
idblock = pov_context_tex_datablock(context)
slot_brush = bpy.data.brushes.new("POVtextureSlot")
context.tool_settings.image_paint.brush = slot_brush
tex = bpy.data.textures.new(name="Texture", type="IMAGE")
# 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 TEXTURE_OT_POV_texture_slot_remove(Operator):
"""Use this class for the remove texture slot button."""
bl_idname = "pov.textureslotremove"
bl_label = "Remove"
bl_description = "Remove texture_slot"
bl_options = {"REGISTER", "UNDO"}
COMPAT_ENGINES = {"POVRAY_RENDER"}
def execute(self, context):
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) # not used
# tex_to_delete = context.tool_settings.image_paint.brush.texture
# bpy.data.textures.remove(tex_to_delete, do_unlink=True, do_id_user=True, do_ui_user=True)
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:
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."""
COMPAT_ENGINES = {"POVRAY_RENDER"}
@classmethod
def poll(cls, context):
if not hasattr(context, "pov_texture_slot"):
return False
engine = context.scene.render.engine
# return TextureButtonsPanel.poll(cls, context) and (engine in cls.COMPAT_ENGINES)
return TextureButtonsPanel.poll(context) and (engine in cls.COMPAT_ENGINES)
class TEXTURE_PT_POV_type(TextureButtonsPanel, Panel):
"""Use this class to define pov texture type buttons."""
bl_label = "POV Textures"
COMPAT_ENGINES = {"POVRAY_RENDER"}
bl_options = {"HIDE_HEADER"}
def draw(self, context):
layout = self.layout
# world = context.world # unused
tex = context.texture
split = layout.split(factor=0.2)
split.label(text="Pattern")
split.prop(tex.pov, "tex_pattern_type", text="")
# row = layout.row()
# row.template_list("WORLD_TEXTURE_SLOTS_UL_List", "texture_slots", world,
# world.texture_slots, world, "active_texture_index")
class TEXTURE_PT_POV_preview(TextureButtonsPanel, Panel):
"""Use this class to define pov texture preview panel."""
bl_label = "Preview"
COMPAT_ENGINES = {"POVRAY_RENDER"}
bl_options = {"HIDE_HEADER"}
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
if not hasattr(context, "pov_texture_slot"):
return False
tex = context.texture
# mat = bpy.context.active_object.active_material #unused
return tex and (tex.pov.tex_pattern_type != "emulator") and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
tex = context.texture
slot = getattr(context, "pov_texture_slot", None)
# idblock = pov_context_tex_datablock(context) # unused
layout = self.layout
# if idblock:
# layout.template_preview(tex, parent=idblock, slot=slot)
if tex.pov.tex_pattern_type != "emulator":
layout.operator("tex.preview_update")
else:
layout.template_preview(tex, slot=slot)
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):
# mat = bpy.context.active_object.active_material # Unused
tex = context.texture
if tex is not None and tex.pov.tex_pattern_type != "emulator":
if tex.pov.tex_pattern_type == "agate":
layout.prop(tex.pov, "modifier_turbulence", text="Agate Turbulence")
if tex.pov.tex_pattern_type in {"spiral1", "spiral2"}:
layout.prop(tex.pov, "modifier_numbers", text="Number of arms")
if tex.pov.tex_pattern_type == "tiling":
layout.prop(tex.pov, "modifier_numbers", text="Pattern number")
if tex.pov.tex_pattern_type == "magnet":
layout.prop(tex.pov, "magnet_style", text="Magnet style")
if tex.pov.tex_pattern_type == "quilted":
row = layout.row(align=align)
row.prop(tex.pov, "modifier_control0", text="Control0")
row.prop(tex.pov, "modifier_control1", text="Control1")
if tex.pov.tex_pattern_type == "brick":
col = layout.column(align=align)
row = col.row()
row.prop(tex.pov, "brick_size_x", text="Brick size X")
row.prop(tex.pov, "brick_size_y", text="Brick size Y")
row = col.row()
row.prop(tex.pov, "brick_size_z", text="Brick size Z")
row.prop(tex.pov, "brick_mortar", text="Brick mortar")
if tex.pov.tex_pattern_type in {"julia", "mandel", "magnet"}:
if tex.pov.tex_pattern_type == "julia":
row = col.row()
row.prop(tex.pov, "julia_complex_1", text="Complex 1")
row.prop(tex.pov, "julia_complex_2", text="Complex 2")
if tex.pov.tex_pattern_type == "magnet" and tex.pov.magnet_style == "julia":
row = col.row()
row.prop(tex.pov, "julia_complex_1", text="Complex 1")
row.prop(tex.pov, "julia_complex_2", text="Complex 2")
row = col.row()
if tex.pov.tex_pattern_type in {"julia", "mandel"}:
if tex.pov.tex_pattern_type == "magnet":
row.prop(tex.pov, "magnet_type", text="Type")
row.prop(tex.pov, "f_iter", text="Iterations")
row = col.row()
row.prop(tex.pov, "f_ior", text="Interior")
row.prop(tex.pov, "f_ior_fac", text="Factor I")
row = col.row()
row.prop(tex.pov, "f_eor", text="Exterior")
row.prop(tex.pov, "f_eor_fac", text="Factor E")
if tex.pov.tex_pattern_type == "gradient":
layout.label(text="Gradient orientation:")
column_flow = layout.column_flow(columns=3, align=True)
column_flow.prop(tex.pov, "grad_orient_x", text="X")
column_flow.prop(tex.pov, "grad_orient_y", text="Y")
column_flow.prop(tex.pov, "grad_orient_z", text="Z")
if tex.pov.tex_pattern_type == "pavement":
layout.prop(tex.pov, "pave_sides", text="Pavement:number of sides")
col = layout.column(align=align)
column_flow = col.column_flow(columns=3, align=True)
column_flow.prop(tex.pov, "pave_tiles", text="Tiles")
if tex.pov.pave_sides == "4" and tex.pov.pave_tiles == 6:
column_flow.prop(tex.pov, "pave_pat_35", text="Pattern")
if tex.pov.pave_sides == "6" and tex.pov.pave_tiles == 5:
column_flow.prop(tex.pov, "pave_pat_22", text="Pattern")
if tex.pov.pave_sides == "4" and tex.pov.pave_tiles == 5:
column_flow.prop(tex.pov, "pave_pat_12", text="Pattern")
if tex.pov.pave_sides == "3" and tex.pov.pave_tiles == 6:
column_flow.prop(tex.pov, "pave_pat_12", text="Pattern")
if tex.pov.pave_sides == "6" and tex.pov.pave_tiles == 4:
column_flow.prop(tex.pov, "pave_pat_7", text="Pattern")
if tex.pov.pave_sides == "4" and tex.pov.pave_tiles == 4:
column_flow.prop(tex.pov, "pave_pat_5", text="Pattern")
if tex.pov.pave_sides == "3" and tex.pov.pave_tiles == 5:
column_flow.prop(tex.pov, "pave_pat_4", text="Pattern")
if tex.pov.pave_sides == "6" and tex.pov.pave_tiles == 3:
column_flow.prop(tex.pov, "pave_pat_3", text="Pattern")
if tex.pov.pave_sides == "3" and tex.pov.pave_tiles == 4:
column_flow.prop(tex.pov, "pave_pat_3", text="Pattern")
if tex.pov.pave_sides == "4" and tex.pov.pave_tiles == 3:
column_flow.prop(tex.pov, "pave_pat_2", text="Pattern")
if tex.pov.pave_sides == "6" and tex.pov.pave_tiles == 6:
column_flow.label(text="!!! 5 tiles!")
column_flow.prop(tex.pov, "pave_form", text="Form")
if tex.pov.tex_pattern_type == "function":
layout.prop(tex.pov, "func_list", text="Functions")
if tex.pov.tex_pattern_type == "function" and tex.pov.func_list != "NONE":
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
func = None
if tex.pov.func_list in {"f_noise3d", "f_ph", "f_r", "f_th"}:
func = 0
if tex.pov.func_list in {
"f_comma",
"f_crossed_trough",
"f_cubic_saddle",
"f_cushion",
"f_devils_curve",
"f_enneper",
"f_glob",
"f_heart",
"f_hex_x",
"f_hex_y",
"f_hunt_surface",
"f_klein_bottle",
"f_kummer_surface_v1",
"f_lemniscate_of_gerono",
"f_mitre",
"f_nodal_cubic",
"f_noise_generator",
"f_odd",
"f_paraboloid",
"f_pillow",
"f_piriform",
"f_quantum",
"f_quartic_paraboloid",
"f_quartic_saddle",
"f_sphere",
"f_steiners_roman",
"f_torus_gumdrop",
"f_umbrella",
}:
func = 1
if tex.pov.func_list in {
"f_bicorn",
"f_bifolia",
"f_boy_surface",
"f_superellipsoid",
"f_torus",
}:
func = 2
if tex.pov.func_list in {
"f_ellipsoid",
"f_folium_surface",
"f_hyperbolic_torus",
"f_kampyle_of_eudoxus",
"f_parabolic_torus",
"f_quartic_cylinder",
"f_torus2",
}:
func = 3
if tex.pov.func_list in {
"f_blob2",
"f_cross_ellipsoids",
"f_flange_cover",
"f_isect_ellipsoids",
"f_kummer_surface_v2",
"f_ovals_of_cassini",
"f_rounded_box",
"f_spikes_2d",
"f_strophoid",
}:
func = 4
if tex.pov.func_list in {
"f_algbr_cyl1",
"f_algbr_cyl2",
"f_algbr_cyl3",
"f_algbr_cyl4",
"f_blob",
"f_mesh1",
"f_poly4",
"f_spikes",
}:
func = 5
if tex.pov.func_list in {
"f_devils_curve_2d",
"f_dupin_cyclid",
"f_folium_surface_2d",
"f_hetero_mf",
"f_kampyle_of_eudoxus_2d",
"f_lemniscate_of_gerono_2d",
"f_polytubes",
"f_ridge",
"f_ridged_mf",
"f_spiral",
"f_witch_of_agnesi",
}:
func = 6
if tex.pov.func_list in {"f_helix1", "f_helix2", "f_piriform_2d", "f_strophoid_2d"}:
func = 7
if tex.pov.func_list == "f_helical_torus":
func = 8
column_flow = layout.column_flow(columns=3, align=True)
column_flow.label(text="X")
column_flow.prop(tex.pov, "func_plus_x", text="")
column_flow.prop(tex.pov, "func_x", text="Value")
column_flow = layout.column_flow(columns=3, align=True)
column_flow.label(text="Y")
column_flow.prop(tex.pov, "func_plus_y", text="")
column_flow.prop(tex.pov, "func_y", text="Value")
column_flow = layout.column_flow(columns=3, align=True)
column_flow.label(text="Z")
column_flow.prop(tex.pov, "func_plus_z", text="")
column_flow.prop(tex.pov, "func_z", text="Value")
row = layout.row(align=align)
if func > 0:
row.prop(tex.pov, "func_P0", text="P0")
if func > 1:
row.prop(tex.pov, "func_P1", text="P1")
row = layout.row(align=align)
if func > 2:
row.prop(tex.pov, "func_P2", text="P2")
if func > 3:
row.prop(tex.pov, "func_P3", text="P3")
row = layout.row(align=align)
if func > 4:
row.prop(tex.pov, "func_P4", text="P4")
if func > 5:
row.prop(tex.pov, "func_P5", text="P5")
row = layout.row(align=align)
if func > 6:
row.prop(tex.pov, "func_P6", text="P6")
if func > 7:
row.prop(tex.pov, "func_P7", text="P7")
row = layout.row(align=align)
row.prop(tex.pov, "func_P8", text="P8")
row.prop(tex.pov, "func_P9", text="P9")
# ------------------------- End Patterns ------------------------- #
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
layout.prop(tex.pov, "warp_types", text="Warp types") # warp
if tex.pov.warp_types == "TOROIDAL":
layout.prop(tex.pov, "warp_tor_major_radius", text="Major radius")
if tex.pov.warp_types not in {"CUBIC", "NONE"}:
layout.prop(tex.pov, "warp_orientation", text="Warp orientation")
col = layout.column(align=align)
row = col.row()
row.prop(tex.pov, "warp_dist_exp", text="Distance exponent")
row = col.row()
row.prop(tex.pov, "modifier_frequency", text="Frequency")
row.prop(tex.pov, "modifier_phase", text="Phase")
row = layout.row()
row.label(text="Offset:")
row.label(text="Scale:")
row.label(text="Rotate:")
col = layout.column(align=align)
row = col.row()
row.prop(tex.pov, "tex_mov_x", text="X")
row.prop(tex.pov, "tex_scale_x", text="X")
row.prop(tex.pov, "tex_rot_x", text="X")
row = col.row()
row.prop(tex.pov, "tex_mov_y", text="Y")
row.prop(tex.pov, "tex_scale_y", text="Y")
row.prop(tex.pov, "tex_rot_y", text="Y")
row = col.row()
row.prop(tex.pov, "tex_mov_z", text="Z")
row.prop(tex.pov, "tex_scale_z", text="Z")
row.prop(tex.pov, "tex_rot_z", text="Z")
row = layout.row()
row.label(text="Turbulence:")
col = layout.column(align=align)
row = col.row()
row.prop(tex.pov, "warp_turbulence_x", text="X")
row.prop(tex.pov, "modifier_octaves", text="Octaves")
row = col.row()
row.prop(tex.pov, "warp_turbulence_y", text="Y")
row.prop(tex.pov, "modifier_lambda", text="Lambda")
row = col.row()
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"
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
@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)
mat = bpy.context.active_object.active_material
# 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":
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
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"}:
if idblock.type == "VOLUME" and tex.texture_coords == "ORCO":
elif tex.texture_coords == "OBJECT":
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="")