mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-26 13:52:15 +01:00
Merge pull request #163 from aardschok/houdini
Improvements on Houdini pipeline
This commit is contained in:
commit
a13b272ef1
19 changed files with 524 additions and 33 deletions
|
|
@ -30,6 +30,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
|
|||
"colorbleed.mayaAscii",
|
||||
"colorbleed.model",
|
||||
"colorbleed.pointcache",
|
||||
"colorbleed.vdbcache",
|
||||
"colorbleed.setdress",
|
||||
"colorbleed.rig",
|
||||
"colorbleed.vrayproxy",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
from collections import OrderedDict
|
||||
|
||||
import hou
|
||||
|
||||
from avalon import houdini
|
||||
|
||||
|
||||
|
|
@ -22,9 +20,18 @@ class CreatePointCache(houdini.Creator):
|
|||
# Set node type to create for output
|
||||
data["node_type"] = "alembic"
|
||||
|
||||
# Collect animation data for point cache exporting
|
||||
start, end = hou.playbar.timelineRange()
|
||||
data["startFrame"] = start
|
||||
data["endFrame"] = end
|
||||
|
||||
self.data = data
|
||||
|
||||
def process(self):
|
||||
instance = super(CreatePointCache, self).process()
|
||||
|
||||
parms = {"build_from_path": 1,
|
||||
"path_attrib": "path",
|
||||
"use_sop_path": True,
|
||||
"filename": "$HIP/%s.abc" % self.name}
|
||||
|
||||
if self.nodes:
|
||||
node = self.nodes[0]
|
||||
parms.update({"sop_path": "%s/OUT" % node.path()})
|
||||
|
||||
instance.setParms(parms)
|
||||
|
|
|
|||
32
colorbleed/plugins/houdini/create/create_vbd_cache.py
Normal file
32
colorbleed/plugins/houdini/create/create_vbd_cache.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
from collections import OrderedDict
|
||||
|
||||
from avalon import houdini
|
||||
|
||||
|
||||
class CreateVDBCache(houdini.Creator):
|
||||
"""Alembic pointcache for animated data"""
|
||||
|
||||
name = "vbdcache"
|
||||
label = "VDB Cache"
|
||||
family = "colorbleed.vdbcache"
|
||||
icon = "cloud"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(CreateVDBCache, self).__init__(*args, **kwargs)
|
||||
|
||||
# create an ordered dict with the existing data first
|
||||
data = OrderedDict(**self.data)
|
||||
|
||||
# Set node type to create for output
|
||||
data["node_type"] = "geometry"
|
||||
|
||||
self.data = data
|
||||
|
||||
def process(self):
|
||||
instance = super(CreateVDBCache, self).process()
|
||||
|
||||
parms = {"sopoutput": "$HIP/geo/%s.$F4.vdb" % self.name}
|
||||
if self.nodes:
|
||||
parms.update({"soppath": self.nodes[0].path()})
|
||||
|
||||
instance.setParms(parms)
|
||||
|
|
@ -6,8 +6,10 @@ from avalon.houdini import pipeline, lib
|
|||
class AbcLoader(api.Loader):
|
||||
"""Specific loader of Alembic for the avalon.animation family"""
|
||||
|
||||
families = ["colorbleed.animation", "colorbleed.pointcache"]
|
||||
label = "Load Animation"
|
||||
families = ["colorbleed.model",
|
||||
"colorbleed.animation",
|
||||
"colorbleed.pointcache"]
|
||||
label = "Load Alembic"
|
||||
representations = ["abc"]
|
||||
order = -10
|
||||
icon = "code-fork"
|
||||
|
|
|
|||
119
colorbleed/plugins/houdini/load/load_camera.py
Normal file
119
colorbleed/plugins/houdini/load/load_camera.py
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
from avalon import api
|
||||
|
||||
from avalon.houdini import pipeline, lib
|
||||
|
||||
|
||||
class CameraLoader(api.Loader):
|
||||
"""Specific loader of Alembic for the avalon.animation family"""
|
||||
|
||||
families = ["colorbleed.camera"]
|
||||
label = "Load Camera (abc)"
|
||||
representations = ["abc"]
|
||||
order = -10
|
||||
|
||||
icon = "code-fork"
|
||||
color = "orange"
|
||||
|
||||
def load(self, context, name=None, namespace=None, data=None):
|
||||
|
||||
import os
|
||||
import hou
|
||||
|
||||
# Format file name, Houdini only wants forward slashes
|
||||
file_path = os.path.normpath(self.fname)
|
||||
file_path = file_path.replace("\\", "/")
|
||||
|
||||
# Get the root node
|
||||
obj = hou.node("/obj")
|
||||
|
||||
# Create a unique name
|
||||
counter = 1
|
||||
asset_name = context["asset"]["name"]
|
||||
|
||||
namespace = namespace if namespace else asset_name
|
||||
formatted = "{}_{}".format(namespace, name) if namespace else name
|
||||
node_name = "{0}_{1:03d}".format(formatted, counter)
|
||||
|
||||
children = lib.children_as_string(hou.node("/obj"))
|
||||
while node_name in children:
|
||||
counter += 1
|
||||
node_name = "{0}_{1:03d}".format(formatted, counter)
|
||||
|
||||
# Create a archive node
|
||||
container = self.create_and_connect(obj, "alembicarchive", node_name)
|
||||
|
||||
# TODO: add FPS of project / asset
|
||||
container.setParms({"fileName": file_path,
|
||||
"channelRef": True})
|
||||
|
||||
# Apply some magic
|
||||
container.parm("buildHierarchy").pressButton()
|
||||
container.moveToGoodPosition()
|
||||
|
||||
# Create an alembic xform node
|
||||
nodes = [container]
|
||||
|
||||
self[:] = nodes
|
||||
|
||||
return pipeline.containerise(node_name,
|
||||
namespace,
|
||||
nodes,
|
||||
context,
|
||||
self.__class__.__name__)
|
||||
|
||||
def update(self, container, representation):
|
||||
|
||||
node = container["node"]
|
||||
|
||||
# Update the file path
|
||||
file_path = api.get_representation_path(representation)
|
||||
file_path = file_path.replace("\\", "/")
|
||||
|
||||
# Update attributes
|
||||
node.setParms({"fileName": file_path,
|
||||
"representation": str(representation["_id"])})
|
||||
|
||||
# Rebuild
|
||||
node.parm("buildHierarchy").pressButton()
|
||||
|
||||
def remove(self, container):
|
||||
|
||||
node = container["node"]
|
||||
node.destroy()
|
||||
|
||||
def create_and_connect(self, node, node_type, name=None):
|
||||
"""Create a node within a node which and connect it to the input
|
||||
|
||||
Args:
|
||||
node(hou.Node): parent of the new node
|
||||
node_type(str) name of the type of node, eg: 'alembic'
|
||||
name(str, Optional): name of the node
|
||||
|
||||
Returns:
|
||||
hou.Node
|
||||
|
||||
"""
|
||||
|
||||
import hou
|
||||
|
||||
try:
|
||||
|
||||
if name:
|
||||
new_node = node.createNode(node_type, node_name=name)
|
||||
else:
|
||||
new_node = node.createNode(node_type)
|
||||
|
||||
new_node.moveToGoodPosition()
|
||||
|
||||
try:
|
||||
input_node = next(i for i in node.allItems() if
|
||||
isinstance(i, hou.SubnetIndirectInput))
|
||||
except StopIteration:
|
||||
return new_node
|
||||
|
||||
new_node.setInput(0, input_node)
|
||||
return new_node
|
||||
|
||||
except Exception:
|
||||
raise RuntimeError("Could not created node type `%s` in node `%s`"
|
||||
% (node_type, node))
|
||||
|
|
@ -3,7 +3,7 @@ import hou
|
|||
import pyblish.api
|
||||
|
||||
|
||||
class CollectMayaCurrentFile(pyblish.api.ContextPlugin):
|
||||
class CollectHoudiniCurrentFile(pyblish.api.ContextPlugin):
|
||||
"""Inject the current working file into context"""
|
||||
|
||||
order = pyblish.api.CollectorOrder - 0.5
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ class CollectInstances(pyblish.api.ContextPlugin):
|
|||
|
||||
"""
|
||||
|
||||
order = pyblish.api.CollectorOrder - 0.01
|
||||
label = "Collect Instances"
|
||||
order = pyblish.api.CollectorOrder
|
||||
hosts = ["houdini"]
|
||||
|
||||
def process(self, context):
|
||||
|
|
@ -51,7 +51,17 @@ class CollectInstances(pyblish.api.ContextPlugin):
|
|||
if "active" in data:
|
||||
data["publish"] = data["active"]
|
||||
|
||||
instance = context.create_instance(data.get("name", node.name()))
|
||||
data.update(self.get_frame_data(node))
|
||||
|
||||
# Create nice name
|
||||
# All nodes in the Outputs graph have the 'Valid Frame Range'
|
||||
# attribute, we check here if any frames are set
|
||||
label = data.get("name", node.name())
|
||||
if "startFrame" in data:
|
||||
frames = "[{startFrame} - {endFrame}]".format(**data)
|
||||
label = "{} {}".format(label, frames)
|
||||
|
||||
instance = context.create_instance(label)
|
||||
|
||||
instance[:] = [node]
|
||||
instance.data.update(data)
|
||||
|
|
@ -66,3 +76,27 @@ class CollectInstances(pyblish.api.ContextPlugin):
|
|||
context[:] = sorted(context, key=sort_by_family)
|
||||
|
||||
return context
|
||||
|
||||
def get_frame_data(self, node):
|
||||
"""Get the frame data: start frame, end frame and steps
|
||||
Args:
|
||||
node(hou.Node)
|
||||
|
||||
Returns:
|
||||
dict
|
||||
|
||||
"""
|
||||
|
||||
data = {}
|
||||
|
||||
if node.parm("trange") is None:
|
||||
return data
|
||||
|
||||
if node.evalParm("trange") == 0:
|
||||
return data
|
||||
|
||||
data["startFrame"] = node.evalParm("f1")
|
||||
data["endFrame"] = node.evalParm("f2")
|
||||
data["steps"] = node.evalParm("f3")
|
||||
|
||||
return data
|
||||
|
|
|
|||
27
colorbleed/plugins/houdini/publish/collect_output_node.py
Normal file
27
colorbleed/plugins/houdini/publish/collect_output_node.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import pyblish.api
|
||||
|
||||
|
||||
class CollectOutputNode(pyblish.api.InstancePlugin):
|
||||
"""Collect the out node which of the instance"""
|
||||
|
||||
order = pyblish.api.CollectorOrder
|
||||
families = ["*"]
|
||||
hosts = ["houdini"]
|
||||
label = "Collect Output Node"
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
import hou
|
||||
|
||||
node = instance[0]
|
||||
|
||||
# Get sop path
|
||||
if node.type().name() == "alembic":
|
||||
sop_path_parm = "sop_path"
|
||||
else:
|
||||
sop_path_parm = "soppath"
|
||||
|
||||
sop_path = node.parm(sop_path_parm).eval()
|
||||
out_node = hou.node(sop_path)
|
||||
|
||||
instance.data["output_node"] = out_node
|
||||
31
colorbleed/plugins/houdini/publish/collection_animation.py
Normal file
31
colorbleed/plugins/houdini/publish/collection_animation.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import pyblish.api
|
||||
|
||||
|
||||
class CollectAnimation(pyblish.api.InstancePlugin):
|
||||
"""Collect the animation data for the data base
|
||||
|
||||
Data collected:
|
||||
- start frame
|
||||
- end frame
|
||||
- nr of steps
|
||||
|
||||
"""
|
||||
|
||||
order = pyblish.api.CollectorOrder
|
||||
families = ["colorbleed.pointcache"]
|
||||
hosts = ["houdini"]
|
||||
label = "Collect Animation"
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
node = instance[0]
|
||||
|
||||
# Get animation parameters for data
|
||||
parameters = {"f1": "startFrame",
|
||||
"f2": "endFrame",
|
||||
"f3": "steps"}
|
||||
|
||||
data = {name: node.parm(par).eval() for par, name in
|
||||
parameters.items()}
|
||||
|
||||
instance.data.update(data)
|
||||
|
|
@ -2,7 +2,6 @@ import os
|
|||
|
||||
import pyblish.api
|
||||
import colorbleed.api
|
||||
from colorbleed.houdini import lib
|
||||
|
||||
|
||||
class ExtractAlembic(colorbleed.api.Extractor):
|
||||
|
|
@ -14,20 +13,19 @@ class ExtractAlembic(colorbleed.api.Extractor):
|
|||
|
||||
def process(self, instance):
|
||||
|
||||
staging_dir = self.staging_dir(instance)
|
||||
|
||||
file_name = "{}.abc".format(instance.data["subset"])
|
||||
tmp_filepath = os.path.join(staging_dir, file_name)
|
||||
|
||||
start_frame = float(instance.data["startFrame"])
|
||||
end_frame = float(instance.data["endFrame"])
|
||||
|
||||
ropnode = instance[0]
|
||||
attributes = {"filename": tmp_filepath,
|
||||
"trange": 2}
|
||||
|
||||
with lib.attribute_values(ropnode, attributes):
|
||||
ropnode.render(frame_range=(start_frame, end_frame, 1))
|
||||
# Get the filename from the filename parameter
|
||||
# `.eval()` will make sure all tokens are resolved
|
||||
output = ropnode.parm("filename").eval()
|
||||
staging_dir = os.path.dirname(output)
|
||||
instance.data["stagingDir"] = staging_dir
|
||||
|
||||
file_name = os.path.basename(output)
|
||||
|
||||
# We run the render
|
||||
self.log.info("Writing alembic '%s' to '%s'" % (file_name, staging_dir))
|
||||
ropnode.render()
|
||||
|
||||
if "files" not in instance.data:
|
||||
instance.data["files"] = []
|
||||
|
|
|
|||
42
colorbleed/plugins/houdini/publish/extract_vdb_cache.py
Normal file
42
colorbleed/plugins/houdini/publish/extract_vdb_cache.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import os
|
||||
import re
|
||||
|
||||
import pyblish.api
|
||||
import colorbleed.api
|
||||
|
||||
|
||||
class ExtractVDBCache(colorbleed.api.Extractor):
|
||||
|
||||
order = pyblish.api.ExtractorOrder + 0.1
|
||||
label = "Extract VDB Cache"
|
||||
families = ["colorbleed.vdbcache"]
|
||||
hosts = ["houdini"]
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
ropnode = instance[0]
|
||||
|
||||
# Get the filename from the filename parameter
|
||||
# `.eval()` will make sure all tokens are resolved
|
||||
output = ropnode.parm("sopoutput").eval()
|
||||
staging_dir = os.path.dirname(output)
|
||||
instance.data["stagingDir"] = staging_dir
|
||||
|
||||
# Replace the 4 digits to match file sequence token '%04d' if we have
|
||||
# a sequence of frames
|
||||
file_name = os.path.basename(output)
|
||||
has_frame = re.match("\w\.(d+)\.vdb", file_name)
|
||||
if has_frame:
|
||||
frame_nr = has_frame.group()
|
||||
file_name.replace(frame_nr, "%04d")
|
||||
|
||||
# We run the render
|
||||
self.log.info(
|
||||
"Starting render: {startFrame} - {endFrame}".format(**instance.data)
|
||||
)
|
||||
ropnode.render()
|
||||
|
||||
if "files" not in instance.data:
|
||||
instance.data["files"] = []
|
||||
|
||||
instance.data["files"].append(file_name)
|
||||
46
colorbleed/plugins/houdini/publish/valiate_vdb_input_node.py
Normal file
46
colorbleed/plugins/houdini/publish/valiate_vdb_input_node.py
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import pyblish.api
|
||||
import colorbleed.api
|
||||
|
||||
|
||||
class ValidateVDBInputNode(pyblish.api.InstancePlugin):
|
||||
"""Validate that the node connected to the output node is of type VDB
|
||||
|
||||
Regardless of the amount of VDBs create the output will need to have an
|
||||
equal amount of VDBs, points, primitives and vertices
|
||||
|
||||
A VDB is an inherited type of Prim, holds the following data:
|
||||
- Primitives: 1
|
||||
- Points: 1
|
||||
- Vertices: 1
|
||||
- VDBs: 1
|
||||
|
||||
"""
|
||||
|
||||
order = colorbleed.api.ValidateContentsOrder + 0.1
|
||||
families = ["colorbleed.vdbcache"]
|
||||
hosts = ["houdini"]
|
||||
label = "Validate Input Node (VDB)"
|
||||
|
||||
def process(self, instance):
|
||||
invalid = self.get_invalid(instance)
|
||||
if invalid:
|
||||
raise RuntimeError("Node connected to the output node is not"
|
||||
"of type VDB!")
|
||||
|
||||
@classmethod
|
||||
def get_invalid(cls, instance):
|
||||
|
||||
node = instance.data["output_node"]
|
||||
|
||||
prims = node.geometry().prims()
|
||||
nr_of_prims = len(prims)
|
||||
|
||||
nr_of_points = len(node.geometry().points())
|
||||
if nr_of_points != nr_of_prims:
|
||||
cls.log.error("The number of primitives and points do not match")
|
||||
return [instance]
|
||||
|
||||
for prim in prims:
|
||||
if prim.numVertices() != 1:
|
||||
cls.log.error("Found primitive with more than 1 vertex!")
|
||||
return [instance]
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
import pyblish.api
|
||||
import colorbleed.api
|
||||
|
||||
|
||||
class ValidateAlembicInputNode(pyblish.api.InstancePlugin):
|
||||
"""Validate that the node connected to the output is correct
|
||||
|
||||
The connected node cannot be of the following types for Alembic:
|
||||
- VDB
|
||||
- Volumne
|
||||
|
||||
"""
|
||||
|
||||
order = colorbleed.api.ValidateContentsOrder + 0.1
|
||||
families = ["colorbleed.pointcache"]
|
||||
hosts = ["houdini"]
|
||||
label = "Validate Input Node (Abc)"
|
||||
|
||||
def process(self, instance):
|
||||
invalid = self.get_invalid(instance)
|
||||
if invalid:
|
||||
raise RuntimeError("Node connected to the output node incorrect")
|
||||
|
||||
@classmethod
|
||||
def get_invalid(cls, instance):
|
||||
|
||||
invalid_nodes = ["VDB", "Volume"]
|
||||
node = instance.data["output_node"]
|
||||
|
||||
prims = node.geometry().prims()
|
||||
|
||||
for prim in prims:
|
||||
prim_type = prim.type().name()
|
||||
if prim_type in invalid_nodes:
|
||||
cls.log.error("Found a primitive which is of type '%s' !"
|
||||
% prim_type)
|
||||
return [instance]
|
||||
|
|
@ -2,7 +2,7 @@ import pyblish.api
|
|||
import colorbleed.api
|
||||
|
||||
|
||||
class ValidatIntermediateDirectoriesChecked(pyblish.api.InstancePlugin):
|
||||
class ValidateIntermediateDirectoriesChecked(pyblish.api.InstancePlugin):
|
||||
"""Validate if node attribute Create intermediate Directories is turned on
|
||||
|
||||
Rules:
|
||||
|
|
|
|||
|
|
@ -29,13 +29,21 @@ class ValidatOutputNodeExists(pyblish.api.InstancePlugin):
|
|||
result = set()
|
||||
|
||||
node = instance[0]
|
||||
sop_path = node.parm("sop_path").eval()
|
||||
if not sop_path.endswith("OUT"):
|
||||
cls.log.error("SOP Path does not end path at output node")
|
||||
result.add(node.path())
|
||||
if node.type().name() == "alembic":
|
||||
soppath_parm = "sop_path"
|
||||
else:
|
||||
# Fall back to geometry node
|
||||
soppath_parm = "soppath"
|
||||
|
||||
if hou.node(sop_path) is None:
|
||||
sop_path = node.parm(soppath_parm).eval()
|
||||
output_node = hou.node(sop_path)
|
||||
|
||||
if output_node is None:
|
||||
cls.log.error("Node at '%s' does not exist" % sop_path)
|
||||
result.add(node.path())
|
||||
|
||||
if output_node.type().name() != "output":
|
||||
cls.log.error("SOP Path does not end path at output node")
|
||||
result.add(node.path())
|
||||
|
||||
return result
|
||||
|
|
|
|||
43
colorbleed/plugins/houdini/publish/validate_output_node.py
Normal file
43
colorbleed/plugins/houdini/publish/validate_output_node.py
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import pyblish.api
|
||||
|
||||
|
||||
class ValidateOutputNode(pyblish.api.InstancePlugin):
|
||||
"""Validate if output node:
|
||||
- exists
|
||||
- is of type 'output'
|
||||
- has an input"""
|
||||
|
||||
order = pyblish.api.ValidatorOrder
|
||||
families = ["*"]
|
||||
hosts = ["houdini"]
|
||||
label = "Validate Output Node"
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
invalid = self.get_invalid(instance)
|
||||
if invalid:
|
||||
raise RuntimeError("Output node(s) `%s` are incorrect" % invalid)
|
||||
|
||||
@classmethod
|
||||
def get_invalid(cls, instance):
|
||||
|
||||
output_node = instance.data["output_node"]
|
||||
|
||||
if output_node is None:
|
||||
node = instance[0]
|
||||
cls.log.error("Output node at '%s' does not exist, see source" %
|
||||
node.path())
|
||||
|
||||
return node.path()
|
||||
|
||||
# Check if type is correct
|
||||
if output_node.type().name() != "output":
|
||||
cls.log.error("Output node `%s` is not if type `output`" %
|
||||
output_node.path())
|
||||
return output_node.path()
|
||||
|
||||
# Check if node has incoming connections
|
||||
if not output_node.inputConnections():
|
||||
cls.log.error("Output node `%s` has no incoming connections"
|
||||
% output_node.path())
|
||||
return output_node.path()
|
||||
|
|
@ -2,7 +2,7 @@ import colorbleed.maya.plugin
|
|||
|
||||
|
||||
class AbcLoader(colorbleed.maya.plugin.ReferenceLoader):
|
||||
"""Specific loader of Alembic for the avalon.animation family"""
|
||||
"""Specific loader of Alembic for the colorbleed.animation family"""
|
||||
|
||||
families = ["colorbleed.animation",
|
||||
"colorbleed.pointcache"]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import colorbleed.maya.plugin
|
|||
|
||||
|
||||
class CameraLoader(colorbleed.maya.plugin.ReferenceLoader):
|
||||
"""Specific loader of Alembic for the avalon.animation family"""
|
||||
"""Specific loader of Alembic for the colorbleed.camera family"""
|
||||
|
||||
families = ["colorbleed.camera"]
|
||||
label = "Reference camera"
|
||||
|
|
|
|||
64
colorbleed/plugins/maya/load/load_vdb_to_vray.py
Normal file
64
colorbleed/plugins/maya/load/load_vdb_to_vray.py
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
from avalon import api
|
||||
# import colorbleed.maya.plugin
|
||||
|
||||
|
||||
class LoadVDBtoVRay(api.Loader):
|
||||
|
||||
families = ["colorbleed.vdbcache"]
|
||||
representations = ["vdb"]
|
||||
|
||||
name = "Load VDB to VRay"
|
||||
icon = "cloud"
|
||||
color = "orange"
|
||||
|
||||
def load(self, context, name, namespace, data):
|
||||
|
||||
# import pprint
|
||||
from maya import cmds
|
||||
import avalon.maya.lib as lib
|
||||
from avalon.maya.pipeline import containerise
|
||||
|
||||
# Check if viewport drawing engine is Open GL Core (compat)
|
||||
render_engine = None
|
||||
compatible = "OpenGLCoreProfileCompat"
|
||||
if cmds.optionVar(exists="vp2RenderingEngine"):
|
||||
render_engine = cmds.optionVar(query="vp2RenderingEngine")
|
||||
|
||||
if not render_engine or render_engine != compatible:
|
||||
raise RuntimeError("Current scene's settings are incompatible."
|
||||
"See Preferences > Display > Viewport 2.0 to "
|
||||
"set the render engine to '%s'" % compatible)
|
||||
|
||||
asset = context['asset']
|
||||
version = context["version"]
|
||||
|
||||
asset_name = asset["name"]
|
||||
namespace = namespace or lib.unique_namespace(
|
||||
asset_name + "_",
|
||||
prefix="_" if asset_name[0].isdigit() else "",
|
||||
suffix="_",
|
||||
)
|
||||
|
||||
# Root group
|
||||
label = "{}:{}".format(namespace, name)
|
||||
root = cmds.group(name=label, empty=True)
|
||||
|
||||
# Create VR
|
||||
grid_node = cmds.createNode("VRayVolumeGrid",
|
||||
name="{}VVGShape".format(label),
|
||||
parent=root)
|
||||
|
||||
# Set attributes
|
||||
cmds.setAttr("{}.inFile".format(grid_node), self.fname, type="string")
|
||||
cmds.setAttr("{}.inReadOffset".format(grid_node),
|
||||
version["startFrames"])
|
||||
|
||||
nodes = [root, grid_node]
|
||||
self[:] = nodes
|
||||
|
||||
return containerise(
|
||||
name=name,
|
||||
namespace=namespace,
|
||||
nodes=nodes,
|
||||
context=context,
|
||||
loader=self.__class__.__name__)
|
||||
Loading…
Add table
Add a link
Reference in a new issue