Beispiel #1
0
def renderWindowSerializer(parent, instance, objId, context, depth):
    dependencies = []
    rendererIds = []

    rendererCollection = instance.GetRenderers()
    for rIdx in range(rendererCollection.GetNumberOfItems()):
        # Grab the next vtkRenderer
        renderer = rendererCollection.GetItemAsObject(rIdx)
        rendererId = getReferenceId(renderer)
        rendererInstance = serializeInstance(
            instance, renderer, rendererId, context, depth + 1
        )
        if rendererInstance:
            dependencies.append(rendererInstance)
            rendererIds.append(rendererId)

    calls = context.buildDependencyCallList(
        objId, rendererIds, "addRenderer", "removeRenderer"
    )

    return {
        "parent": getReferenceId(parent),
        "id": objId,
        "type": class_name(instance),
        "properties": {"numberOfLayers": instance.GetNumberOfLayers()},
        "dependencies": dependencies,
        "calls": calls,
        "mtime": instance.GetMTime(),
    }
Beispiel #2
0
def propertySerializer(parent, propObj, propObjId, context, depth):
    representation = (
        propObj.GetRepresentation() if hasattr(propObj, "GetRepresentation") else 2
    )
    colorToUse = (
        propObj.GetDiffuseColor() if hasattr(propObj, "GetDiffuseColor") else [1, 1, 1]
    )
    if representation == 1 and hasattr(propObj, "GetColor"):
        colorToUse = propObj.GetColor()

    return {
        "parent": getReferenceId(parent),
        "id": propObjId,
        "type": class_name(propObj),
        "properties": {
            "representation": representation,
            "diffuseColor": colorToUse,
            "color": propObj.GetColor(),
            "ambientColor": propObj.GetAmbientColor(),
            "specularColor": propObj.GetSpecularColor(),
            "edgeColor": propObj.GetEdgeColor(),
            "ambient": propObj.GetAmbient(),
            "diffuse": propObj.GetDiffuse(),
            "specular": propObj.GetSpecular(),
            "specularPower": propObj.GetSpecularPower(),
            "opacity": propObj.GetOpacity(),
            "interpolation": propObj.GetInterpolation(),
            "edgeVisibility": 1 if propObj.GetEdgeVisibility() else 0,
            "backfaceCulling": 1 if propObj.GetBackfaceCulling() else 0,
            "frontfaceCulling": 1 if propObj.GetFrontfaceCulling() else 0,
            "pointSize": propObj.GetPointSize(),
            "lineWidth": propObj.GetLineWidth(),
            "lighting": 1 if propObj.GetLighting() else 0,
        },
    }
Beispiel #3
0
def colorTransferFunctionSerializer(parent, instance, objId, context, depth):
    nodes = []

    for i in range(instance.GetSize()):
        # x, r, g, b, midpoint, sharpness
        node = [0, 0, 0, 0, 0, 0]
        instance.GetNodeValue(i, node)
        nodes.append(node)

    return {
        "parent": getReferenceId(parent),
        "id": objId,
        "type": class_name(instance),
        "properties": {
            "clamping": 1 if instance.GetClamping() else 0,
            "colorSpace": instance.GetColorSpace(),
            "hSVWrap": 1 if instance.GetHSVWrap() else 0,
            # 'nanColor': instance.GetNanColor(),                  # Breaks client
            # 'belowRangeColor': instance.GetBelowRangeColor(),    # Breaks client
            # 'aboveRangeColor': instance.GetAboveRangeColor(),    # Breaks client
            # 'useAboveRangeColor': 1 if instance.GetUseAboveRangeColor() else 0,
            # 'useBelowRangeColor': 1 if instance.GetUseBelowRangeColor() else 0,
            "allowDuplicateScalars": 1 if instance.GetAllowDuplicateScalars() else 0,
            "alpha": instance.GetAlpha(),
            "vectorComponent": instance.GetVectorComponent(),
            "vectorSize": instance.GetVectorSize(),
            "vectorMode": instance.GetVectorMode(),
            "indexedLookup": instance.GetIndexedLookup(),
            "nodes": nodes,
        },
    }
