1 /*
2
3 Copyright (c) 2002, Calum Robinson
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8
9 * Redistributions of source code must retain the above copyright notice, this
10 list of conditions and the following disclaimer.
11
12 * Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15
16 * Neither the name of the author nor the names of its contributors may be used
17 to endorse or promote products derived from this software without specific
18 prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
24 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 */
32
33 /*
34 * Copyright Karsten Heimrich, host.haiku@gmx.de. All rights reserved.
35 * Distributed under the terms of the MIT License.
36 */
37
38
39 #include "Flurry.h"
40
41 #include <new>
42 #include <sys/time.h>
43 #include <time.h>
44 #include <unistd.h>
45
46 #include <Catalog.h>
47
48 #include "Shared.h"
49 #include "Smoke.h"
50 #include "Spark.h"
51 #include "Star.h"
52 #include "Texture.h"
53
54
55 using namespace BPrivate;
56
57
58 // #pragma mark - FlurryView
59
60
FlurryView(BRect bounds)61 FlurryView::FlurryView(BRect bounds)
62 :
63 BGLView(bounds, (const char *)NULL, B_FOLLOW_ALL,
64 B_FRAME_EVENTS | B_WILL_DRAW,
65 BGL_RGB | BGL_ALPHA | BGL_DEPTH | BGL_DOUBLE),
66 fOldFrameTime(-1.0),
67 fFlurryInfo(NULL)
68 {
69 B_TRANSLATE_MARK_SYSTEM_NAME_VOID("Flurry");
70
71 fWidth = bounds.Width();
72 fHeight = bounds.Height();
73 fStartTime = _CurrentTime();
74
75 LockGL();
76 _SetupFlurryBaseInfo();
77 UnlockGL();
78 }
79
80
~FlurryView()81 FlurryView::~FlurryView()
82 {
83 if (fFlurryInfo != NULL) {
84 LockGL();
85
86 free(fFlurryInfo->s);
87 free(fFlurryInfo->star);
88 for (int32 i = 0; i < MAX_SPARKS; ++i)
89 free(fFlurryInfo->spark[i]);
90 free(fFlurryInfo);
91
92 UnlockGL();
93 }
94 }
95
96
97 status_t
InitCheck() const98 FlurryView::InitCheck() const
99 {
100 return (fFlurryInfo != NULL) ? B_OK : B_ERROR;
101 }
102
103
104 void
AttachedToWindow()105 FlurryView::AttachedToWindow()
106 {
107 LockGL();
108
109 BGLView::AttachedToWindow();
110
111 MakeTexture();
112
113 glDisable(GL_DEPTH_TEST);
114 glAlphaFunc(GL_GREATER, 0.0);
115 glEnable(GL_ALPHA_TEST);
116 glShadeModel(GL_FLAT);
117 glDisable(GL_LIGHTING);
118 glDisable(GL_CULL_FACE);
119 glEnable(GL_BLEND);
120
121 glViewport(0, 0, int(fWidth), int(fHeight));
122 glMatrixMode(GL_PROJECTION);
123 glLoadIdentity();
124 gluOrtho2D(0.0, fWidth, 0.0, fHeight);
125 glMatrixMode(GL_MODELVIEW);
126 glLoadIdentity();
127
128 glClearColor(0.0, 0.0, 0.0, 1.0);
129 glClear(GL_COLOR_BUFFER_BIT);
130
131 glEnableClientState(GL_COLOR_ARRAY);
132 glEnableClientState(GL_VERTEX_ARRAY);
133 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
134
135 UnlockGL();
136 }
137
138
139 void
DrawFlurryScreenSaver()140 FlurryView::DrawFlurryScreenSaver()
141 {
142 double deltaFrameTime = 0.0;
143 const double newFrameTime = _CurrentTime();
144
145 GLfloat alpha = 1.0;
146 if (fOldFrameTime >= 0.0) {
147 deltaFrameTime = newFrameTime - fOldFrameTime;
148 alpha = 5.0 * deltaFrameTime;
149
150 if (alpha > 0.2)
151 alpha = 0.2;
152 }
153
154 fOldFrameTime = newFrameTime;
155
156 LockGL();
157
158 // TODO: enable once double buffering is supported
159 //glDrawBuffer(GL_BACK);
160
161 glEnable(GL_BLEND);
162 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
163
164 glColor4f(0.0, 0.0, 0.0, alpha);
165 glRectd(0.0, 0.0, fWidth, fHeight);
166
167 fFlurryInfo->dframe++;
168 fFlurryInfo->fOldTime = fFlurryInfo->fTime;
169 fFlurryInfo->fTime = _SecondsSinceStart() + fFlurryInfo->randomSeed;
170 fFlurryInfo->fDeltaTime = fFlurryInfo->fTime - fFlurryInfo->fOldTime;
171 fFlurryInfo->drag = (float)pow(0.9965, fFlurryInfo->fDeltaTime * 85.0);
172
173 UpdateStar(fFlurryInfo, fFlurryInfo->star);
174
175 glEnable(GL_BLEND);
176 glShadeModel(GL_SMOOTH);
177 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
178
179 for (int32 i = 0; i < fFlurryInfo->numStreams; ++i) {
180 fFlurryInfo->spark[i]->color[0] = 1.0;
181 fFlurryInfo->spark[i]->color[1] = 1.0;
182 fFlurryInfo->spark[i]->color[2] = 1.0;
183 fFlurryInfo->spark[i]->color[3] = 1.0;
184
185 UpdateSpark(fFlurryInfo, fFlurryInfo->spark[i]);
186 }
187
188 UpdateSmoke_ScalarBase(fFlurryInfo, fFlurryInfo->s);
189
190 glEnable(GL_BLEND);
191 glEnable(GL_TEXTURE_2D);
192 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
193
194 const double brite = pow(deltaFrameTime, 0.75) * 10.0;
195 DrawSmoke_Scalar(fFlurryInfo, fFlurryInfo->s,
196 brite * fFlurryInfo->briteFactor);
197
198 glDisable(GL_TEXTURE_2D);
199 glDisable(GL_BLEND);
200
201 glFinish();
202
203 SwapBuffers();
204 UnlockGL();
205 }
206
207
208 void
FrameResized(float newWidth,float newHeight)209 FlurryView::FrameResized(float newWidth, float newHeight)
210 {
211 LockGL();
212
213 BGLView::FrameResized(newWidth, newHeight);
214
215 if (fFlurryInfo != NULL) {
216 fWidth = newWidth;
217 fHeight = newHeight;
218
219 fFlurryInfo->sys_glWidth = fWidth;
220 fFlurryInfo->sys_glHeight = fHeight;
221
222 glViewport(0, 0, int(fWidth), int(fHeight));
223 glMatrixMode(GL_PROJECTION);
224 glLoadIdentity();
225 gluOrtho2D(0.0, fWidth, 0.0, fHeight);
226 glMatrixMode(GL_MODELVIEW);
227
228 glClearColor(0.0, 0.0, 0.0, 1.0);
229 glClear(GL_COLOR_BUFFER_BIT);
230
231 glFlush();
232 }
233
234 UnlockGL();
235 }
236
237
238 void
_SetupFlurryBaseInfo()239 FlurryView::_SetupFlurryBaseInfo()
240 {
241 fFlurryInfo = (flurry_info_t*)malloc(sizeof(flurry_info_t));
242
243 if (fFlurryInfo == NULL)
244 return;
245
246 fFlurryInfo->next = NULL;
247 fFlurryInfo->randomSeed = RandFlt(0.0, 300.0);
248
249 fFlurryInfo->dframe = 0;
250 fFlurryInfo->fOldTime = 0.0;
251 fFlurryInfo->sys_glWidth = fWidth;
252 fFlurryInfo->sys_glHeight = fHeight;
253 fFlurryInfo->fTime = _SecondsSinceStart() + fFlurryInfo->randomSeed;
254 fFlurryInfo->fDeltaTime = fFlurryInfo->fTime - fFlurryInfo->fOldTime;
255
256 fFlurryInfo->numStreams = 5;
257 fFlurryInfo->briteFactor = 1.0;
258 fFlurryInfo->streamExpansion = 10000.0;
259 fFlurryInfo->currentColorMode = tiedyeColorMode;
260
261 fFlurryInfo->s = (SmokeV*)malloc(sizeof(SmokeV));
262 InitSmoke(fFlurryInfo->s);
263
264 fFlurryInfo->star = (Star*)malloc(sizeof(Star));
265 InitStar(fFlurryInfo->star);
266
267 fFlurryInfo->star->rotSpeed = 1.0;
268
269 for (int32 i = 0; i < MAX_SPARKS; ++i) {
270 fFlurryInfo->spark[i] = (Spark*)malloc(sizeof(Spark));
271 InitSpark(fFlurryInfo->spark[i]);
272 fFlurryInfo->spark[i]->mystery = 1800 * (i + 1) / 13;
273 UpdateSpark(fFlurryInfo, fFlurryInfo->spark[i]);
274 }
275
276 for (int32 i = 0; i < NUMSMOKEPARTICLES / 4; ++i) {
277 for (int32 k = 0; k < 4; ++k)
278 fFlurryInfo->s->p[i].dead.i[k] = 1;
279 }
280 }
281
282
283 double
_CurrentTime() const284 FlurryView::_CurrentTime() const
285 {
286 return double(BDateTime::CurrentDateTime(B_LOCAL_TIME).Time_t() +
287 double(BTime::CurrentTime(B_LOCAL_TIME).Millisecond() / 1000.0));
288 }
289
290
291 double
_SecondsSinceStart() const292 FlurryView::_SecondsSinceStart() const
293 {
294 return _CurrentTime() - fStartTime;
295 }
296
297
298 // #pragma mark - Flurry
299
300
301 extern "C" BScreenSaver*
instantiate_screen_saver(BMessage * archive,image_id imageId)302 instantiate_screen_saver(BMessage* archive, image_id imageId)
303 {
304 return new Flurry(archive, imageId);
305 }
306
307
Flurry(BMessage * archive,image_id imageId)308 Flurry::Flurry(BMessage* archive, image_id imageId)
309 :
310 BScreenSaver(archive, imageId),
311 fFlurryView(NULL)
312 {
313 struct timeval tv;
314 gettimeofday(&tv, NULL);
315
316 srand((999 * tv.tv_sec) + (1001 * tv.tv_usec) + (1003 * getpid()));
317 }
318
319
~Flurry()320 Flurry::~Flurry()
321 {
322 }
323
324
325 status_t
InitCheck()326 Flurry::InitCheck()
327 {
328 return B_OK;
329 }
330
331
332 status_t
StartSaver(BView * view,bool preview)333 Flurry::StartSaver(BView* view, bool preview)
334 {
335 status_t result = B_ERROR;
336
337 SetTickSize(50000);
338
339 fFlurryView = new (std::nothrow) FlurryView(view->Bounds());
340 if (fFlurryView != NULL) {
341 if (fFlurryView->InitCheck() != B_OK) {
342 delete fFlurryView;
343 fFlurryView = NULL;
344 } else {
345 result = B_OK;
346 view->AddChild(fFlurryView);
347 }
348 }
349
350 return result;
351 }
352
353
354 void
StopSaver()355 Flurry::StopSaver()
356 {
357 if (fFlurryView != NULL)
358 fFlurryView->EnableDirectMode(false);
359 }
360
361
362 void
Draw(BView *,int32 frame)363 Flurry::Draw(BView*, int32 frame)
364 {
365 fFlurryView->DrawFlurryScreenSaver();
366 }
367
368
369 void
DirectConnected(direct_buffer_info * info)370 Flurry::DirectConnected(direct_buffer_info* info)
371 {
372 if (fFlurryView != NULL) {
373 fFlurryView->DirectConnected(info);
374 fFlurryView->EnableDirectMode(true);
375 }
376 }
377
378
379 void
StartConfig(BView * configView)380 Flurry::StartConfig(BView* configView)
381 {
382 }
383
384
385 void
StopConfig()386 Flurry::StopConfig()
387 {
388 }
389
390
391 status_t
SaveState(BMessage * into) const392 Flurry::SaveState(BMessage* into) const
393 {
394 return B_ERROR;
395 }
396