/*
 * Copyright (c) 2006, John T. Reese 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 John T. Reese nor the names of his
 *     contributors may be used to endorse or promote products
 *     derived from this software without specific prior written
 *     permission.
 *
 * THIS SOFTWARE IS PROVIDED BY JOHN T. REESE 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 JOHN T.
 * REESE AND 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.
 */


import jtr.*;
import jtr.mesh.*;
import vrml.*;
import vrml.field.*;
import vrml.node.*;




/*
 *
 * to use from VRML:
 *
 * the VRML file should be of this form:
 *
 * # any applicable grouping node
 * Transform {
 *      children [
 *          # Use a touch sensor to active the subdivision.
 *          DEF SENSOR TouchSensor {}
 *          Shape {
 *              # Whatever you want it to look like: color and so
 *              # forth.
 *              appearance Appearance {...}
 *
 *              # The mesh itself.  Name (with DEF) for future
 *              # reference in the Script node.
 *              geometry DEF IFS IndexedFaceSet {
 *                  # point is a vector of vertices
 *                  coord Coordinate { point [...] }
 *                  # coordIndex represents the faces
 *                  coordIndex [...]
 *              }
 *          }
 *
 *          # the Script node
 *          DEF SC Script {
 *              # important -- allows script to affect scene graph
 *              directOutput TRUE
 *
 *              # point to the compiled Java code
 *              url "http://www.ugcs.caltech.edu/~jtr/tide/mesh-div.class"
 *
 *              # used to link TouchSensor to script
 *              eventIn SFBool isActive
 *
 *              # points to mesh previously defined
 *              field SFNode ifs USE IFS
 *
 *              # because the VRML Java interface blows goats, you must
 *              # duplicate all of the data from coordIndex, verbatim,
 *              # here.  There is no other way for the Script to
 *              # acquire this information.
 *              field MFInt32 coordIndex [...]
 *          }
 *
 *          # Connect touch sensor to script, allowing script to
 *          # subdivide when mouse button is pressed over shape.
 *          ROUTE SENSOR.isActive TO SC.isActive
 *      ]
 * }
 *
 * There is some flexibility possible.  mesh-div subdivides when the
 * isActive eventIn is triggered... any normal VRML method of
 * generating a VRML eventIn will work as well as the TouchSensor
 * method.  The code could easily be tweaked to activate in another
 * way, but an SFBool eventIn seems natural.
 *
 * The duplication of the coordIndex annoys me, but is currently
 * unavoidable.  Hopefully coordIndex will become an exposedField in
 * some future version of VRML.
 *
 *
 *
 */



public class MeshDiv extends Script {
    VRMLDivide v;
    Browser br;
    float[][] point;
    int[] coordIndex;


    public void initialize() {
        try {
            Node ifs= (Node) ((SFNode) getField("ifs")).getValue();
            Node co= (Node) ((SFNode) ifs.getExposedField("coord")).getValue();

            MFVec3f mv= (MFVec3f) co.getExposedField("point");
            MFInt32 mi= (MFInt32) getField("coordIndex");

            point= new float[mv.getSize()][3];
            coordIndex= new int[mi.getSize()];

            mv.getValue(point);
            mi.getValue(coordIndex);

            br= ifs.getBrowser();
            v= new VRMLDivide(ifs, mi);
        }

        catch (Throwable e) {
            System.out.println("*** error during construction");
            e.printStackTrace(System.out);
            System.out.println("*** thump");
        }
    }

    public void processEvent(Event e) {
        try {
            if (e.getName().equals("isActive") &&
                ((ConstSFBool) e.getValue()).getValue())
            {
                String[] s= new String[4];
                System.out.println("Preparing " + (s.length - 1) + " levels");
                s[0]= v.Emit(coordIndex, point);
                s[1]= v.CatClark(1);
                s[2]= v.CatClark(2);
                s[3]= v.CatClark(3);
                //s[3]= v.CatClark(4);
                System.out.println("Done.");
                BaseNode[] bn= br.createVrmlFromString(MakeNewWorld(s));

                br.replaceWorld(bn);   
            }
        }
        catch (Throwable ex) {
            System.out.println("*** yawn");
            ex.printStackTrace(System.out);
            System.out.println("*** thump");
        }
    }

    private String MakeNewWorld(String[] meshes) {
        String s;
 
        s= "Transform {\n" +
            "children [\n" +
                //"DEF RED Appearance {\n" +
                //"material Material { diffuseColor 1 0 0 }\n" +
                //"}\n" +
                "DEF TS TouchSensor {}\n" +
                "DirectionalLight {\n" +
                " color 0.05 0.05 0.6\n" +
                " direction 0.1 0.1 0.0\n" +
                "}\n" +
                "DirectionalLight {\n" +
                " color 0.6 0.05 0.05\n" +
                " direction 0.1 -0.1 0.0\n" +
                "}\n" +
                "DEF SW Switch {\n" +
                    "choice [\n";

        for (int i= 0; i < meshes.length; i++)
            s += "Shape { appearance Appearance {\n" +
                "material Material {diffuseColor .4 .4 .4 \n" +
                                   "specularColor 1 1 1\n" +
                                   "shininess 1.0\n" +
                "}\n" +
                "}\n" +
                "geometry " + meshes[i] + "}\n";

        s += "]\n" +
                    "whichChoice 0\n" +
                "}\n" +
                "DEF BUTTSWITCH Script {\n" +
                    "directOutput TRUE\n" +
                    "field SFNode swit USE SW\n" +
                    "eventIn SFBool butt1\n" +
                    "url \"javascript:\n" +
                        "function butt1(value,timestamp) {\n" +
                            "if (value) {\n" +
                              "swit.set_whichChoice= " +
                                "(swit.whichChoice + 1) %" +
                                meshes.length + ";\n" +
                            "}\n" +
                        "}\"\n" +
                "}\n" +
            "]\n" +
            "ROUTE TS.isActive TO BUTTSWITCH.butt1\n" +
        "}\n";


        return s;
    }
}