Beispiel #4
0
def volumePropertySerializer(parent, propObj, propObjId, context, depth):
    calls = []
    dependencies = []

    # Color handling
    lut = propObj.GetRGBTransferFunction()
    if lut:
        lookupTableId = getReferenceId(lut)
        lookupTableInstance = serializeInstance(
            propObj, lut, lookupTableId, context, depth + 1
        )

        if lookupTableInstance:
            dependencies.append(lookupTableInstance)
            calls.append(["setRGBTransferFunction", [0, wrapId(lookupTableId)]])

    # Piecewise handling
    pwf = propObj.GetScalarOpacity()
    if pwf:
        pwfId = getReferenceId(pwf)
        pwfInstance = serializeInstance(
            propObj, pwf, pwfId, context, depth + 1
        )

        if pwfInstance:
            dependencies.append(pwfInstance)
            calls.append(["setScalarOpacity", [0, wrapId(pwfId)]])

    return {
        "parent": getReferenceId(parent),
        "id": propObjId,
        "type": class_name(propObj),
        "properties": {
            "independentComponents": propObj.GetIndependentComponents(),
            "interpolationType": propObj.GetInterpolationType(),
            "shade": propObj.GetShade(),
            "ambient": propObj.GetAmbient(),
            "diffuse": propObj.GetDiffuse(),
            "specular": propObj.GetSpecular(),
            "specularPower": propObj.GetSpecularPower(),
            # "useLabelOutline": propObj.GetUseLabelOutline(),
            # "labelOutlineThickness": propObj.GetLabelOutlineThickness(),
        },
        "calls": calls,
        "dependencies": dependencies,
    }
Beispiel #5
0
def cameraSerializer(parent, instance, objId, context, depth):
    return {
        "parent": getReferenceId(parent),
        "id": objId,
        "type": class_name(instance),
        "properties": {
            "focalPoint": instance.GetFocalPoint(),
            "position": instance.GetPosition(),
            "viewUp": instance.GetViewUp(),
            "clippingRange": instance.GetClippingRange(),
        },
    }
Beispiel #6
0
def polydataSerializer(parent, dataset, datasetId, context, depth, requested_fields = ["Normals", "TCoords"]):
    if dataset and dataset.GetPoints():
        properties = {}

        # Points
        points = getArrayDescription(dataset.GetPoints().GetData(), context)
        points["vtkClass"] = "vtkPoints"
        properties["points"] = points

        # Verts
        if dataset.GetVerts() and dataset.GetVerts().GetData().GetNumberOfTuples() > 0:
            _verts = getArrayDescription(dataset.GetVerts().GetData(), context)
            properties["verts"] = _verts
            properties["verts"]["vtkClass"] = "vtkCellArray"

        # Lines
        if dataset.GetLines() and dataset.GetLines().GetData().GetNumberOfTuples() > 0:
            _lines = getArrayDescription(dataset.GetLines().GetData(), context)
            properties["lines"] = _lines
            properties["lines"]["vtkClass"] = "vtkCellArray"

        # Polys
        if dataset.GetPolys() and dataset.GetPolys().GetData().GetNumberOfTuples() > 0:
            _polys = getArrayDescription(dataset.GetPolys().GetData(), context)
            properties["polys"] = _polys
            properties["polys"]["vtkClass"] = "vtkCellArray"

        # Strips
        if (
            dataset.GetStrips()
            and dataset.GetStrips().GetData().GetNumberOfTuples() > 0
        ):
            _strips = getArrayDescription(dataset.GetStrips().GetData(), context)
            properties["strips"] = _strips
            properties["strips"]["vtkClass"] = "vtkCellArray"

        # Fields
        properties["fields"] = []
        extractRequiredFields(properties["fields"], parent, dataset, context, requested_fields)

        return {
            "parent": getReferenceId(parent),
            "id": datasetId,
            "type": class_name(dataset),
            "properties": properties,
        }

    if context.debugAll:
        print("This dataset has no points!")
    return None
Beispiel #7
0
def digest(array):
    objId = getReferenceId(array)

    record = None
    if objId in dataArrayShaMapping:
        record = dataArrayShaMapping[objId]

    if record and record["mtime"] == array.GetMTime():
        return record["sha"]

    record = {"sha": hashDataArray(array), "mtime": array.GetMTime()}

    dataArrayShaMapping[objId] = record
    return record["sha"]
Beispiel #8
0
def genericVolumeMapperSerializer(parent, mapper, mapperId, context, depth):
    # This kind of mapper requires us to get 2 items: input data and lookup
    # table
    dataObject = None
    dataObjectInstance = None
    lookupTableInstance = None
    calls = []
    dependencies = []

    if hasattr(mapper, "GetInputDataObject"):
        mapper.GetInputAlgorithm().Update()
        dataObject = mapper.GetInputDataObject(0, 0)
    else:
        if context.debugAll:
            print("This mapper does not have GetInputDataObject method")

    if dataObject:
        dataObjectId = "%s-dataset" % mapperId
        dataObjectInstance = serializeInstance(
            mapper, dataObject, dataObjectId, context, depth + 1
        )

        if dataObjectInstance:
            dependencies.append(dataObjectInstance)
            calls.append(["setInputData", [wrapId(dataObjectId)]])

    if dataObjectInstance:
        return {
            "parent": getReferenceId(parent),
            "id": mapperId,
            "type": class_name(mapper),
            "properties": {
                # VolumeMapper
                "sampleDistance": mapper.GetSampleDistance(),
                "imageSampleDistance": mapper.GetImageSampleDistance(),
                # "maximumSamplesPerRay": mapper.GetMaximumSamplesPerRay(),
                "autoAdjustSampleDistances": mapper.GetAutoAdjustSampleDistances(),
                "blendMode": mapper.GetBlendMode(),
                # "ipScalarRange": mapper.GetIpScalarRange(),
                # "filterMode": mapper.GetFilterMode(),
                # "preferSizeOverAccuracy": mapper.Get(),
            },
            "calls": calls,
            "dependencies": dependencies,
        }

    return None
Beispiel #9
0
def lookupTableSerializer(parent, lookupTable, lookupTableId, context, depth):
    # No children in this case, so no additions to bindings and return empty list
    # But we do need to add instance

    lookupTableRange = lookupTable.GetRange()

    lookupTableHueRange = [0.5, 0]
    if hasattr(lookupTable, "GetHueRange"):
        try:
            lookupTable.GetHueRange(lookupTableHueRange)
        except Exception as inst:
            pass

    lutSatRange = lookupTable.GetSaturationRange()
    lutAlphaRange = lookupTable.GetAlphaRange()

    return {
        "parent": getReferenceId(parent),
        "id": lookupTableId,
        "type": class_name(lookupTable),
        "properties": {
            "numberOfColors": lookupTable.GetNumberOfColors(),
            "valueRange": lookupTableRange,
            "hueRange": lookupTableHueRange,
            # 'alphaRange': lutAlphaRange,  # Causes weird rendering artifacts on client
            "saturationRange": lutSatRange,
            "nanColor": lookupTable.GetNanColor(),
            "belowRangeColor": lookupTable.GetBelowRangeColor(),
            "aboveRangeColor": lookupTable.GetAboveRangeColor(),
            "useAboveRangeColor": True
            if lookupTable.GetUseAboveRangeColor()
            else False,
            "useBelowRangeColor": True
            if lookupTable.GetUseBelowRangeColor()
            else False,
            "alpha": lookupTable.GetAlpha(),
            "vectorSize": lookupTable.GetVectorSize(),
            "vectorComponent": lookupTable.GetVectorComponent(),
            "vectorMode": lookupTable.GetVectorMode(),
            "indexedLookup": lookupTable.GetIndexedLookup(),
        },
    }
