// Aqsis
// Copyright (C) 2001, Paul C. Gregory and the other authors and contributors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
// * Neither the name of the software's owners nor the names of its
//   contributors may be used to endorse or promote products derived from this
//   software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// (This is the New BSD license)

/// \file
/// \brief A "tee" junction in the filter pipeline.
/// \author Chris Foster [chris42f (at) g mail (d0t) com]

#include <aqsis/riutil/ricxx_filter.h>
#include <aqsis/riutil/ribwriter.h>

#include <iostream>

#include <boost/scoped_ptr.hpp>

namespace Aqsis {

/// Tee junction in a filter pipeline
///
/// This filter creates a "tee" junction in the filter pipeline, so that the
/// the output goes to both of two interface objects.
class TeeFilter : public Ri::Filter
{
    private:
        Ri::Renderer& m_branch;
    public:
        TeeFilter(Ri::Renderer& branch)
            : m_branch(branch)
        { }

        virtual RtVoid ArchiveRecord(RtConstToken type, const char* string)
        {
            m_branch.ArchiveRecord(type, string);
            nextFilter().ArchiveRecord(type, string);
        }

        // Code generator for autogenerated method declarations
        /*[[[cog
        from codegenutils import *
        from Cheetah.Template import Template

        riXml = parseXml(riXmlPath)

        methodTemplate = '''
        virtual $riCxxMethodDecl($proc)
        {
            #if $procName.endswith('End'):
            nextFilter().${procName}(${', '.join($wrapperCallArgList($proc))});
            m_branch.${procName}(${', '.join($wrapperCallArgList($proc))});
            #else
            m_branch.${procName}(${', '.join($wrapperCallArgList($proc))});
            nextFilter().${procName}(${', '.join($wrapperCallArgList($proc))});
            #end if
        }'''

        for proc in riXml.findall('Procedures/Procedure'):
            if proc.findall('Rib'):
                procName = proc.findtext('Name')
                cog.out(str(Template(methodTemplate, searchList=locals())))
        ]]]*/

