1. -- 
  2. -- Copyright (c) 2012 Kevin Wellwood 
  3. -- All rights reserved. 
  4. -- 
  5. -- This source code is distributed under the Modified BSD License. For terms and 
  6. -- conditions, see license.txt. 
  7. -- 
  8.  
  9. with Events.Corrals;                    use Events.Corrals; 
  10. with Events.Listeners;                  use Events.Listeners; 
  11. with Objects;                           use Objects; 
  12. with Processes;                         use Processes; 
  13. with Widgets;                           use Widgets; 
  14. with Widgets.Containers.Windows;        use Widgets.Containers.Windows; 
  15.  
  16. private with Ada.Containers.Indefinite_Hashed_Maps; 
  17. private with Ada.Strings.Hash_Case_Insensitive; 
  18. private with Audio_Players; 
  19. private with Events; 
  20. private with Input_Handlers; 
  21. private with Processes.Managers; 
  22. private with Renderers; 
  23.  
  24. package Game_Views is 
  25.  
  26.     -- The Game_View class is parent object in the View system, which is 
  27.     -- responsible for managing all user input/output for the game. This 
  28.     -- includes receiving mouse and keyboard input, rendering the screen and 
  29.     -- playing audio. No game logic is performed by the view, it only receives 
  30.     -- input and displays a view of the current game state (graphically and 
  31.     -- audibly) for the user. 
  32.     -- 
  33.     -- The Game_View provides a Process_Manager to service the view system, a 
  34.     -- Corral to receive events sent to listeners in the view, and a various 
  35.     -- child objects to handle screen drawing, input capturing, and audio 
  36.     -- playback. The Game_View itself is a Process and Event_Listener that is 
  37.     -- attached to its own Process_Manager and Corral facilities. 
  38.     type Game_View is abstract new Limited_Object and 
  39.                                    Event_Listener and 
  40.                                    Process with private; 
  41.     type A_Game_View is access all Game_View'Class; 
  42.     pragma No_Strict_Aliasing( A_Game_View ); 
  43.  
  44.     -- Creates and returns a new Game_View object using the registered allocator 
  45.     -- function. An exception will be raised if no allocator is registered. 
  46.     function Create_Game_View( xres, yres : Positive; 
  47.                                scale      : Positive ) return A_Game_View; 
  48.     pragma Postcondition( Create_Game_View'Result /= null ); 
  49.  
  50.     -- Attachs a Process to the view's Process_Manager. 
  51.     procedure Attach( this    : not null access Game_View'Class; 
  52.                       process : not null A_Process ); 
  53.  
  54.     -- Detaches a Process from the view's Process_Manager. 
  55.     procedure Detach( this    : not null access Game_View'Class; 
  56.                       process : not null A_Process ); 
  57.  
  58.     -- Returns the view's Corral. The view creates its corral at construction. 
  59.     function Get_Corral( this : not null access Game_View'Class ) return A_Corral; 
  60.     pragma Postcondition( Get_Corral'Result /= null ); 
  61.  
  62.     -- Returns a widget in the registry by id. Raises exception ID_NOT_FOUND if 
  63.     -- the widget does not exist. 
  64.     function Get_Widget( this : not null access Game_View'Class; 
  65.                          id   : String ) return A_Widget; 
  66.     pragma Postcondition( Get_Widget'Result /= null ); 
  67.  
  68.     -- Returns the view's Window widget. This will return null if the window has 
  69.     -- not yet been set. 
  70.     function Get_Window( this : not null access Game_View'Class ) return A_Window; 
  71.  
  72.     -- Adds a widget to the view's widget registry. Raises exception 
  73.     -- DUPLICATE_ID if a widget with the same id is already registered. 
  74.     procedure Register( this   : not null access Game_View'Class; 
  75.                         widget : not null A_Widget ); 
  76.  
  77.     -- Sets the view's Window widget. If 'window' is null, the view's Window 
  78.     -- will be removed. The window can only be set before the view is started. 
  79.     -- All attempts to change the window after the view has been started will be 
  80.     -- ignored. The view's Renderer is deleted and recreated when its Window is 
  81.     -- changed. If this procedure raises an exception, the view will be left 
  82.     -- without a Window. 
  83.     procedure Set_Window( this   : not null access Game_View'Class; 
  84.                           window : A_Window ); 
  85.  
  86.     -- Starts the game view, attaching it to the framework. This will attach 
  87.     -- event listeners, processes, start the view's subsystems (audio, etc) 
  88.     -- and begin running the view's Process_Manager. If the view has already 
  89.     -- been started then this will do nothing. Start_View will be called at the 
  90.     -- end of this procedure. 
  91.     procedure Start( this : not null access Game_View'Class ); 
  92.  
  93.     -- Stops the game view, detaching it from the framework. This must be called 
  94.     -- after Start and before deleting the object. If the view has not been 
  95.     -- started or has already been stopped, this will do nothing. Stop_View will 
  96.     -- be called at the beginning of this procedure. 
  97.     procedure Stop( this : not null access Game_View'Class ); 
  98.  
  99.     -- Removes a widget from the view's registry. If the widget is not 
  100.     -- registered, nothing happens. 
  101.     procedure Unregister( this : not null access Game_View'Class; id : String ); 
  102.     pragma Precondition( id'Length > 0 ); 
  103.  
  104.     -- Deletes the Game_View. 
  105.     procedure Delete( this : in out A_Game_View ); 
  106.     pragma Postcondition( this = null ); 
  107.  
  108.     ---------------------------------------------------------------------------- 
  109.  
  110.     -- raised on attempt to register a widget with a duplicate id 
  111.     DUPLICATE_ID : exception; 
  112.  
  113.     -- raised on attempt to access an registered widget by id 
  114.     ID_NOT_FOUND : exception; 
  115.  
  116. private 
  117.  
  118.     use Audio_Players; 
  119.     use Events; 
  120.     use Input_Handlers; 
  121.     use Processes.Managers; 
  122.     use Renderers; 
  123.  
  124.     -- A Widget_Registry maps widget ids to widget references. The registry will 
  125.     -- contain references to all created widgets, whether they are parented or 
  126.     -- not. 
  127.     package Widget_Registry is new Ada.Containers.Indefinite_Hashed_Maps( 
  128.         String, A_Widget, Ada.Strings.Hash_Case_Insensitive, "=", "=" ); 
  129.     use Widget_Registry; 
  130.  
  131.     ----------------------------------------------------------------------------- 
  132.  
  133.     type Game_View is abstract new Limited_Object and 
  134.                                    Event_Listener and 
  135.                                    Process with 
  136.         record 
  137.             started, 
  138.             stopped     : Boolean := False; 
  139.             paused      : Boolean := False; 
  140.             win         : A_Window := null; 
  141.             renderer    : A_Renderer := null; 
  142.             audioPlayer : A_Audio_Player := null; 
  143.             inhandler   : A_Input_Handler := null; 
  144.             pman        : A_Process_Manager := null; 
  145.             corral      : A_Corral := null; 
  146.             widgets     : Widget_Registry.Map; 
  147.         end record; 
  148.  
  149.     procedure Construct( this : access Game_View ); 
  150.  
  151.     procedure Delete( this : in out Game_View ); 
  152.  
  153.     function Get_Process_Name( this : access Game_View ) return String; 
  154.     pragma Postcondition( Get_Process_Name'Result'Length > 0 ); 
  155.  
  156.     -- Called when the window is requested to close by the OS. The default 
  157.     -- implementation is to simply queue a Queue_Close_Window message which will 
  158.     -- exit the application. Override this procedure if a confirmation dialog 
  159.     -- or some other activity must happen instead. 
  160.     procedure Handle_Close_Request( this : access Game_View ); 
  161.  
  162.     -- Handles all events that the Game_View is registered to receive. 
  163.     procedure Handle_Event( this : access Game_View; 
  164.                             evt  : in out A_Event; 
  165.                             resp : out Response_Type ); 
  166.     pragma Precondition( evt /= null ); 
  167.  
  168.     -- Called when resource loading is beginning and ending. Override this 
  169.     -- procedure to display a message, etc during loading. 
  170.     procedure Handle_Loading( this : access Game_View; loading : Boolean ) is null; 
  171.  
  172.     -- Called when the game logic is paused or resumed. Override this procedure 
  173.     -- to perform actions when the game pause state changes. 
  174.     procedure Handle_Paused( this : access Game_View; paused : Boolean ) is null; 
  175.  
  176.     -- Called as part of Start, this procedure can be overridden to add the view 
  177.     -- as a listener for various events or anything else that needs to be done 
  178.     -- at start time. 
  179.     procedure Start_View( this : access Game_View ) is null; 
  180.  
  181.     -- Called as part of Stop, this procedure can be overridden to do anything 
  182.     -- that needs to be done at stop time. For example, any events the view was 
  183.     -- registered to receive in Start_View should be unregistered here. 
  184.     procedure Stop_View( this : access Game_View ) is null; 
  185.  
  186.     -- Executes the Game_View logic. Overriding implementations must call this 
  187.     -- first. 
  188.     procedure Tick( this : access Game_View; time : Tick_Time ); 
  189.  
  190.     ---------------------------------------------------------------------------- 
  191.  
  192.     -- An allocator function for a concrete Game_View implemenation. 'xres' and 
  193.     -- 'yres' are the requested application resolution. 'scale' is a multiplier 
  194.     -- to enlarge small resolutions. For example, if the view requested a 
  195.     -- 320x200 resolution, a scale of 2 would cause the application to actually 
  196.     -- display a 640x400 window and upscale the contents. The view would draw to 
  197.     -- the window as though it were the requested resolution. 
  198.     type Allocator is 
  199.         access function( xres, yres : Positive; 
  200.                          scale      : Positive ) return A_Game_View; 
  201.  
  202.     -- Registers the allocator function used by Create_Game_View to create an 
  203.     -- instance of the appropriate concrete Game_View subclass. This should be 
  204.     -- called at elaboration time. 
  205.     procedure Register_Allocator( allocate : not null Allocator ); 
  206.  
  207. end Game_Views;