Beispiel #10
0
def pwfSerializer(parent, instance, objId, context, depth):
    nodes = []

    for i in range(instance.GetSize()):
        # x, y, midpoint, sharpness
        node = [0, 0, 0, 0]
        instance.GetNodeValue(i, node)
        nodes.append(node)

    return {
        "parent": getReferenceId(parent),
        "id": objId,
        "type": class_name(instance),
        "properties": {
            "range": list(instance.GetRange()),
            "clamping": instance.GetClamping(),
            "allowDuplicateScalars": instance.GetAllowDuplicateScalars(),
            "nodes": nodes,
        },
    }
Beispiel #11
0
def lightSerializer(parent, instance, objId, context, depth):
    return {
        "parent": getReferenceId(parent),
        "id": objId,
        "type": class_name(instance),
        "properties": {
            # 'specularColor': instance.GetSpecularColor(),
            # 'ambientColor': instance.GetAmbientColor(),
            "switch": instance.GetSwitch(),
            "intensity": instance.GetIntensity(),
            "color": instance.GetDiffuseColor(),
            "position": instance.GetPosition(),
            "focalPoint": instance.GetFocalPoint(),
            "positional": instance.GetPositional(),
            "exponent": instance.GetExponent(),
            "coneAngle": instance.GetConeAngle(),
            "attenuationValues": instance.GetAttenuationValues(),
            "lightType": lightTypeToString(instance.GetLightType()),
            "shadowAttenuation": instance.GetShadowAttenuation(),
        },
    }
Beispiel #12
0
def imagedataSerializer(parent, dataset, datasetId, context, depth, requested_fields = ["Normals", "TCoords"]):
    if hasattr(dataset, "GetDirectionMatrix"):
        direction = [dataset.GetDirectionMatrix().GetElement(0, i) for i in range(9)]
    else:
        direction = [1, 0, 0, 0, 1, 0, 0, 0, 1]

    # Extract dataset fields
    fields = []
    extractRequiredFields(fields, parent, dataset, context, "*")

    return {
        "parent": getReferenceId(parent),
        "id": datasetId,
        "type": class_name(dataset),
        "properties": {
            "spacing": dataset.GetSpacing(),
            "origin": dataset.GetOrigin(),
            "dimensions": dataset.GetDimensions(),
            "direction": direction,
            "fields": fields,
        },
    }
Beispiel #13
0
def textureSerializer(parent, texture, textureId, context, depth):
    # This kind of mapper requires us to get 2 items: input data and lookup
    # table
    dataObject = None
    dataObjectInstance = None
    calls = []
    dependencies = []

    if hasattr(texture, "GetInput"):
        dataObject = texture.GetInput()
    else:
        if context.debugAll:
            print("This texture does not have GetInput method")

    if dataObject:
        dataObjectId = "%s-texture" % textureId
        dataObjectInstance = serializeInstance(
            texture, dataObject, dataObjectId, context, depth + 1
        )
        if dataObjectInstance:
            dependencies.append(dataObjectInstance)
            calls.append(["setInputData", [wrapId(dataObjectId)]])

    if dataObjectInstance:
        return {
            "parent": getReferenceId(parent),
            "id": textureId,
            "type": "vtkTexture",
            "properties": {
                "interpolate": texture.GetInterpolate(),
                "repeat": texture.GetRepeat(),
                "edgeClamp": texture.GetEdgeClamp(),
            },
            "calls": calls,
            "dependencies": dependencies,
        }

    return None
