1 /*
2 * Copyright (C) 2004 Ivo Danihelka (ivo@danihelka.net)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 */
9 #include "VideoAgent.h"
10
11 #include "Log.h"
12 #include "Path.h"
13 #include "ImgException.h"
14 #include "SDLException.h"
15 #include "LogicException.h"
16 #include "AgentPack.h"
17 #include "SimpleMsg.h"
18 #include "StringMsg.h"
19 #include "UnknownMsgException.h"
20 #include "OptionAgent.h"
21 #include "SysVideo.h"
22
23 #include "SDL_image.h"
24 #include <stdlib.h> // atexit()
25
26 //-----------------------------------------------------------------
27 /**
28 * Init SDL and grafic window.
29 * Register watcher for "fullscren" and "screen_*" options.
30 * @throws SDLException if there is no usuable video mode
31 */
32 void
own_init()33 VideoAgent::own_init()
34 {
35 m_screen = NULL;
36 m_fullscreen = false;
37 if (SDL_Init(SDL_INIT_VIDEO) < 0) {
38 throw SDLException(ExInfo("Init"));
39 }
40 atexit(SDL_Quit);
41
42 setIcon(Path::dataReadPath("images/icon.png"));
43
44 registerWatcher("fullscreen");
45 initVideoMode();
46 }
47 //-----------------------------------------------------------------
48 /**
49 * Draw all drawer from list.
50 * First will be drawed first.
51 */
52 void
own_update()53 VideoAgent::own_update()
54 {
55 drawOn(m_screen);
56 SDL_Flip(m_screen);
57 }
58 //-----------------------------------------------------------------
59 /**
60 * Shutdown SDL.
61 */
62 void
own_shutdown()63 VideoAgent::own_shutdown()
64 {
65 SDL_Quit();
66 }
67
68 //-----------------------------------------------------------------
69 /**
70 * Load and set icon.
71 * @throws ImgException
72 */
73 void
setIcon(const Path & file)74 VideoAgent::setIcon(const Path &file)
75 {
76 SDL_Surface *icon = IMG_Load(file.getNative().c_str());
77 if (NULL == icon) {
78 throw ImgException(ExInfo("Load")
79 .addInfo("file", file.getNative()));
80 }
81
82 SDL_WM_SetIcon(icon, NULL);
83 SDL_FreeSurface(icon);
84 }
85
86 //-----------------------------------------------------------------
87 /**
88 * Init video mode along options.
89 * Change window only when necessary.
90 *
91 * @throws SDLException when video mode cannot be made,
92 * the old video mode remain usable
93 */
94 void
initVideoMode()95 VideoAgent::initVideoMode()
96 {
97 OptionAgent *options = OptionAgent::agent();
98 int screen_width = options->getAsInt("screen_width", 640);
99 int screen_height = options->getAsInt("screen_height", 480);
100
101 SysVideo::setCaption(options->getParam("caption", "A game"));
102 if (NULL == m_screen
103 || m_screen->w != screen_width
104 || m_screen->h != screen_height)
105 {
106 changeVideoMode(screen_width, screen_height);
107 }
108 }
109 //-----------------------------------------------------------------
110 /**
111 * Init new video mode.
112 * NOTE: m_screen pointer will change
113 */
114 void
changeVideoMode(int screen_width,int screen_height)115 VideoAgent::changeVideoMode(int screen_width, int screen_height)
116 {
117 OptionAgent *options = OptionAgent::agent();
118 int screen_bpp = options->getAsInt("screen_bpp", 32);
119 int videoFlags = getVideoFlags();
120 m_fullscreen = options->getAsBool("fullscreen", false);
121 if (m_fullscreen) {
122 videoFlags |= SDL_FULLSCREEN;
123 }
124
125 //TODO: check VideoModeOK and available ListModes
126 SDL_Surface *newScreen =
127 SDL_SetVideoMode(screen_width, screen_height, screen_bpp, videoFlags);
128 if (NULL == newScreen && (videoFlags & SDL_FULLSCREEN)) {
129 LOG_WARNING(ExInfo("unable to use fullscreen resolution, trying windowed")
130 .addInfo("width", screen_width)
131 .addInfo("height", screen_height)
132 .addInfo("bpp", screen_bpp));
133
134 videoFlags = videoFlags & ~SDL_FULLSCREEN;
135 newScreen = SDL_SetVideoMode(screen_width, screen_height, screen_bpp,
136 videoFlags);
137 }
138
139 if (newScreen) {
140 m_screen = newScreen;
141 //NOTE: must be two times to change MouseState
142 SDL_WarpMouse(screen_width / 2, screen_height / 2);
143 SDL_WarpMouse(screen_width / 2, screen_height / 2);
144 }
145 else {
146 throw SDLException(ExInfo("SetVideoMode")
147 .addInfo("width", screen_width)
148 .addInfo("height", screen_height)
149 .addInfo("bpp", screen_bpp));
150 }
151 }
152 //-----------------------------------------------------------------
153 /**
154 * Obtain video information about best video mode.
155 * @return best video flags
156 */
157 int
getVideoFlags()158 VideoAgent::getVideoFlags()
159 {
160 int videoFlags = 0;
161 videoFlags |= SDL_HWPALETTE;
162 videoFlags |= SDL_ANYFORMAT;
163 videoFlags |= SDL_SWSURFACE;
164
165 return videoFlags;
166 }
167 //-----------------------------------------------------------------
168 /**
169 * Toggle fullscreen.
170 */
171 void
toggleFullScreen()172 VideoAgent::toggleFullScreen()
173 {
174 int success = SDL_WM_ToggleFullScreen(m_screen);
175 if (success) {
176 m_fullscreen = !m_fullscreen;
177 }
178 else {
179 //NOTE: some platforms need reinit video
180 changeVideoMode(m_screen->w, m_screen->h);
181 }
182 }
183 //-----------------------------------------------------------------
184 /**
185 * Handle incoming message.
186 * Messages:
187 * - fullscreen ... toggle fullscreen
188 *
189 * @throws UnknownMsgException
190 */
191 void
receiveSimple(const SimpleMsg * msg)192 VideoAgent::receiveSimple(const SimpleMsg *msg)
193 {
194 if (msg->equalsName("fullscreen")) {
195 OptionAgent *options = OptionAgent::agent();
196 bool toggle = !(options->getAsBool("fullscreen"));
197 options->setPersistent("fullscreen", toggle);
198 }
199 else {
200 throw UnknownMsgException(msg);
201 }
202 }
203 //-----------------------------------------------------------------
204 /**
205 * Handle incoming message.
206 * Messages:
207 * - param_changed(fullscreen) ... handle fullscreen
208 *
209 * @throws UnknownMsgException
210 */
211 void
receiveString(const StringMsg * msg)212 VideoAgent::receiveString(const StringMsg *msg)
213 {
214 if (msg->equalsName("param_changed")) {
215 std::string param = msg->getValue();
216 if ("fullscreen" == param) {
217 bool fs = OptionAgent::agent()->getAsBool("fullscreen");
218 if (fs != m_fullscreen) {
219 toggleFullScreen();
220 }
221 }
222 else {
223 throw UnknownMsgException(msg);
224 }
225 }
226 else {
227 throw UnknownMsgException(msg);
228 }
229 }
230
231