/*
-----------------------------------------------------------------------------
This source file is part of OpenSpace3D
For the latest info, see http://www.openspace3d.com

Copyright (c) 2012 I-maginer

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt

-----------------------------------------------------------------------------
*/

struct PlugRotate = [
  ROT_shell                 : SO3_OBJECT,
  ROT_iShellMode            : I,
  ROT_initQuat              : [F F F F],
  ROT_speed                 : [F F F],
  ROT_bState                : I,
  ROT_bFpsBased             : I

  ]mkPlugRotate;;



fun deleteOb(inst, rotstr)=
  setPluginInstanceCbScenePreRender inst nil;
  setPluginInstanceCbCameraChange inst nil;
  SO3ObjectSetOrientation rotstr.ROT_shell rotstr.ROT_initQuat;
  0;;


fun cbRotPreRender(inst, viewstr, etime, rotstr)=
  let rotstr.ROT_speed -> [pitch yaw roll] in
  let (itof etime) /. 1000000.0 -> ftime in 
  let if rotstr.ROT_bFpsBased then 1.0 else ftime *. 90.0 -> nbframe in
  (
    SO3ObjectRotateYaw rotstr.ROT_shell (yaw *. nbframe) SO3_LOCAL_TS;
    SO3ObjectRotatePitch rotstr.ROT_shell (pitch *. nbframe) SO3_LOCAL_TS;
    SO3ObjectRotateRoll rotstr.ROT_shell (roll *. nbframe) SO3_LOCAL_TS;
  );
  0;;


fun enableRotate(inst, from, action, param, rep, rotstr) =
  set rotstr.ROT_bState = 1;
  setPluginInstanceCbScenePreRender inst mkfun4 @cbRotPreRender rotstr;
  0;;


fun disableRotate(inst, from, action, param, rep, rotstr) =
  set rotstr.ROT_bState = 0;
  setPluginInstanceCbScenePreRender inst nil;
  0;;


fun setPitch(inst, from, action, param, rep, rotstr) =
  if (param == nil) || ((atof param) == nil) then nil else
  mutate rotstr.ROT_speed <- [(SO3MathsDegreeToRadian (atof param)) _ _];
  0;;


fun setYaw(inst, from, action, param, rep, rotstr) =
  if (param == nil) || ((atof param) == nil) then nil else
  mutate rotstr.ROT_speed <- [_ (SO3MathsDegreeToRadian (atof param)) _];
  0;;


fun setRoll(inst, from, action, param, rep, rotstr) =
  if (param == nil) || ((atof param) == nil) then nil else
  mutate rotstr.ROT_speed <- [_ _ (SO3MathsDegreeToRadian (atof param))];
  0;;


fun cbChangeCamera(inst, viewstr, sessionstr, camera, rotstr)=
  let V3DgetCameraByType sessionstr camera rotstr.ROT_iShellMode -> nfather in
  let SO3ObjectGetOrientation nfather -> cquat in
  (
    SO3ObjectSetOrientation rotstr.ROT_shell rotstr.ROT_initQuat;
   
    set rotstr.ROT_shell = nfather; 
    set rotstr.ROT_initQuat = cquat;
  );
  0;;


fun newOb(inst)=
  let (getPluginInstanceParam inst "object") -> objname in
  let atoi (getPluginInstanceParam inst "enable") -> enable in
  let SO3MathsDegreeToRadian (atof (getPluginInstanceParam inst "rotx")) -> pitch in
  let SO3MathsDegreeToRadian (atof (getPluginInstanceParam inst "roty")) -> yaw in
  let SO3MathsDegreeToRadian (atof (getPluginInstanceParam inst "rotz")) -> roll in
  let atoi (getPluginInstanceParam inst "fpsbased") -> fpsbased in
  let if fpsbased == nil then 0 else fpsbased -> fpsbased in
  
  let V3DgetObjectByName c3dXsession objname -> obj in
  let V3DgetObjectTypeByName objname -> iobjmode in

  let SO3ObjectGetOrientation obj -> initquat in
  let mkPlugRotate [obj iobjmode initquat [pitch yaw roll] 0 fpsbased] -> rotstr in
  (
	  PluginRegisterAction inst "Play" mkfun6 @enableRotate rotstr;
	  PluginRegisterAction inst "Stop" mkfun6 @disableRotate rotstr;
	  PluginRegisterAction inst "Pitch" mkfun6 @setPitch rotstr;
	  PluginRegisterAction inst "Roll" mkfun6 @setRoll rotstr;
	  PluginRegisterAction inst "Yaw" mkfun6 @setYaw rotstr;
    
    if !iobjmode then nil else
      setPluginInstanceCbCameraChange inst mkfun5 @cbChangeCamera rotstr;
    
    if !enable then nil else
    (
      set rotstr.ROT_bState = 1;
      setPluginInstanceCbScenePreRender inst mkfun4 @cbRotPreRender rotstr;
    );
    
    setPluginInstanceCbDel inst mkfun2 @deleteOb rotstr;
  );
  0;;


fun IniPlug(file)=
  PlugRegister @newOb nil;
  setPluginEditor @dynamicedit;
  0;;