Beispiel #14
0
def genericVolumeSerializer(parent, actor, actorId, context, depth):
    # This kind of actor has two "children" of interest, a property and a
    # mapper
    actorVisibility = actor.GetVisibility()
    mapperInstance = None
    propertyInstance = None
    calls = []
    dependencies = []

    if actorVisibility:
        mapper = None
        if not hasattr(actor, "GetMapper"):
            if context.debugAll:
                print("This actor does not have a GetMapper method")
        else:
            mapper = actor.GetMapper()

        if mapper:
            mapperId = getReferenceId(mapper)
            mapperInstance = serializeInstance(
                actor, mapper, mapperId, context, depth + 1
            )
            if mapperInstance:
                dependencies.append(mapperInstance)
                calls.append(["setMapper", [wrapId(mapperId)]])

        prop = None
        if hasattr(actor, "GetProperty"):
            prop = actor.GetProperty()
        else:
            if context.debugAll:
                print("This actor does not have a GetProperty method")

        if prop:
            propId = getReferenceId(prop)
            propertyInstance = serializeInstance(
                actor, prop, propId, context, depth + 1
            )
            if propertyInstance:
                dependencies.append(propertyInstance)
                calls.append(["setProperty", [wrapId(propId)]])

    if actorVisibility == 0 or (mapperInstance and propertyInstance):
        return {
            "parent": getReferenceId(parent),
            "id": actorId,
            "type": class_name(actor),
            "properties": {
                # vtkProp
                "visibility": actorVisibility,
                "pickable": actor.GetPickable(),
                "dragable": actor.GetDragable(),
                "useBounds": actor.GetUseBounds(),
                # vtkProp3D
                "origin": actor.GetOrigin(),
                "position": actor.GetPosition(),
                "scale": actor.GetScale(),
            },
            "calls": calls,
            "dependencies": dependencies,
        }

    return None
Beispiel #15
0
def cubeAxesSerializer(parent, actor, actorId, context, depth):
    """
    Possible add-on properties for vtk.js:
        gridLines: True,
        axisLabels: None,
        axisTitlePixelOffset: 35.0,
        axisTextStyle: {
            fontColor: 'white',
            fontStyle: 'normal',
            fontSize: 18,
            fontFamily: 'serif',
        },
        tickLabelPixelOffset: 12.0,
        tickTextStyle: {
            fontColor: 'white',
            fontStyle: 'normal',
            fontSize: 14,
            fontFamily: 'serif',
        },
    """
    axisLabels = ["", "", ""]
    if actor.GetXAxisLabelVisibility():
        axisLabels[0] = actor.GetXTitle()
    if actor.GetYAxisLabelVisibility():
        axisLabels[1] = actor.GetYTitle()
    if actor.GetZAxisLabelVisibility():
        axisLabels[2] = actor.GetZTitle()

    return {
        "parent": getReferenceId(parent),
        "id": actorId,
        "type": "vtkCubeAxesActor",
        "properties": {
            # vtkProp
            "visibility": actor.GetVisibility(),
            "pickable": actor.GetPickable(),
            "dragable": actor.GetDragable(),
            "useBounds": actor.GetUseBounds(),
            # vtkProp3D
            "origin": actor.GetOrigin(),
            "position": actor.GetPosition(),
            "scale": actor.GetScale(),
            # vtkActor
            "forceOpaque": actor.GetForceOpaque(),
            "forceTranslucent": actor.GetForceTranslucent(),
            # vtkCubeAxesActor
            "dataBounds": actor.GetBounds(),
            "faceVisibilityAngle": 8,
            "gridLines": True,
            "axisLabels": axisLabels,
            "axisTitlePixelOffset": 35.0,
            "axisTextStyle": {
                "fontColor": "white",
                "fontStyle": "normal",
                "fontSize": 18,
                "fontFamily": "serif",
            },
            "tickLabelPixelOffset": 12.0,
            "tickTextStyle": {
                "fontColor": "white",
                "fontStyle": "normal",
                "fontSize": 14,
                "fontFamily": "serif",
            },
        },
        "calls": [["setCamera", [wrapId(getReferenceId(actor.GetCamera()))]]],
        "dependencies": [],
    }