        virtual RtVoid Declare(RtConstString name, RtConstString declaration)
        {
            m_branch.Declare(name, declaration);
            nextFilter().Declare(name, declaration);
        }
        virtual RtVoid FrameBegin(RtInt number)
        {
            m_branch.FrameBegin(number);
            nextFilter().FrameBegin(number);
        }
        virtual RtVoid FrameEnd()
        {
            nextFilter().FrameEnd();
            m_branch.FrameEnd();
        }
        virtual RtVoid WorldBegin()
        {
            m_branch.WorldBegin();
            nextFilter().WorldBegin();
        }
        virtual RtVoid WorldEnd()
        {
            nextFilter().WorldEnd();
            m_branch.WorldEnd();
        }
        virtual RtVoid IfBegin(RtConstString condition)
        {
            m_branch.IfBegin(condition);
            nextFilter().IfBegin(condition);
        }
        virtual RtVoid ElseIf(RtConstString condition)
        {
            m_branch.ElseIf(condition);
            nextFilter().ElseIf(condition);
        }
        virtual RtVoid Else()
        {
            m_branch.Else();
            nextFilter().Else();
        }
        virtual RtVoid IfEnd()
        {
            nextFilter().IfEnd();
            m_branch.IfEnd();
        }
        virtual RtVoid Format(RtInt xresolution, RtInt yresolution, RtFloat pixelaspectratio)
        {
            m_branch.Format(xresolution, yresolution, pixelaspectratio);
            nextFilter().Format(xresolution, yresolution, pixelaspectratio);
        }
        virtual RtVoid FrameAspectRatio(RtFloat frameratio)
        {
            m_branch.FrameAspectRatio(frameratio);
            nextFilter().FrameAspectRatio(frameratio);
        }
        virtual RtVoid ScreenWindow(RtFloat left, RtFloat right, RtFloat bottom, RtFloat top)
        {
            m_branch.ScreenWindow(left, right, bottom, top);
            nextFilter().ScreenWindow(left, right, bottom, top);
        }
        virtual RtVoid CropWindow(RtFloat xmin, RtFloat xmax, RtFloat ymin, RtFloat ymax)
        {
            m_branch.CropWindow(xmin, xmax, ymin, ymax);
            nextFilter().CropWindow(xmin, xmax, ymin, ymax);
        }
        virtual RtVoid Projection(RtConstToken name, const ParamList& pList)
        {
            m_branch.Projection(name, pList);
            nextFilter().Projection(name, pList);
        }
        virtual RtVoid Clipping(RtFloat cnear, RtFloat cfar)
        {
            m_branch.Clipping(cnear, cfar);
            nextFilter().Clipping(cnear, cfar);
        }
        virtual RtVoid ClippingPlane(RtFloat x, RtFloat y, RtFloat z, RtFloat nx, RtFloat ny, RtFloat nz)
        {
            m_branch.ClippingPlane(x, y, z, nx, ny, nz);
            nextFilter().ClippingPlane(x, y, z, nx, ny, nz);
        }
        virtual RtVoid DepthOfField(RtFloat fstop, RtFloat focallength, RtFloat focaldistance)
        {
            m_branch.DepthOfField(fstop, focallength, focaldistance);
            nextFilter().DepthOfField(fstop, focallength, focaldistance);
        }
        virtual RtVoid Shutter(RtFloat opentime, RtFloat closetime)
        {
            m_branch.Shutter(opentime, closetime);
            nextFilter().Shutter(opentime, closetime);
        }
        virtual RtVoid PixelVariance(RtFloat variance)
        {
            m_branch.PixelVariance(variance);
            nextFilter().PixelVariance(variance);
        }
        virtual RtVoid PixelSamples(RtFloat xsamples, RtFloat ysamples)
        {
            m_branch.PixelSamples(xsamples, ysamples);
            nextFilter().PixelSamples(xsamples, ysamples);
        }
        virtual RtVoid PixelFilter(RtFilterFunc function, RtFloat xwidth, RtFloat ywidth)
        {
            m_branch.PixelFilter(function, xwidth, ywidth);
            nextFilter().PixelFilter(function, xwidth, ywidth);
        }
        virtual RtVoid Exposure(RtFloat gain, RtFloat gamma)
        {
            m_branch.Exposure(gain, gamma);
            nextFilter().Exposure(gain, gamma);
        }
        virtual RtVoid Imager(RtConstToken name, const ParamList& pList)
        {
            m_branch.Imager(name, pList);
            nextFilter().Imager(name, pList);
        }
        virtual RtVoid Quantize(RtConstToken type, RtInt one, RtInt min, RtInt max, RtFloat ditheramplitude)
        {
            m_branch.Quantize(type, one, min, max, ditheramplitude);
            nextFilter().Quantize(type, one, min, max, ditheramplitude);
        }
        virtual RtVoid Display(RtConstToken name, RtConstToken type, RtConstToken mode, const ParamList& pList)
        {
            m_branch.Display(name, type, mode, pList);
            nextFilter().Display(name, type, mode, pList);
        }
        virtual RtVoid Hider(RtConstToken name, const ParamList& pList)
        {
            m_branch.Hider(name, pList);
            nextFilter().Hider(name, pList);
        }
        virtual RtVoid ColorSamples(const FloatArray& nRGB, const FloatArray& RGBn)
        {
            m_branch.ColorSamples(nRGB, RGBn);
            nextFilter().ColorSamples(nRGB, RGBn);
        }
        virtual RtVoid RelativeDetail(RtFloat relativedetail)
        {
            m_branch.RelativeDetail(relativedetail);
            nextFilter().RelativeDetail(relativedetail);
        }
        virtual RtVoid Option(RtConstToken name, const ParamList& pList)
        {
            m_branch.Option(name, pList);
            nextFilter().Option(name, pList);
        }
        virtual RtVoid AttributeBegin()
        {
            m_branch.AttributeBegin();
            nextFilter().AttributeBegin();
        }
        virtual RtVoid AttributeEnd()
        {
            nextFilter().AttributeEnd();
            m_branch.AttributeEnd();
        }
        virtual RtVoid Color(RtConstColor Cq)
        {
            m_branch.Color(Cq);
            nextFilter().Color(Cq);
        }
        virtual RtVoid Opacity(RtConstColor Os)
        {
            m_branch.Opacity(Os);
            nextFilter().Opacity(Os);
        }
        virtual RtVoid TextureCoordinates(RtFloat s1, RtFloat t1, RtFloat s2, RtFloat t2, RtFloat s3, RtFloat t3, RtFloat s4, RtFloat t4)
        {
            m_branch.TextureCoordinates(s1, t1, s2, t2, s3, t3, s4, t4);
            nextFilter().TextureCoordinates(s1, t1, s2, t2, s3, t3, s4, t4);
        }
        virtual RtVoid LightSource(RtConstToken shadername, RtConstToken name, const ParamList& pList)
        {
            m_branch.LightSource(shadername, name, pList);
            nextFilter().LightSource(shadername, name, pList);
        }
        virtual RtVoid AreaLightSource(RtConstToken shadername, RtConstToken name, const ParamList& pList)
        {
            m_branch.AreaLightSource(shadername, name, pList);
            nextFilter().AreaLightSource(shadername, name, pList);
        }
        virtual RtVoid Illuminate(RtConstToken name, RtBoolean onoff)
        {
            m_branch.Illuminate(name, onoff);
            nextFilter().Illuminate(name, onoff);
        }
        virtual RtVoid Surface(RtConstToken name, const ParamList& pList)
        {
            m_branch.Surface(name, pList);
            nextFilter().Surface(name, pList);
        }
        virtual RtVoid Displacement(RtConstToken name, const ParamList& pList)
        {
            m_branch.Displacement(name, pList);
            nextFilter().Displacement(name, pList);
        }
        virtual RtVoid Atmosphere(RtConstToken name, const ParamList& pList)
        {
            m_branch.Atmosphere(name, pList);
            nextFilter().Atmosphere(name, pList);
        }
        virtual RtVoid Interior(RtConstToken name, const ParamList& pList)
        {
            m_branch.Interior(name, pList);
            nextFilter().Interior(name, pList);
        }
        virtual RtVoid Exterior(RtConstToken name, const ParamList& pList)
        {
            m_branch.Exterior(name, pList);
            nextFilter().Exterior(name, pList);
        }
        virtual RtVoid ShaderLayer(RtConstToken type, RtConstToken name, RtConstToken layername, const ParamList& pList)
        {
            m_branch.ShaderLayer(type, name, layername, pList);
            nextFilter().ShaderLayer(type, name, layername, pList);
        }
        virtual RtVoid ConnectShaderLayers(RtConstToken type, RtConstToken layer1, RtConstToken variable1, RtConstToken layer2, RtConstToken variable2)
        {
            m_branch.ConnectShaderLayers(type, layer1, variable1, layer2, variable2);
            nextFilter().ConnectShaderLayers(type, layer1, variable1, layer2, variable2);
        }
        virtual RtVoid ShadingRate(RtFloat size)
        {
            m_branch.ShadingRate(size);
            nextFilter().ShadingRate(size);
        }
        virtual RtVoid ShadingInterpolation(RtConstToken type)
        {
            m_branch.ShadingInterpolation(type);
            nextFilter().ShadingInterpolation(type);
        }
        virtual RtVoid Matte(RtBoolean onoff)
        {
            m_branch.Matte(onoff);
            nextFilter().Matte(onoff);
        }
        virtual RtVoid Bound(RtConstBound bound)
        {
            m_branch.Bound(bound);
            nextFilter().Bound(bound);
        }
        virtual RtVoid Detail(RtConstBound bound)
        {
            m_branch.Detail(bound);
            nextFilter().Detail(bound);
        }
        virtual RtVoid DetailRange(RtFloat offlow, RtFloat onlow, RtFloat onhigh, RtFloat offhigh)
        {
            m_branch.DetailRange(offlow, onlow, onhigh, offhigh);
            nextFilter().DetailRange(offlow, onlow, onhigh, offhigh);
        }
        virtual RtVoid GeometricApproximation(RtConstToken type, RtFloat value)
        {
            m_branch.GeometricApproximation(type, value);
            nextFilter().GeometricApproximation(type, value);
        }
        virtual RtVoid Orientation(RtConstToken orientation)
        {
            m_branch.Orientation(orientation);
            nextFilter().Orientation(orientation);
        }
        virtual RtVoid ReverseOrientation()
        {
            m_branch.ReverseOrientation();
            nextFilter().ReverseOrientation();
        }
        virtual RtVoid Sides(RtInt nsides)
        {
            m_branch.Sides(nsides);
            nextFilter().Sides(nsides);
        }
        virtual RtVoid Identity()
        {
            m_branch.Identity();
            nextFilter().Identity();
        }
        virtual RtVoid Transform(RtConstMatrix transform)
        {
            m_branch.Transform(transform);
            nextFilter().Transform(transform);
        }
        virtual RtVoid ConcatTransform(RtConstMatrix transform)
        {
            m_branch.ConcatTransform(transform);
            nextFilter().ConcatTransform(transform);
        }
        virtual RtVoid Perspective(RtFloat fov)
        {
            m_branch.Perspective(fov);
            nextFilter().Perspective(fov);
        }
        virtual RtVoid Translate(RtFloat dx, RtFloat dy, RtFloat dz)
        {
            m_branch.Translate(dx, dy, dz);
            nextFilter().Translate(dx, dy, dz);
        }
        virtual RtVoid Rotate(RtFloat angle, RtFloat dx, RtFloat dy, RtFloat dz)
        {
            m_branch.Rotate(angle, dx, dy, dz);
            nextFilter().Rotate(angle, dx, dy, dz);
        }
        virtual RtVoid Scale(RtFloat sx, RtFloat sy, RtFloat sz)
        {
            m_branch.Scale(sx, sy, sz);
            nextFilter().Scale(sx, sy, sz);
        }
        virtual RtVoid Skew(RtFloat angle, RtFloat dx1, RtFloat dy1, RtFloat dz1, RtFloat dx2, RtFloat dy2, RtFloat dz2)
        {
            m_branch.Skew(angle, dx1, dy1, dz1, dx2, dy2, dz2);
            nextFilter().Skew(angle, dx1, dy1, dz1, dx2, dy2, dz2);
        }
        virtual RtVoid CoordinateSystem(RtConstToken space)
        {
            m_branch.CoordinateSystem(space);
            nextFilter().CoordinateSystem(space);
        }
        virtual RtVoid CoordSysTransform(RtConstToken space)
        {
            m_branch.CoordSysTransform(space);
            nextFilter().CoordSysTransform(space);
        }
        virtual RtVoid TransformBegin()
        {
            m_branch.TransformBegin();
            nextFilter().TransformBegin();
        }
        virtual RtVoid TransformEnd()
        {
            nextFilter().TransformEnd();
            m_branch.TransformEnd();
        }
        virtual RtVoid Resource(RtConstToken handle, RtConstToken type, const ParamList& pList)
        {
            m_branch.Resource(handle, type, pList);
            nextFilter().Resource(handle, type, pList);
        }
        virtual RtVoid ResourceBegin()
        {
            m_branch.ResourceBegin();
            nextFilter().ResourceBegin();
        }
        virtual RtVoid ResourceEnd()
        {
            nextFilter().ResourceEnd();
            m_branch.ResourceEnd();
        }
        virtual RtVoid Attribute(RtConstToken name, const ParamList& pList)
        {
            m_branch.Attribute(name, pList);
            nextFilter().Attribute(name, pList);
        }
        virtual RtVoid Polygon(const ParamList& pList)
        {
            m_branch.Polygon(pList);
            nextFilter().Polygon(pList);
        }
        virtual RtVoid GeneralPolygon(const IntArray& nverts, const ParamList& pList)
        {
            m_branch.GeneralPolygon(nverts, pList);
            nextFilter().GeneralPolygon(nverts, pList);
        }
        virtual RtVoid PointsPolygons(const IntArray& nverts, const IntArray& verts, const ParamList& pList)
        {
            m_branch.PointsPolygons(nverts, verts, pList);
            nextFilter().PointsPolygons(nverts, verts, pList);
        }
        virtual RtVoid PointsGeneralPolygons(const IntArray& nloops, const IntArray& nverts, const IntArray& verts, const ParamList& pList)
        {
            m_branch.PointsGeneralPolygons(nloops, nverts, verts, pList);
            nextFilter().PointsGeneralPolygons(nloops, nverts, verts, pList);
        }
        virtual RtVoid Basis(RtConstBasis ubasis, RtInt ustep, RtConstBasis vbasis, RtInt vstep)
        {
            m_branch.Basis(ubasis, ustep, vbasis, vstep);
            nextFilter().Basis(ubasis, ustep, vbasis, vstep);
        }
        virtual RtVoid Patch(RtConstToken type, const ParamList& pList)
        {
            m_branch.Patch(type, pList);
            nextFilter().Patch(type, pList);
        }
        virtual RtVoid PatchMesh(RtConstToken type, RtInt nu, RtConstToken uwrap, RtInt nv, RtConstToken vwrap, const ParamList& pList)
        {
            m_branch.PatchMesh(type, nu, uwrap, nv, vwrap, pList);
            nextFilter().PatchMesh(type, nu, uwrap, nv, vwrap, pList);
        }
        virtual RtVoid NuPatch(RtInt nu, RtInt uorder, const FloatArray& uknot, RtFloat umin, RtFloat umax, RtInt nv, RtInt vorder, const FloatArray& vknot, RtFloat vmin, RtFloat vmax, const ParamList& pList)
        {
            m_branch.NuPatch(nu, uorder, uknot, umin, umax, nv, vorder, vknot, vmin, vmax, pList);
            nextFilter().NuPatch(nu, uorder, uknot, umin, umax, nv, vorder, vknot, vmin, vmax, pList);
        }
        virtual RtVoid TrimCurve(const IntArray& ncurves, const IntArray& order, const FloatArray& knot, const FloatArray& min, const FloatArray& max, const IntArray& n, const FloatArray& u, const FloatArray& v, const FloatArray& w)
        {
            m_branch.TrimCurve(ncurves, order, knot, min, max, n, u, v, w);
            nextFilter().TrimCurve(ncurves, order, knot, min, max, n, u, v, w);
        }
        virtual RtVoid SubdivisionMesh(RtConstToken scheme, const IntArray& nvertices, const IntArray& vertices, const TokenArray& tags, const IntArray& nargs, const IntArray& intargs, const FloatArray& floatargs, const ParamList& pList)
        {
            m_branch.SubdivisionMesh(scheme, nvertices, vertices, tags, nargs, intargs, floatargs, pList);
            nextFilter().SubdivisionMesh(scheme, nvertices, vertices, tags, nargs, intargs, floatargs, pList);
        }
        virtual RtVoid Sphere(RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, const ParamList& pList)
        {
            m_branch.Sphere(radius, zmin, zmax, thetamax, pList);
            nextFilter().Sphere(radius, zmin, zmax, thetamax, pList);
        }
        virtual RtVoid Cone(RtFloat height, RtFloat radius, RtFloat thetamax, const ParamList& pList)
        {
            m_branch.Cone(height, radius, thetamax, pList);
            nextFilter().Cone(height, radius, thetamax, pList);
        }
        virtual RtVoid Cylinder(RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, const ParamList& pList)
        {
            m_branch.Cylinder(radius, zmin, zmax, thetamax, pList);
            nextFilter().Cylinder(radius, zmin, zmax, thetamax, pList);
        }
        virtual RtVoid Hyperboloid(RtConstPoint point1, RtConstPoint point2, RtFloat thetamax, const ParamList& pList)
        {
            m_branch.Hyperboloid(point1, point2, thetamax, pList);
            nextFilter().Hyperboloid(point1, point2, thetamax, pList);
        }
        virtual RtVoid Paraboloid(RtFloat rmax, RtFloat zmin, RtFloat zmax, RtFloat thetamax, const ParamList& pList)
        {
            m_branch.Paraboloid(rmax, zmin, zmax, thetamax, pList);
            nextFilter().Paraboloid(rmax, zmin, zmax, thetamax, pList);
        }
        virtual RtVoid Disk(RtFloat height, RtFloat radius, RtFloat thetamax, const ParamList& pList)
        {
            m_branch.Disk(height, radius, thetamax, pList);
            nextFilter().Disk(height, radius, thetamax, pList);
        }
        virtual RtVoid Torus(RtFloat majorrad, RtFloat minorrad, RtFloat phimin, RtFloat phimax, RtFloat thetamax, const ParamList& pList)
        {
            m_branch.Torus(majorrad, minorrad, phimin, phimax, thetamax, pList);
            nextFilter().Torus(majorrad, minorrad, phimin, phimax, thetamax, pList);
        }
        virtual RtVoid Points(const ParamList& pList)
        {
            m_branch.Points(pList);
            nextFilter().Points(pList);
        }
        virtual RtVoid Curves(RtConstToken type, const IntArray& nvertices, RtConstToken wrap, const ParamList& pList)
        {
            m_branch.Curves(type, nvertices, wrap, pList);
            nextFilter().Curves(type, nvertices, wrap, pList);
        }
        virtual RtVoid Blobby(RtInt nleaf, const IntArray& code, const FloatArray& floats, const TokenArray& strings, const ParamList& pList)
        {
            m_branch.Blobby(nleaf, code, floats, strings, pList);
            nextFilter().Blobby(nleaf, code, floats, strings, pList);
        }
        virtual RtVoid Procedural(RtPointer data, RtConstBound bound, RtProcSubdivFunc refineproc, RtProcFreeFunc freeproc)
        {
            m_branch.Procedural(data, bound, refineproc, freeproc);
            nextFilter().Procedural(data, bound, refineproc, freeproc);
        }
        virtual RtVoid Geometry(RtConstToken type, const ParamList& pList)
        {
            m_branch.Geometry(type, pList);
            nextFilter().Geometry(type, pList);
        }
        virtual RtVoid SolidBegin(RtConstToken type)
        {
            m_branch.SolidBegin(type);
            nextFilter().SolidBegin(type);
        }
        virtual RtVoid SolidEnd()
        {
            nextFilter().SolidEnd();
            m_branch.SolidEnd();
        }
        virtual RtVoid ObjectBegin(RtConstToken name)
        {
            m_branch.ObjectBegin(name);
            nextFilter().ObjectBegin(name);
        }
        virtual RtVoid ObjectEnd()
        {
            nextFilter().ObjectEnd();
            m_branch.ObjectEnd();
        }
        virtual RtVoid ObjectInstance(RtConstToken name)
        {
            m_branch.ObjectInstance(name);
            nextFilter().ObjectInstance(name);
        }
        virtual RtVoid MotionBegin(const FloatArray& times)
        {
            m_branch.MotionBegin(times);
            nextFilter().MotionBegin(times);
        }
        virtual RtVoid MotionEnd()
        {
            nextFilter().MotionEnd();
            m_branch.MotionEnd();
        }
        virtual RtVoid MakeTexture(RtConstString imagefile, RtConstString texturefile, RtConstToken swrap, RtConstToken twrap, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, const ParamList& pList)
        {
            m_branch.MakeTexture(imagefile, texturefile, swrap, twrap, filterfunc, swidth, twidth, pList);
            nextFilter().MakeTexture(imagefile, texturefile, swrap, twrap, filterfunc, swidth, twidth, pList);
        }
        virtual RtVoid MakeLatLongEnvironment(RtConstString imagefile, RtConstString reflfile, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, const ParamList& pList)
        {
            m_branch.MakeLatLongEnvironment(imagefile, reflfile, filterfunc, swidth, twidth, pList);
            nextFilter().MakeLatLongEnvironment(imagefile, reflfile, filterfunc, swidth, twidth, pList);
        }
        virtual RtVoid MakeCubeFaceEnvironment(RtConstString px, RtConstString nx, RtConstString py, RtConstString ny, RtConstString pz, RtConstString nz, RtConstString reflfile, RtFloat fov, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, const ParamList& pList)
        {
            m_branch.MakeCubeFaceEnvironment(px, nx, py, ny, pz, nz, reflfile, fov, filterfunc, swidth, twidth, pList);
            nextFilter().MakeCubeFaceEnvironment(px, nx, py, ny, pz, nz, reflfile, fov, filterfunc, swidth, twidth, pList);
        }
        virtual RtVoid MakeShadow(RtConstString picfile, RtConstString shadowfile, const ParamList& pList)
        {
            m_branch.MakeShadow(picfile, shadowfile, pList);
            nextFilter().MakeShadow(picfile, shadowfile, pList);
        }
        virtual RtVoid MakeOcclusion(const StringArray& picfiles, RtConstString shadowfile, const ParamList& pList)
        {
            m_branch.MakeOcclusion(picfiles, shadowfile, pList);
            nextFilter().MakeOcclusion(picfiles, shadowfile, pList);
        }
        virtual RtVoid ErrorHandler(RtErrorFunc handler)
        {
            m_branch.ErrorHandler(handler);
            nextFilter().ErrorHandler(handler);
        }
        virtual RtVoid ReadArchive(RtConstToken name, RtArchiveCallback callback, const ParamList& pList)
        {
            m_branch.ReadArchive(name, callback, pList);
            nextFilter().ReadArchive(name, callback, pList);
        }
        virtual RtVoid ArchiveBegin(RtConstToken name, const ParamList& pList)
        {
            m_branch.ArchiveBegin(name, pList);
            nextFilter().ArchiveBegin(name, pList);
        }
        virtual RtVoid ArchiveEnd()
        {
            nextFilter().ArchiveEnd();
            m_branch.ArchiveEnd();
        }
        ///[[[end]]]
};

Ri::Filter* createTeeFilter(Ri::Renderer& branch)
{
    return new TeeFilter(branch);
}

}

// vi: set et:
