pragma Source_Reference (1, "opengl/view_gl.gpb");
--! #if HAVE_GL then
--! with Ada.Text_IO;      use Ada.Text_IO;
--! with gl_h;             use gl_h;
--! with Gdk.Event;        use Gdk.Event;
--! with Gdk.GL;           use Gdk.GL;
--! with Gdk.Rectangle;    use Gdk.Rectangle;
--! with Gdk.Types;        use Gdk.Types;
--! with Gdk.Window;       use Gdk.Window;
--! with Glib;             use Glib;
--! with glu_h;            use glu_h;
--! with Gtk.GLArea;       use Gtk.GLArea;
--! with Gtk.Handlers;     use Gtk.Handlers;
--! with Lwobjects;        use Lwobjects;
--! with Trackball;        use Trackball;
--! #else
with Gtk.Label; use Gtk.Label;
--! #end if;

package body View_Gl is

--! #if HAVE_GL
--!    type Mesh_Info_Type is
--!       record
--!          Do_Init : Boolean := True;  --  True if not yet initialized
--!          Zoom    : Float;            --  Field of view in degrees
--!          Quat    : Quaternion;       -- orientation of object
--!          Beginx  : Float;            --  Position of mouse
--!          Beginy  : Float;
--!          Object  : Lwobject;         --  lightwave object mesh
--!       end record;
--!
--!    type My_Glarea_Record is new Gtk_GLArea_Record with
--!       record
--!          Mesh_Info : Mesh_Info_Type;
--!       end record;
--!    type My_Glarea is access all My_Glarea_Record'Class;
--!
--!    package Event_Cb is new Gtk.Handlers.Return_Callback
--!      (My_Glarea_Record, Boolean);
--!    package Void_Cb is new Gtk.Handlers.Callback (My_Glarea_Record);
--!
--!    VIEW_ASPECT : constant Float := 1.3;
--!
--!    -------------
--!    -- Init_GL --
--!    -------------
--!
--!    procedure Init_GL is
--!       Light0_Pos   : constant GLfloat_Vec_4 := (-50.0, 50.0, 0.0, 0.0);
--!       Light0_Color : constant GLfloat_Vec_4 := (0.6, 0.6, 0.6, 1.0);
--!       Light1_Pos   : constant GLfloat_Vec_4 := (50.0, 50.0, 0.0, 0.0);
--!       Light1_Color : constant GLfloat_Vec_4 := (0.4, 0.4, 1.0, 1.0);
--!
--!    begin
--!
--!       --  Remove back faces
--!
--!       glDisable (GL_CULL_FACE);
--!       glEnable (GL_DEPTH_TEST);
--!
--!       --  Speedups
--!
--!       glDisable (GL_DITHER);
--!       glShadeModel (GL_SMOOTH);
--!       glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
--!       glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
--!
--!       --  Light
--!
--!       glLightfv (GL_LIGHT0, GL_POSITION, Light0_Pos);
--!       glLightfv (GL_LIGHT0, GL_DIFFUSE,  Light0_Color);
--!       glLightfv (GL_LIGHT1, GL_POSITION, Light1_Pos);
--!       glLightfv (GL_LIGHT1, GL_DIFFUSE,  Light1_Color);
--!       glEnable (GL_LIGHT0);
--!       glEnable (GL_LIGHT1);
--!       glEnable (GL_LIGHTING);
--!
--!       glColorMaterial (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
--!       glEnable (GL_COLOR_MATERIAL);
--!    end Init_GL;
--!
--!    -------------------
--!    -- Glarea_Expose --
--!    -------------------
--!
--!    function Glarea_Expose (Area  : access My_Glarea_Record'Class;
--!                            Event : Gdk_Event)
--!                           return Boolean
--!    is
--!       --  Event is an Expose_Event, but no need to cast, this is tested
--!       --  automatically by GtkAda
--!
--!       M : Trackball.Matrix;
--!
--!    begin
--!       --  Draw only the last expose event
--!
--!       if Get_Count (Event) > 0 then
--!          return True;
--!       end if;
--!
--!       --  OpenGL calls can be done only if make_current returns true
--!
--!       if Make_Current (Area) then
--!
--!          --  Basic initialization
--!          if Area.Mesh_Info.Do_Init then
--!             Init_GL;
--!             Area.Mesh_Info.Do_Init := False;
--!          end if;
--!
--!          --  View
--!          glMatrixMode (GL_PROJECTION);
--!          glLoadIdentity;
--!
--!          gluPerspective (Long_Float (Area.Mesh_Info.Zoom),
--!                          Long_Float (VIEW_ASPECT), 1.0, 100.0);
--!          glMatrixMode (GL_MODELVIEW);
--!
--!          --  Draw Object
--!          glClearColor (0.3, 0.4, 0.6, 1.0);
--!          glClear (GL_COLOR_BUFFER_BIT + GL_DEPTH_BUFFER_BIT);
--!
--!          glLoadIdentity;
--!          glTranslatef (0.0, 0.0, -30.0);
--!          Build_Rotmatrix (M, Area.Mesh_Info.Quat);
--!
--!          glMultMatrixf (M (0, 0)'Access);
--!
--!          Lw_Object_Show (Area.Mesh_Info.Object);
--!
--!          --  Swap backbuffer to front
--!          Swap_Buffers (Area);
--!       end if;
--!       return True;
--!    end Glarea_Expose;
--!
--!    ---------------
--!    -- Configure --
--!    ---------------
--!
--!    function Configure (Area : access My_Glarea_Record'Class;
--!                        Event : Gdk_Event)
--!                       return Boolean
--!    is
--!       pragma Warnings (Off, Event);
--!    begin
--!       if Make_Current (Area) then
--! #if WIN32 then
--!          glViewport (0, 0,
--!                      GLsizei (Get_Allocation_Width (Area)),
--!                      GLsizei (Get_Allocation_Height (Area)));
--! #else
--!          glViewport (0, 0,
--!                      Integer (Get_Allocation_Width (Area)),
--!                      Integer (Get_Allocation_Height (Area)));
--! #end if;
--!       end if;
--!       return True;
--!    end Configure;
--!
--!    --------------------
--!    -- GlArea_Destroy --
--!    --------------------
--!
--!    procedure GlArea_Destroy (Area : access My_Glarea_Record'Class)
--!    is
--!    begin
--!       Lw_Object_Free (Area.Mesh_Info.Object);
--!    end GlArea_Destroy;
--!
--!    ------------------
--!    -- Button_Press --
--!    ------------------
--!
--!    function Button_Press (Area : access My_Glarea_Record'Class;
--!                           Event : Gdk_Event)
--!                          return Boolean
--!    is
--!       --  Event is an Gdk_Event_Button, but no need to cast, this is tested
--!       --  automatically by GtkAda
--!    begin
--!       if Get_Button (Event) = 1 then
--!          Area.Mesh_Info.Beginx := Float (Get_X (Event));
--!          Area.Mesh_Info.Beginy := Float (Get_Y (Event));
--!          return True;
--!       end if;
--!       return False;
--!    end Button_Press;
--!
--!    -------------------
--!    -- Motion_Notify --
--!    -------------------
--!
--!    function Motion_Notify (Area : access My_Glarea_Record'Class;
--!                            Event : Gdk_Event)
--!                           return Boolean
--!    is
--!       --  Event is an Gdk_Event_Motion, but no need to cast, this is tested
--!       --  automatically by GtkAda
--!       X, Y : Gint;
--!       Win  : Gdk_Window;
--!       State : Gdk_Modifier_Type;
--!       Rect  : Gdk_Rectangle;
--!
--!    begin
--!       if Get_Is_Hint (Event) then
--!          Get_Pointer (Get_Window (Event), X, Y, State, Win);
--!       else
--!          X := Gint (Get_X (Event));
--!          Y := Gint (Get_Y (Event));
--!          State := Get_State (Event);
--!       end if;
--!       Rect.X := 0;
--!       Rect.Y := 0;
--!       Rect.Width  := Gint (Get_Allocation_Width (Area));
--!       Rect.Height := Gint (Get_Allocation_Height (Area));
--!
--!       if (State and Button1_Mask) /= 0 then
--!          --  Drag in progress, simulate trackball
--!          declare
--!             Spin_Quat : Trackball.Quaternion;
--!          begin
--!             Trackball.Trackball
--!               (Spin_Quat,
--!                (2.0 * Area.Mesh_Info.Beginx - Float (Rect.Width))
--!                   / Float (Rect.Width),
--!                (Float (Rect.Height) - 2.0 * Area.Mesh_Info.Beginy)
--!                   / Float (Rect.Height),
--!                (2.0 * Float (X) - Float (Rect.Width)) / Float (Rect.Width),
--!                (Float (Rect.Height) - 2.0 * Float (Y))
--!                 / Float (Rect.Height));
--!             Add_Quats (Spin_Quat, Area.Mesh_Info.Quat,
--!                        Dest => Area.Mesh_Info.Quat);
--!
--!             --  orientation has changed, redraw mesh
--!             Draw (Area, Rect);
--!          end;
--!       end if;
--!
--!       if (State and Button2_Mask) /= 0 then
--!          --  Zooming drag
--!          Area.Mesh_Info.Zoom := Area.Mesh_Info.Zoom +
--!            ((Float (Y) - Area.Mesh_Info.Beginy)
--!             / Float (Rect.Height)) * 40.0;
--!          if Area.Mesh_Info.Zoom < 5.0 then
--!             Area.Mesh_Info.Zoom := 5.0;
--!          end if;
--!          if Area.Mesh_Info.Zoom > 120.0 then
--!             Area.Mesh_Info.Zoom := 120.0;
--!          end if;
--!
--!          --  Zoom has changed, redraw mesh
--!          Draw (Area, Rect);
--!       end if;
--!
--!       Area.Mesh_Info.Beginx := Float (X);
--!       Area.Mesh_Info.Beginy := Float (Y);
--!       return True;
--!    end Motion_Notify;
--!
--!    -------------------
--!    -- Show_Lwobject --
--!    -------------------
--!
--!    procedure Show_Lwobject (Frame : access Gtk_Frame_Record'Class;
--!                             Lwobject_Name : String)
--!    is
--!       Object : Lwobject;
--!       Area   : My_Glarea;
--!
--!    begin
--!       --  Read lightwave object
--!       if not Lw_Is_Lwobject (Lwobject_Name) then
--!          Put_Line (Lwobject_Name & " is not a lightwave 3D object");
--!          return;
--!       end if;
--!
--!       Object := Lw_Object_Read (Lwobject_Name);
--!       if Object = Null_Lwobject then
--!          Put_Line ("can't read lightwave 3D object " & Lwobject_Name);
--!          return;
--!       end if;
--!
--!       Lw_Object_Scale (Object, 10.0 / Lw_Object_Radius (Object));
--!
--!       --  Create aspect frame
--!       --  Gtk_New (Frame, "", 0.5, 0.5, VIEW_ASPECT, False);
--!
--!       --  Create new OpenGL widget
--!       Area := new My_Glarea_Record;
--!       Initialize (Area,
--!                   (Gdk_GL_Rgba,
--!                    Gdk_GL_Red_Size, GL_Configs (1),
--!                    Gdk_GL_Green_Size, GL_Configs (1),
--!                    Gdk_GL_Blue_Size, GL_Configs (1),
--!                    Gdk_GL_Doublebuffer,
--!                    Gdk_GL_Depth_Size, GL_Configs (1)));
--!       if Area = null then
--!          Put_Line ("Can't create Gtk_GLArea widget");
--!          return;
--!       end if;
--!       Queue_Draw (Area);
--!
--!       --  Setup events and signals
--!       Set_Events (Area, Exposure_Mask or Button_Press_Mask
--!                   or Button_Release_Mask or Pointer_Motion_Mask
--!                   or Pointer_Motion_Hint_Mask);
--!       Event_Cb.Connect (Area, "expose_event",
--!                         Event_Cb.To_Marshaller (Glarea_Expose'Access));
--!       Event_Cb.Connect (Area, "motion_notify_event",
--!                         Event_Cb.To_Marshaller (Motion_Notify'Access));
--!       Event_Cb.Connect (Area, "button_press_event",
--!                         Event_Cb.To_Marshaller (Button_Press'Access));
--!       Event_Cb.Connect (Area, "configure_event",
--!                         Event_Cb.To_Marshaller (Configure'Access));
--!       Void_Cb.Connect (Area, "destroy",
--!                        Void_Cb.To_Marshaller (GlArea_Destroy'Access));
--!
--!       Set_USize (Area, 200, Gint (200.0 / VIEW_ASPECT));
--!
--!       --  Set up mesh info
--!       Area.Mesh_Info.Do_Init := True;
--!       Area.Mesh_Info.Object := Object;
--!       Area.Mesh_Info.Beginx := 0.0;
--!       Area.Mesh_Info.Beginy := 0.0;
--!       Area.Mesh_Info.Zoom   := 45.0;
--!       Trackball.Trackball (Area.Mesh_Info.Quat, 0.0, 0.0, 0.0, 0.0);
--!
--!       --  gtk_quit_add_destroy(1, GTK_OBJECT(window));
--!
--!       --  Put GlArea into Window and show it all
--!       Add (Frame, Area);
--!       Show_All (Frame);
--!    end Show_Lwobject;
--!
--!    ---------
--!    -- Run --
--!    ---------
--!
--!    procedure Run (Frame : access Gtk.Frame.Gtk_Frame_Record'Class) is
--!    begin
--!       if not Gdk.GL.Query then
--!          Put_Line ("OpenGL not supported");
--!          return;
--!       end if;
--!
--!       Show_Lwobject (Frame, "penguin.lwo");
--!    end Run;
--!
--! #else

   procedure Run (Frame : access Gtk.Frame.Gtk_Frame_Record'Class) is
      Label : Gtk_Label;
   begin
      Gtk_New (Label, "OpenGL has not been installed on this system");
      Add (Frame, Label);
      Show_All (Frame);
   end Run;

--! #end if;

end View_Gl;