Beispiel #16
0
def scalarBarActorSerializer(parent, actor, actorId, context, depth):
    dependencies = []
    calls = []
    lut = actor.GetLookupTable()
    if not lut:
        return None

    lutId = getReferenceId(lut)
    lutInstance = serializeInstance(actor, lut, lutId, context, depth + 1)
    if not lutInstance:
        return None

    dependencies.append(lutInstance)
    calls.append(["setScalarsToColors", [wrapId(lutId)]])

    prop = None
    if hasattr(actor, "GetProperty"):
        prop = actor.GetProperty()
    else:
        if context.debugAll:
            print("This scalarBarActor does not have a GetProperty method")

        if prop:
            propId = getReferenceId(prop)
            propertyInstance = serializeInstance(
                actor, prop, propId, context, depth + 1
            )
            if propertyInstance:
                dependencies.append(propertyInstance)
                calls.append(["setProperty", [wrapId(propId)]])

    axisLabel = actor.GetTitle()
    width = actor.GetWidth()
    height = actor.GetHeight()

    # axisTitlePixelOffset = actor.GetTextPad()
    # position = actor.GetPosition()
    # position2 = actor.GetPosition2()
    # print(f'axisTitlePixelOffset: {axisTitlePixelOffset}')
    # print(f'axisLabel: {axisLabel}')
    # print(f'width: {width}')
    # print(f'height: {height}')
    # print(f'position: {position}')
    # print(f'position2: {position2}')

    return {
        "parent": getReferenceId(parent),
        "id": actorId,
        "type": "vtkScalarBarActor",
        "properties": {
            # vtkProp
            "visibility": actor.GetVisibility(),
            "pickable": actor.GetPickable(),
            "dragable": actor.GetDragable(),
            "useBounds": actor.GetUseBounds(),
            # vtkActor2D
            # "position": actor.GetPosition(),
            # "position2": actor.GetPosition2(),
            # "width": actor.GetWidth(),
            # "height": actor.GetHeight(),
            # vtkScalarBarActor
            "automated": True,
            "axisLabel": axisLabel,
            # 'barPosition': [0, 0],
            # 'barSize': [0, 0],
            "boxPosition": [0.88, -0.92],
            "boxSize": [width, height],
            "axisTitlePixelOffset": 36.0,
            "axisTextStyle": {
                "fontColor": "white",
                "fontStyle": "normal",
                "fontSize": 18,
                "fontFamily": "serif",
            },
            "tickLabelPixelOffset": 14.0,
            "tickTextStyle": {
                "fontColor": "white",
                "fontStyle": "normal",
                "fontSize": 14,
                "fontFamily": "serif",
            },
        },
        "calls": calls,
        "dependencies": dependencies,
    }
Beispiel #17
0
def genericMapperSerializer(parent, mapper, mapperId, context, depth):
    # This kind of mapper requires us to get 2 items: input data and lookup
    # table
    dataObject = None
    dataObjectInstance = None
    lookupTableInstance = None
    calls = []
    dependencies = []

    if hasattr(mapper, "GetInputDataObject"):
        mapper.GetInputAlgorithm().Update()
        dataObject = mapper.GetInputDataObject(0, 0)
    else:
        if context.debugAll:
            print("This mapper does not have GetInputDataObject method")

    if dataObject:
        dataObjectId = "%s-dataset" % mapperId
        dataObjectInstance = serializeInstance(
            mapper, dataObject, dataObjectId, context, depth + 1
        )

        if dataObjectInstance:
            dependencies.append(dataObjectInstance)
            calls.append(["setInputData", [wrapId(dataObjectId)]])

    lookupTable = None

    if hasattr(mapper, "GetLookupTable"):
        lookupTable = mapper.GetLookupTable()
    else:
        if context.debugAll:
            print("This mapper does not have GetLookupTable method")

    if lookupTable:
        lookupTableId = getReferenceId(lookupTable)
        lookupTableInstance = serializeInstance(
            mapper, lookupTable, lookupTableId, context, depth + 1
        )
        if lookupTableInstance:
            dependencies.append(lookupTableInstance)
            calls.append(["setLookupTable", [wrapId(lookupTableId)]])

    if dataObjectInstance:
        colorArrayName = (
            mapper.GetArrayName()
            if mapper.GetArrayAccessMode() == 1
            else mapper.GetArrayId()
        )
        return {
            "parent": getReferenceId(parent),
            "id": mapperId,
            "type": class_name(mapper),
            "properties": {
                "resolveCoincidentTopology": mapper.GetResolveCoincidentTopology(),
                "renderTime": mapper.GetRenderTime(),
                "arrayAccessMode": mapper.GetArrayAccessMode(),
                "scalarRange": mapper.GetScalarRange(),
                "useLookupTableScalarRange": 1
                if mapper.GetUseLookupTableScalarRange()
                else 0,
                "scalarVisibility": mapper.GetScalarVisibility(),
                "colorByArrayName": colorArrayName,
                "colorMode": mapper.GetColorMode(),
                "scalarMode": mapper.GetScalarMode(),
                "interpolateScalarsBeforeMapping": 1
                if mapper.GetInterpolateScalarsBeforeMapping()
                else 0,
            },
            "calls": calls,
            "dependencies": dependencies,
        }

    return None
