# vPresent is an immersive presentation creation and display application.
# Copyright (C) 2007-2008 by Infiscape Corporation
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU 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 General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

from PyQt4 import QtCore, QtGui
import rotateui 
import gui.util.environment as environ
from wheel import Wheel
import gmtl
import osg2 as osg

def fromOpenSG(mat):
   r =  gmtl.Matrix44f()
   r.set(mat[0][0], mat[1][0], mat[2][0], mat[3][0],
         mat[0][1], mat[1][1], mat[2][1], mat[3][1],
         mat[0][2], mat[1][2], mat[2][2], mat[3][2],
         mat[0][3], mat[1][3], mat[2][3], mat[3][3])
   return r

class Rotate(QtGui.QWidget, rotateui.Ui_RotateBase):
   def __init__(self, rotateElement, parent=None):
      QtGui.QWidget.__init__(self, parent)
      self.setupUi(self)

      self.mRotateElement = rotateElement
      self._updateUi()

   def setupUi(self, widget):
      rotateui.Ui_RotateBase.setupUi(self, widget)

      # Replace all sliders with wheels
      # - Rename var to end in wheel
      grid_name = 'gridlayout'
      slider_names = ["mXRotationSlider","mYRotationSlider","mZRotationSlider"]
      for slider_name in slider_names:
         slider = getattr(self,slider_name)
         grid = getattr(self,grid_name)
         assert (slider is not None and grid is not None)
         
         slider_index = grid.indexOf(slider)
         slider_location = grid.getItemPosition(slider_index)
         grid.removeWidget(slider)
         slider.setParent(None)
         delattr(self,slider_name)
         
         wheel_name = slider_name.replace("Slider","Wheel")
         wheel = Wheel(self)
         wheel.setRange(-1000.0, 1000.0, 1.0, 1.0)
         grid.addWidget(wheel, *slider_location)
         setattr(self,wheel_name, wheel)

      self.widgets = [self.mXRotation, self.mYRotation, self.mZRotation,
                      self.mXRotationWheel, self.mYRotationWheel, self.mZRotationWheel]

      for w in self.widgets[:3]:
         self.connect(w, QtCore.SIGNAL("valueChanged(double)"),
                      self.onValueChanged)

      for w in self.widgets[3:]:
         self.connect(w, QtCore.SIGNAL("valueChanged(double)"),
                      self.onWheelChanged)

   def _updateUi(self):
      # Disable signals while changing values.
      for w in self.widgets:
         w.blockSignals(True)

      # Get the OpenSG matrix and convert it to GMTL.
      osg_matrix = self.mRotateElement.dr3d_transform
      xform = gmtl.Matrix44f()
      xform.set(osg_matrix.getValues())

      coord = gmtl.Coord3fXYZ()
      gmtl.set(coord, xform)
      cur_rot = coord.getRot()
      new_rot = [gmtl.Math.rad2Deg(cur_rot[i]) for i in xrange(3)]

      self.mXRotation.setValue(new_rot[0])
      self.mYRotation.setValue(new_rot[1])
      self.mZRotation.setValue(new_rot[2])
      self.mXRotationWheel.setValue(new_rot[0])
      self.mYRotationWheel.setValue(new_rot[1])
      self.mZRotationWheel.setValue(new_rot[2])

      for w in self.widgets:
         w.blockSignals(False)

   def _updateElement(self):
      xform = self.mRotateElement.dr3d_transform

      rot = [self.mXRotation.value(), self.mYRotation.value(), self.mZRotation.value()]
      rot = [gmtl.Math.deg2Rad(i) for i in rot]
      trans = xform[3]
      
      coord = gmtl.Coord3fXYZ()
      coord.pos = gmtl.Vec3f(trans[0], trans[1], trans[2])
      coord.rot = gmtl.EulerAngleXYZf(rot[0], rot[1], rot[2])
      matrix = gmtl.Matrix44f()
      gmtl.set(matrix, coord)

      # Create an OpenSG matrix from the GMTL matrix.
      osg_matrix = osg.Matrix()
      osg_matrix.setValue(matrix.getData())

      # Set the transform and update scene object.
      self.mRotateElement.dr3d_transform = osg_matrix
      self.mRotateElement._update()
      env = environ.Environment()
      env.updateGL()

   def onValueChanged(self, value):
      self._updateElement()

   def onWheelChanged(self, value):
      self.mXRotation.setValue(self.mXRotationWheel.value())
      self.mYRotation.setValue(self.mYRotationWheel.value())
      self.mZRotation.setValue(self.mZRotationWheel.value())
      self._updateElement()
