Sun Position: remove show_daylight_savings preference
[blender-addons.git] / render_povray / nodes_properties.py
blob2147134e1d543c7ee4b522bad28d64599d940110
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 """"Nodes based User interface for shaders exported to POV textures."""
4 import bpy
6 from bpy.utils import register_class, unregister_class
7 from bpy.types import NodeSocket, Operator
8 from bpy.props import (
9 StringProperty,
10 FloatVectorProperty,
12 import nodeitems_utils
13 from nodeitems_utils import NodeCategory, NodeItem
15 # ---------------------------------------------------------------- #
16 # Pov Nodes init
17 # ---------------------------------------------------------------- #
18 # -------- Parent node class
19 class ObjectNodeTree(bpy.types.NodeTree):
20 """Povray Material Nodes"""
22 bl_idname = "ObjectNodeTree"
23 bl_label = "Povray Object Nodes"
24 bl_icon = "PLUGIN"
26 @classmethod
27 def poll(cls, context):
28 return context.scene.render.engine == "POVRAY_RENDER"
30 @classmethod
31 def get_from_context(cls, context):
32 ob = context.active_object
33 if ob and ob.type != 'LIGHT':
34 ma = ob.active_material
35 if ma is not None:
36 nt_name = ma.node_tree
37 if nt_name != "":
38 return nt_name, ma, ma
39 return (None, None, None)
41 def update(self):
42 self.refresh = True
45 # -------- Sockets classes
46 class PovraySocketUniversal(NodeSocket):
47 bl_idname = "PovraySocketUniversal"
48 bl_label = "Povray Socket"
49 value_unlimited: bpy.props.FloatProperty(default=0.0)
50 value_0_1: bpy.props.FloatProperty(min=0.0, max=1.0, default=0.0)
51 value_0_10: bpy.props.FloatProperty(min=0.0, max=10.0, default=0.0)
52 value_000001_10: bpy.props.FloatProperty(min=0.000001, max=10.0, default=0.0)
53 value_1_9: bpy.props.IntProperty(min=1, max=9, default=1)
54 value_0_255: bpy.props.IntProperty(min=0, max=255, default=0)
55 percent: bpy.props.FloatProperty(min=0.0, max=100.0, default=0.0)
57 def draw(self, context, layout, node, text):
58 space = context.space_data
59 tree = space.edit_tree
60 links = tree.links
61 if self.is_linked:
62 value = []
63 for link in links:
64 # inps = link.to_node.inputs
65 linked_inps = (
66 inp for inp in link.to_node.inputs if link.from_node == node and inp.is_linked
68 for inp in linked_inps:
69 if inp.bl_idname == "PovraySocketFloat_0_1":
70 if (prop := "value_0_1") not in value:
71 value.append(prop)
72 if inp.bl_idname == "PovraySocketFloat_000001_10":
73 if (prop := "value_000001_10") not in value:
74 value.append(prop)
75 if inp.bl_idname == "PovraySocketFloat_0_10":
76 if (prop := "value_0_10") not in value:
77 value.append(prop)
78 if inp.bl_idname == "PovraySocketInt_1_9":
79 if (prop := "value_1_9") not in value:
80 value.append(prop)
81 if inp.bl_idname == "PovraySocketInt_0_255":
82 if (prop := "value_0_255") not in value:
83 value.append(prop)
84 if inp.bl_idname == "PovraySocketFloatUnlimited":
85 if (prop := "value_unlimited") not in value:
86 value.append(prop)
87 if len(value) == 1:
88 layout.prop(self, "%s" % value[0], text=text)
89 else:
90 layout.prop(self, "percent", text="Percent")
91 else:
92 layout.prop(self, "percent", text=text)
94 def draw_color(self, context, node):
95 return (1, 0, 0, 1)
98 class PovraySocketFloat_0_1(NodeSocket):
99 bl_idname = "PovraySocketFloat_0_1"
100 bl_label = "Povray Socket"
101 default_value: bpy.props.FloatProperty(
102 description="Input node Value_0_1", min=0, max=1, default=0
105 def draw(self, context, layout, node, text):
106 if self.is_linked:
107 layout.label(text=text)
108 else:
109 layout.prop(self, "default_value", text=text, slider=True)
111 def draw_color(self, context, node):
112 return (0.5, 0.7, 0.7, 1)
115 class PovraySocketFloat_0_10(NodeSocket):
116 bl_idname = "PovraySocketFloat_0_10"
117 bl_label = "Povray Socket"
118 default_value: bpy.props.FloatProperty(
119 description="Input node Value_0_10", min=0, max=10, default=0
122 def draw(self, context, layout, node, text):
123 if node.bl_idname == "ShaderNormalMapNode" and node.inputs[2].is_linked:
124 layout.label(text="")
125 self.hide_value = True
126 if self.is_linked:
127 layout.label(text=text)
128 else:
129 layout.prop(self, "default_value", text=text, slider=True)
131 def draw_color(self, context, node):
132 return (0.65, 0.65, 0.65, 1)
135 class PovraySocketFloat_10(NodeSocket):
136 bl_idname = "PovraySocketFloat_10"
137 bl_label = "Povray Socket"
138 default_value: bpy.props.FloatProperty(
139 description="Input node Value_10", min=-10, max=10, default=0
142 def draw(self, context, layout, node, text):
143 if node.bl_idname == "ShaderNormalMapNode" and node.inputs[2].is_linked:
144 layout.label(text="")
145 self.hide_value = True
146 if self.is_linked:
147 layout.label(text=text)
148 else:
149 layout.prop(self, "default_value", text=text, slider=True)
151 def draw_color(self, context, node):
152 return (0.65, 0.65, 0.65, 1)
155 class PovraySocketFloatPositive(NodeSocket):
156 bl_idname = "PovraySocketFloatPositive"
157 bl_label = "Povray Socket"
158 default_value: bpy.props.FloatProperty(
159 description="Input Node Value Positive", min=0.0, default=0
162 def draw(self, context, layout, node, text):
163 if self.is_linked:
164 layout.label(text=text)
165 else:
166 layout.prop(self, "default_value", text=text, slider=True)
168 def draw_color(self, context, node):
169 return (0.045, 0.005, 0.136, 1)
172 class PovraySocketFloat_000001_10(NodeSocket):
173 bl_idname = "PovraySocketFloat_000001_10"
174 bl_label = "Povray Socket"
175 default_value: bpy.props.FloatProperty(min=0.000001, max=10, default=0.000001)
177 def draw(self, context, layout, node, text):
178 if self.is_output or self.is_linked:
179 layout.label(text=text)
180 else:
181 layout.prop(self, "default_value", text=text, slider=True)
183 def draw_color(self, context, node):
184 return (1, 0, 0, 1)
187 class PovraySocketFloatUnlimited(NodeSocket):
188 bl_idname = "PovraySocketFloatUnlimited"
189 bl_label = "Povray Socket"
190 default_value: bpy.props.FloatProperty(default=0.0)
192 def draw(self, context, layout, node, text):
193 if self.is_linked:
194 layout.label(text=text)
195 else:
196 layout.prop(self, "default_value", text=text, slider=True)
198 def draw_color(self, context, node):
199 return (0.7, 0.7, 1, 1)
202 class PovraySocketInt_1_9(NodeSocket):
203 bl_idname = "PovraySocketInt_1_9"
204 bl_label = "Povray Socket"
205 default_value: bpy.props.IntProperty(
206 description="Input node Value_1_9", min=1, max=9, default=6
209 def draw(self, context, layout, node, text):
210 if self.is_linked:
211 layout.label(text=text)
212 else:
213 layout.prop(self, "default_value", text=text)
215 def draw_color(self, context, node):
216 return (1, 0.7, 0.7, 1)
219 class PovraySocketInt_0_256(NodeSocket):
220 bl_idname = "PovraySocketInt_0_256"
221 bl_label = "Povray Socket"
222 default_value: bpy.props.IntProperty(min=0, max=255, default=0)
224 def draw(self, context, layout, node, text):
225 if self.is_linked:
226 layout.label(text=text)
227 else:
228 layout.prop(self, "default_value", text=text)
230 def draw_color(self, context, node):
231 return (0.5, 0.5, 0.5, 1)
234 class PovraySocketPattern(NodeSocket):
235 bl_idname = "PovraySocketPattern"
236 bl_label = "Povray Socket"
238 default_value: bpy.props.EnumProperty(
239 name="Pattern",
240 description="Select the pattern",
241 items=(
242 ("boxed", "Boxed", ""),
243 ("brick", "Brick", ""),
244 ("cells", "Cells", ""),
245 ("checker", "Checker", ""),
246 ("granite", "Granite", ""),
247 ("leopard", "Leopard", ""),
248 ("marble", "Marble", ""),
249 ("onion", "Onion", ""),
250 ("planar", "Planar", ""),
251 ("quilted", "Quilted", ""),
252 ("ripples", "Ripples", ""),
253 ("radial", "Radial", ""),
254 ("spherical", "Spherical", ""),
255 ("spotted", "Spotted", ""),
256 ("waves", "Waves", ""),
257 ("wood", "Wood", ""),
258 ("wrinkles", "Wrinkles", ""),
260 default="granite",
263 def draw(self, context, layout, node, text):
264 if self.is_output or self.is_linked:
265 layout.label(text="Pattern")
266 else:
267 layout.prop(self, "default_value", text=text)
269 def draw_color(self, context, node):
270 return (1, 1, 1, 1)
273 class PovraySocketColor(NodeSocket):
274 bl_idname = "PovraySocketColor"
275 bl_label = "Povray Socket"
277 default_value: FloatVectorProperty(
278 precision=4,
279 step=0.01,
280 min=0,
281 soft_max=1,
282 default=(0.0, 0.0, 0.0),
283 options={"ANIMATABLE"},
284 subtype="COLOR",
287 def draw(self, context, layout, node, text):
288 if self.is_output or self.is_linked:
289 layout.label(text=text)
290 else:
291 layout.prop(self, "default_value", text=text)
293 def draw_color(self, context, node):
294 return (1, 1, 0, 1)
297 class PovraySocketColorRGBFT(NodeSocket):
298 bl_idname = "PovraySocketColorRGBFT"
299 bl_label = "Povray Socket"
301 default_value: FloatVectorProperty(
302 precision=4,
303 step=0.01,
304 min=0,
305 soft_max=1,
306 default=(0.0, 0.0, 0.0),
307 options={"ANIMATABLE"},
308 subtype="COLOR",
310 f: bpy.props.FloatProperty(default=0.0, min=0.0, max=1.0)
311 t: bpy.props.FloatProperty(default=0.0, min=0.0, max=1.0)
313 def draw(self, context, layout, node, text):
314 if self.is_output or self.is_linked:
315 layout.label(text=text)
316 else:
317 layout.prop(self, "default_value", text=text)
319 def draw_color(self, context, node):
320 return (1, 1, 0, 1)
323 class PovraySocketTexture(NodeSocket):
324 bl_idname = "PovraySocketTexture"
325 bl_label = "Povray Socket"
326 default_value: bpy.props.IntProperty()
328 def draw(self, context, layout, node, text):
329 layout.label(text=text)
331 def draw_color(self, context, node):
332 return (0, 1, 0, 1)
335 class PovraySocketTransform(NodeSocket):
336 bl_idname = "PovraySocketTransform"
337 bl_label = "Povray Socket"
338 default_value: bpy.props.IntProperty(min=0, max=255, default=0)
340 def draw(self, context, layout, node, text):
341 layout.label(text=text)
343 def draw_color(self, context, node):
344 return (99 / 255, 99 / 255, 199 / 255, 1)
347 class PovraySocketNormal(NodeSocket):
348 bl_idname = "PovraySocketNormal"
349 bl_label = "Povray Socket"
350 default_value: bpy.props.IntProperty(min=0, max=255, default=0)
352 def draw(self, context, layout, node, text):
353 layout.label(text=text)
355 def draw_color(self, context, node):
356 return (0.65, 0.65, 0.65, 1)
359 class PovraySocketSlope(NodeSocket):
360 bl_idname = "PovraySocketSlope"
361 bl_label = "Povray Socket"
362 default_value: bpy.props.FloatProperty(min=0.0, max=1.0)
363 height: bpy.props.FloatProperty(min=0.0, max=10.0)
364 slope: bpy.props.FloatProperty(min=-10.0, max=10.0)
366 def draw(self, context, layout, node, text):
367 if self.is_output or self.is_linked:
368 layout.label(text=text)
369 else:
370 layout.prop(self, "default_value", text="")
371 layout.prop(self, "height", text="")
372 layout.prop(self, "slope", text="")
374 def draw_color(self, context, node):
375 return (0, 0, 0, 1)
378 class PovraySocketMap(NodeSocket):
379 bl_idname = "PovraySocketMap"
380 bl_label = "Povray Socket"
381 default_value: bpy.props.StringProperty()
383 def draw(self, context, layout, node, text):
384 layout.label(text=text)
386 def draw_color(self, context, node):
387 return (0.2, 0, 0.2, 1)
390 class PovrayPatternNode(Operator):
391 bl_idname = "pov.patternnode"
392 bl_label = "Pattern"
394 add = True
396 def execute(self, context):
397 space = context.space_data
398 tree = space.edit_tree
399 for node in tree.nodes:
400 node.select = False
401 if self.add:
402 tmap = tree.nodes.new("ShaderNodeValToRGB")
403 tmap.label = "Pattern"
404 for inp in tmap.inputs:
405 tmap.inputs.remove(inp)
406 for outp in tmap.outputs:
407 tmap.outputs.remove(outp)
408 pattern = tmap.inputs.new("PovraySocketPattern", "Pattern")
409 pattern.hide_value = True
410 mapping = tmap.inputs.new("NodeSocketVector", "Mapping")
411 mapping.hide_value = True
412 transform = tmap.inputs.new("NodeSocketVector", "Transform")
413 transform.hide_value = True
414 modifier = tmap.inputs.new("NodeSocketVector", "Modifier")
415 modifier.hide_value = True
416 for i in range(0, 2):
417 tmap.inputs.new("NodeSocketShader", "%s" % (i + 1))
418 tmap.outputs.new("NodeSocketShader", "Material")
419 tmap.outputs.new("NodeSocketColor", "Color")
420 tree.nodes.active = tmap
421 self.add = False
422 aNode = tree.nodes.active
423 aNode.select = True
424 v2d = context.region.view2d
425 x, y = v2d.region_to_view(self.x, self.y)
426 aNode.location = (x, y)
428 def modal(self, context, event):
429 if event.type == "MOUSEMOVE":
430 self.x = event.mouse_region_x
431 self.y = event.mouse_region_y
432 self.execute(context)
433 return {"RUNNING_MODAL"}
434 if event.type == "LEFTMOUSE":
435 return {"FINISHED"}
436 if event.type in ("RIGHTMOUSE", "ESC"):
437 return {"CANCELLED"}
439 return {"RUNNING_MODAL"}
441 def invoke(self, context, event):
442 context.window_manager.modal_handler_add(self)
443 return {"RUNNING_MODAL"}
446 class UpdatePreviewMaterial(Operator):
447 """Operator update preview material"""
449 bl_idname = "node.updatepreview"
450 bl_label = "Update preview"
452 def execute(self, context):
453 scene = context.view_layer
454 ob = context.object
455 for obj in scene.objects:
456 if obj != ob:
457 scene.objects.active = ob
458 break
459 scene.objects.active = ob
461 def modal(self, context, event):
462 if event.type == "RIGHTMOUSE":
463 self.execute(context)
464 return {"FINISHED"}
465 return {"PASS_THROUGH"}
467 def invoke(self, context, event):
468 context.window_manager.modal_handler_add(self)
469 return {"RUNNING_MODAL"}
472 class UpdatePreviewKey(Operator):
473 """Operator update preview keymap"""
475 bl_idname = "wm.updatepreviewkey"
476 bl_label = "Activate RMB"
478 @classmethod
479 def poll(cls, context):
480 conf = context.window_manager.keyconfigs.active
481 mapstr = "Node Editor"
482 map = conf.keymaps[mapstr]
483 try:
484 map.keymap_items["node.updatepreview"]
485 return False
486 except BaseException as e:
487 print(e.__doc__)
488 print("An exception occurred: {}".format(e))
489 return True
491 def execute(self, context):
492 conf = context.window_manager.keyconfigs.active
493 mapstr = "Node Editor"
494 map = conf.keymaps[mapstr]
495 map.keymap_items.new("node.updatepreview", type="RIGHTMOUSE", value="PRESS")
496 return {"FINISHED"}
499 class PovrayShaderNodeCategory(NodeCategory):
500 @classmethod
501 def poll(cls, context):
502 return context.space_data.tree_type == "ObjectNodeTree"
505 class PovrayTextureNodeCategory(NodeCategory):
506 @classmethod
507 def poll(cls, context):
508 return context.space_data.tree_type == "TextureNodeTree"
511 class PovraySceneNodeCategory(NodeCategory):
512 @classmethod
513 def poll(cls, context):
514 return context.space_data.tree_type == "CompositorNodeTree"
517 node_categories = [
518 PovrayShaderNodeCategory("SHADEROUTPUT", "Output", items=[NodeItem("PovrayOutputNode")]),
519 PovrayShaderNodeCategory("SIMPLE", "Simple texture", items=[NodeItem("PovrayTextureNode")]),
520 PovrayShaderNodeCategory(
521 "MAPS",
522 "Maps",
523 items=[
524 NodeItem("PovrayBumpMapNode"),
525 NodeItem("PovrayColorImageNode"),
526 NodeItem("ShaderNormalMapNode"),
527 NodeItem("PovraySlopeNode"),
528 NodeItem("ShaderTextureMapNode"),
529 NodeItem("ShaderNodeValToRGB"),
532 PovrayShaderNodeCategory(
533 "OTHER",
534 "Other patterns",
535 items=[NodeItem("PovrayImagePatternNode"), NodeItem("ShaderPatternNode")],
537 PovrayShaderNodeCategory("COLOR", "Color", items=[NodeItem("PovrayPigmentNode")]),
538 PovrayShaderNodeCategory(
539 "TRANSFORM",
540 "Transform",
541 items=[
542 NodeItem("PovrayMappingNode"),
543 NodeItem("PovrayMultiplyNode"),
544 NodeItem("PovrayModifierNode"),
545 NodeItem("PovrayTransformNode"),
546 NodeItem("PovrayValueNode"),
549 PovrayShaderNodeCategory(
550 "FINISH",
551 "Finish",
552 items=[
553 NodeItem("PovrayFinishNode"),
554 NodeItem("PovrayDiffuseNode"),
555 NodeItem("PovraySpecularNode"),
556 NodeItem("PovrayPhongNode"),
557 NodeItem("PovrayAmbientNode"),
558 NodeItem("PovrayMirrorNode"),
559 NodeItem("PovrayIridescenceNode"),
560 NodeItem("PovraySubsurfaceNode"),
563 PovrayShaderNodeCategory(
564 "CYCLES",
565 "Cycles",
566 items=[
567 NodeItem("ShaderNodeAddShader"),
568 NodeItem("ShaderNodeAmbientOcclusion"),
569 NodeItem("ShaderNodeAttribute"),
570 NodeItem("ShaderNodeBackground"),
571 NodeItem("ShaderNodeBlackbody"),
572 NodeItem("ShaderNodeBrightContrast"),
573 NodeItem("ShaderNodeBsdfAnisotropic"),
574 NodeItem("ShaderNodeBsdfDiffuse"),
575 NodeItem("ShaderNodeBsdfGlass"),
576 NodeItem("ShaderNodeBsdfGlossy"),
577 NodeItem("ShaderNodeBsdfHair"),
578 NodeItem("ShaderNodeBsdfRefraction"),
579 NodeItem("ShaderNodeBsdfToon"),
580 NodeItem("ShaderNodeBsdfTranslucent"),
581 NodeItem("ShaderNodeBsdfTransparent"),
582 NodeItem("ShaderNodeBsdfVelvet"),
583 NodeItem("ShaderNodeBump"),
584 NodeItem("ShaderNodeCameraData"),
585 NodeItem("ShaderNodeCombineHSV"),
586 NodeItem("ShaderNodeCombineRGB"),
587 NodeItem("ShaderNodeCombineXYZ"),
588 NodeItem("ShaderNodeEmission"),
589 NodeItem("ShaderNodeExtendedMaterial"),
590 NodeItem("ShaderNodeFresnel"),
591 NodeItem("ShaderNodeGamma"),
592 NodeItem("ShaderNodeGeometry"),
593 NodeItem("ShaderNodeGroup"),
594 NodeItem("ShaderNodeHairInfo"),
595 NodeItem("ShaderNodeHoldout"),
596 NodeItem("ShaderNodeHueSaturation"),
597 NodeItem("ShaderNodeInvert"),
598 NodeItem("ShaderNodeLampData"),
599 NodeItem("ShaderNodeLayerWeight"),
600 NodeItem("ShaderNodeLightFalloff"),
601 NodeItem("ShaderNodeLightPath"),
602 NodeItem("ShaderNodeMapping"),
603 NodeItem("ShaderNodeMaterial"),
604 NodeItem("ShaderNodeMath"),
605 NodeItem("ShaderNodeMixRGB"),
606 NodeItem("ShaderNodeMixShader"),
607 NodeItem("ShaderNodeNewGeometry"),
608 NodeItem("ShaderNodeNormal"),
609 NodeItem("ShaderNodeNormalMap"),
610 NodeItem("ShaderNodeObjectInfo"),
611 NodeItem("ShaderNodeOutput"),
612 NodeItem("ShaderNodeOutputLamp"),
613 NodeItem("ShaderNodeOutputLineStyle"),
614 NodeItem("ShaderNodeOutputMaterial"),
615 NodeItem("ShaderNodeOutputWorld"),
616 NodeItem("ShaderNodeParticleInfo"),
617 NodeItem("ShaderNodeRGB"),
618 NodeItem("ShaderNodeRGBCurve"),
619 NodeItem("ShaderNodeRGBToBW"),
620 NodeItem("ShaderNodeScript"),
621 NodeItem("ShaderNodeSeparateHSV"),
622 NodeItem("ShaderNodeSeparateRGB"),
623 NodeItem("ShaderNodeSeparateXYZ"),
624 NodeItem("ShaderNodeSqueeze"),
625 NodeItem("ShaderNodeSubsurfaceScattering"),
626 NodeItem("ShaderNodeTangent"),
627 NodeItem("ShaderNodeTexBrick"),
628 NodeItem("ShaderNodeTexChecker"),
629 NodeItem("ShaderNodeTexCoord"),
630 NodeItem("ShaderNodeTexEnvironment"),
631 NodeItem("ShaderNodeTexGradient"),
632 NodeItem("ShaderNodeTexImage"),
633 NodeItem("ShaderNodeTexMagic"),
634 NodeItem("ShaderNodeTexMusgrave"),
635 NodeItem("ShaderNodeTexNoise"),
636 NodeItem("ShaderNodeTexPointDensity"),
637 NodeItem("ShaderNodeTexSky"),
638 NodeItem("ShaderNodeTexVoronoi"),
639 NodeItem("ShaderNodeTexWave"),
640 NodeItem("ShaderNodeTexture"),
641 NodeItem("ShaderNodeUVAlongStroke"),
642 NodeItem("ShaderNodeUVMap"),
643 NodeItem("ShaderNodeValToRGB"),
644 NodeItem("ShaderNodeValue"),
645 NodeItem("ShaderNodeVectorCurve"),
646 NodeItem("ShaderNodeVectorMath"),
647 NodeItem("ShaderNodeVectorTransform"),
648 NodeItem("ShaderNodeVolumeAbsorption"),
649 NodeItem("ShaderNodeVolumeScatter"),
650 NodeItem("ShaderNodeWavelength"),
651 NodeItem("ShaderNodeWireframe"),
654 PovrayTextureNodeCategory(
655 "TEXTUREOUTPUT",
656 "Output",
657 items=[NodeItem("TextureNodeValToRGB"), NodeItem("TextureOutputNode")],
659 PovraySceneNodeCategory("ISOSURFACE", "Isosurface", items=[NodeItem("IsoPropsNode")]),
660 PovraySceneNodeCategory("FOG", "Fog", items=[NodeItem("PovrayFogNode")]),
662 # -------- end nodes init
665 classes = (
666 ObjectNodeTree,
667 PovraySocketUniversal,
668 PovraySocketFloat_0_1,
669 PovraySocketFloat_0_10,
670 PovraySocketFloat_10,
671 PovraySocketFloatPositive,
672 PovraySocketFloat_000001_10,
673 PovraySocketFloatUnlimited,
674 PovraySocketInt_1_9,
675 PovraySocketInt_0_256,
676 PovraySocketPattern,
677 PovraySocketColor,
678 PovraySocketColorRGBFT,
679 PovraySocketTexture,
680 PovraySocketTransform,
681 PovraySocketNormal,
682 PovraySocketSlope,
683 PovraySocketMap,
684 # PovrayShaderNodeCategory, # XXX SOMETHING BROKEN from 2.8 ?
685 # PovrayTextureNodeCategory, # XXX SOMETHING BROKEN from 2.8 ?
686 # PovraySceneNodeCategory, # XXX SOMETHING BROKEN from 2.8 ?
687 PovrayPatternNode,
688 UpdatePreviewMaterial,
689 UpdatePreviewKey,
693 def register():
694 nodeitems_utils.register_node_categories("POVRAYNODES", node_categories)
695 for cls in classes:
696 register_class(cls)
699 def unregister():
700 for cls in reversed(classes):
701 unregister_class(cls)
702 nodeitems_utils.unregister_node_categories("POVRAYNODES")