Beispiel #18
0
def rendererSerializer(parent, instance, objId, context, depth):
    dependencies = []
    viewPropIds = []
    lightsIds = []
    calls = []

    # Camera
    camera = instance.GetActiveCamera()
    cameraId = getReferenceId(camera)
    cameraInstance = serializeInstance(instance, camera, cameraId, context, depth + 1)
    if cameraInstance:
        dependencies.append(cameraInstance)
        calls.append(["setActiveCamera", [wrapId(cameraId)]])

    # View prop as representation containers
    viewPropCollection = instance.GetViewProps()
    for rpIdx in range(viewPropCollection.GetNumberOfItems()):
        viewProp = viewPropCollection.GetItemAsObject(rpIdx)
        viewPropId = getReferenceId(viewProp)

        viewPropInstance = serializeInstance(
            instance, viewProp, viewPropId, context, depth + 1
        )
        if viewPropInstance:
            dependencies.append(viewPropInstance)
            viewPropIds.append(viewPropId)

    calls += context.buildDependencyCallList(
        "%s-props" % objId, viewPropIds, "addViewProp", "removeViewProp"
    )

    # Lights
    lightCollection = instance.GetLights()
    for lightIdx in range(lightCollection.GetNumberOfItems()):
        light = lightCollection.GetItemAsObject(lightIdx)
        lightId = getReferenceId(light)

        lightInstance = serializeInstance(instance, light, lightId, context, depth + 1)
        if lightInstance:
            dependencies.append(lightInstance)
            lightsIds.append(lightId)

    calls += context.buildDependencyCallList(
        "%s-lights" % objId, lightsIds, "addLight", "removeLight"
    )

    if len(dependencies) > 1:
        return {
            "parent": getReferenceId(parent),
            "id": objId,
            "type": class_name(instance),
            "properties": {
                "background": instance.GetBackground(),
                "background2": instance.GetBackground2(),
                "viewport": instance.GetViewport(),
                # These commented properties do not yet have real setters in vtk.js
                # 'gradientBackground': instance.GetGradientBackground(),
                # 'aspect': instance.GetAspect(),
                # 'pixelAspect': instance.GetPixelAspect(),
                # 'ambient': instance.GetAmbient(),
                "twoSidedLighting": instance.GetTwoSidedLighting(),
                "lightFollowCamera": instance.GetLightFollowCamera(),
                "layer": instance.GetLayer(),
                "preserveColorBuffer": instance.GetPreserveColorBuffer(),
                "preserveDepthBuffer": instance.GetPreserveDepthBuffer(),
                "nearClippingPlaneTolerance": instance.GetNearClippingPlaneTolerance(),
                "clippingRangeExpansion": instance.GetClippingRangeExpansion(),
                "useShadows": instance.GetUseShadows(),
                "useDepthPeeling": instance.GetUseDepthPeeling(),
                "occlusionRatio": instance.GetOcclusionRatio(),
                "maximumNumberOfPeels": instance.GetMaximumNumberOfPeels(),
                "interactive": instance.GetInteractive(),
            },
            "dependencies": dependencies,
            "calls": calls,
        }

    return None