function HandleSwitchNode(scene, nodeID, inVal) {
    this.sceneID = scene.GetID();
    this.nodeID = nodeID;
    var nodes = scene.GetNodes(nodeID);
    if (nodes != undefined)
        this.nodesCount = nodes.length;
    else
        this.nodesCount = 0;
    this.value = inVal;

    scene.SetSwitchActiveChild(this.nodeID, this.value);

    this.set = function(value) {
        this.value = value;
        if (this.value >= this.nodesCount)
            this.value = this.nodesCount-1;
        if (this.value < -2)
            this.value = -2;
        scene.SetSwitchActiveChild(this.nodeID, this.value);
    }

    this.inc = function() {
        this.value++;
        if (this.value >= this.nodesCount)
            this.value = 0;
        //LOG("+" + this.value + "+");
        scene.SetSwitchActiveChild(this.nodeID, this.value);
    }

    this.dec = function() {
        this.value--;
        if (this.value < 0) {
            this.value = this.nodesCount - 1;
        }
        //LOG("-" + this.value + "-");
        scene.SetSwitchActiveChild(this.nodeID, this.value);
    }
}

//VRED scenes has often more switches with the same name, we need to control all of them together
function HandleMultiSwitch(scene, switchName, inVal) {
    this.sceneID = scene.GetID();
    this.nodes = scene.GetNodes(switchName);
    if (this.nodes != undefined) {
        var subNodes = scene.GetNodes(this.nodes[0].GetID());
        if (subNodes != undefined) {
            this.nodesCount = subNodes.length;
            /*for (i = 0; i < subNodes.length; ++i)
                LOG("HandleMultiSwitch " + switchName + " " + subNodes[i].GetID());*/
        }
        else {
            this.nodesCount = 0;
            LOGWARNING("HandleMultiSwitch name=" + switchName + " has not children");
        }
    }
    else {
        this.nodesCount = 0;
        LOGWARNING("HandleMultiSwitch not exist name=" + switchName);
    }
    this.value = inVal;
    //LOG("HandleMultiSwitch " + switchName + " count=" + this.nodesCount + " nodes=" + this.nodes);

    this.set = function (value) {
        this.value = value;
        if (this.value >= this.nodesCount)
            this.value = this.nodesCount - 1;
        if (this.value < -2)
            this.value = -2;
        if (this.nodes!=undefined)
            for (i = 0; i < this.nodes.length; ++i)
                scene.SetSwitchActiveChild(this.nodes[i].GetID(), this.value);
    }

    this.set(this.value);//set initial value

    this.inc = function () {
        this.value++;
        if (this.value >= this.nodesCount)
            this.value = 0;
        //LOG("+" + this.value + "+");
        if (this.nodes != undefined)
            for (i = 0; i < this.nodes.length; ++i)
                scene.SetSwitchActiveChild(this.nodes[i].GetID(), this.value);
    }

    this.dec = function () {
        this.value--;
        if (this.value < 0) {
            this.value = this.nodesCount - 1;
        }
        //LOG("-" + this.value + "-");
        if (this.nodes != undefined)
            for (i = 0; i < this.nodes.length; ++i)
                scene.SetSwitchActiveChild(this.nodes[i].GetID(), this.value);
    }
}

function NodesSwitch(inVal, scene, nodes) {
	this.value=inVal;
	this.maxValue=nodes.length;
	this.nodes=nodes;
	this.scene=scene;

	for (i=0; i<nodes.length; i++) {
		if (i==this.value) {
			this.scene.SetActive(this.nodes[i], true);
		} else {
		    this.scene.SetActive(this.nodes[i], false);
		}
	}

	//LOG("initial value: " + this.value);

	this.set = function(value) {
	    this.scene.SetActive(this.nodes[this.value], false);
	    this.value = value;
	    if (value > this.maxValue) {
	        this.value = this.maxValue;
	    }
	    if (value < 0) {
	        this.value = 0;
	    }
	    this.scene.SetActive(this.nodes[this.value], true);
	    //LOG("new counter value: " + this.value);
	}

	this.inc = function() {
	    value = this.value + 1;
	    value %= this.maxValue;
	    this.set(value);
	}

	this.dec = function() {
	    value = this.value - 1;
	    if (value < 0) {
	        value += this.maxValue;
	    }
	    this.set(value);
	}

	this.hide = function() {
	    this.scene.SetActive(this.nodes[this.value], false);
	}
}

function TranslateSwitch(inVal, scene, vectors, nodeTrans) {
	this.value=inVal;
	this.maxValue=vectors.length;
	this.vectors=vectors;
	this.scene=scene;
	this.nodeTrans=nodeTrans;

	this.scene.TranslateAbs(this.nodeTrans, this.vectors[this.value]);

	this.set = function(value) {
	    this.value = value;
	    if (value > this.maxValue) {
	        this.value = this.maxValue;
	    }
	    if (value < 0) {
	        this.value = 0;
	    }
	    this.scene.TranslateAbs(this.nodeTrans, this.vectors[this.value]);
	}

	this.inc=function() {
	    //LOG("incrementing "+this.value);
		this.value++;
		this.value%=this.maxValue;
		this.scene.TranslateAbs(this.nodeTrans, this.vectors[this.value]);
		//LOG("new counter value: " + this.value);
	}

	this.dec=function() {
	    //LOG("decrementing "+this.value);
		this.value--;
		if (this.value<0) {
			this.value+=this.maxValue;
		}
		this.scene.TranslateAbs(this.nodeTrans, this.vectors[this.value]);
		//LOG("new counter value: " + this.value);
	}
}

function SwitchRotations(nodeTrans, scene, vecCenter, arrVecAxes, arrLimits, arrInitialValues) {
	this.nodeTrans=nodeTrans;
	this.scene=scene;

	this.vecCenter=vecCenter;
	this.arrLimits=arrLimits;
	this.arrVecAxes=arrVecAxes;

	this.arrValues = arrInitialValues;
	if (this.arrValues == undefined)
	    this.arrValues = new Array();

	for (i = 0; i < arrVecAxes.length; i++) {
	    if (this.arrValues.length<i+1)
		    this.arrValues[i]=0;
		this.arrVecAxes[i]=this.arrVecAxes[i].Normalize();
	}

	this.update = function(dimension, step) {
	    this.arrValues[dimension] += step;
	    if (this.arrValues[dimension] > this.arrLimits[dimension]) {
	        this.arrValues[dimension] = this.arrLimits[dimension]
	    }
	    if (this.arrValues[dimension] < -this.arrLimits[dimension]) {
	        this.arrValues[dimension] = -this.arrLimits[dimension]
	    }
	    this.ftransform();
	};

	this.ftransform = function() {
	    var vpinv = new Vector3(-this.vecCenter.x, -this.vecCenter.y, -this.vecCenter.z);
	    var mat = Matrix.Translation(vpinv);
	    for (i = 0; i < this.arrVecAxes.length; i++) {
	        mat = mat.Multiply(Matrix.RotationAxis(this.arrVecAxes[i], -(this.arrValues[i]) * 3.141592 / 180.0));
	    }
	    mat = mat.Multiply(Matrix.Translation(this.vecCenter));
	    scene.SetTransformation(this.nodeTrans, mat);
	    //LOG("SwitchRotations.ftransform, this.nodeTrans=" + this.nodeTrans + ", mat=" + mat);
	};

	this.ftransform();
}