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 * Copyright Karsten Heimrich, host.haiku@gmx.de. All rights reserved. 34 * Distributed under the terms of the MIT License. 35 */ 36 #include "Flurry.h" 37 38 #include <new> 39 #include <sys/time.h> 40 #include <time.h> 41 #include <unistd.h> 42 43 #include <Catalog.h> 44 45 #include "Shared.h" 46 #include "Smoke.h" 47 #include "Spark.h" 48 #include "Star.h" 49 #include "Texture.h" 50 51 52 using namespace BPrivate; 53 54 55 FlurryView::FlurryView(BRect bounds) 56 : 57 BGLView(bounds, (const char *)NULL, B_FOLLOW_ALL, B_FRAME_EVENTS | B_WILL_DRAW, 58 BGL_RGB | BGL_ALPHA | BGL_DEPTH | BGL_DOUBLE), 59 fOldFrameTime(-1.0), 60 fFlurryInfo_t(NULL) 61 { 62 B_TRANSLATE_MARK_SYSTEM_NAME_VOID("Flurry"); 63 64 fWidth = bounds.Width(); 65 fHeight = bounds.Height(); 66 fStartTime = _CurrentTime(); 67 68 LockGL(); 69 _SetupFlurryBaseInfo(); 70 UnlockGL(); 71 72 73 } 74 75 76 FlurryView::~FlurryView() 77 { 78 if (fFlurryInfo_t) { 79 LockGL(); 80 81 free(fFlurryInfo_t->s); 82 free(fFlurryInfo_t->star); 83 for (int32 i = 0; i < MAX_SPARKS; ++i) 84 free(fFlurryInfo_t->spark[i]); 85 free(fFlurryInfo_t); 86 87 UnlockGL(); 88 } 89 } 90 91 92 status_t 93 FlurryView::InitCheck() const 94 { 95 return (fFlurryInfo_t != NULL) ? B_OK : B_ERROR; 96 } 97 98 99 void 100 FlurryView::AttachedToWindow() 101 { 102 LockGL(); 103 104 BGLView::AttachedToWindow(); 105 106 MakeTexture(); 107 108 glDisable(GL_DEPTH_TEST); 109 glAlphaFunc(GL_GREATER, 0.0); 110 glEnable(GL_ALPHA_TEST); 111 glShadeModel(GL_FLAT); 112 glDisable(GL_LIGHTING); 113 glDisable(GL_CULL_FACE); 114 glEnable(GL_BLEND); 115 116 glViewport(0, 0, int(fWidth), int(fHeight)); 117 glMatrixMode(GL_PROJECTION); 118 glLoadIdentity(); 119 gluOrtho2D(0.0, fWidth, 0.0, fHeight); 120 glMatrixMode(GL_MODELVIEW); 121 glLoadIdentity(); 122 123 glClearColor(0.0, 0.0, 0.0, 1.0); 124 glClear(GL_COLOR_BUFFER_BIT); 125 126 glEnableClientState(GL_COLOR_ARRAY); 127 glEnableClientState(GL_VERTEX_ARRAY); 128 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 129 130 UnlockGL(); 131 } 132 133 134 void 135 FlurryView::DrawFlurryScreenSaver() 136 { 137 double deltaFrameTime = 0.0; 138 const double newFrameTime = _CurrentTime(); 139 140 GLfloat alpha = 1.0; 141 if (fOldFrameTime >= 0.0) { 142 deltaFrameTime = newFrameTime - fOldFrameTime; 143 alpha = 5.0 * deltaFrameTime; 144 145 if (alpha > 0.2) 146 alpha = 0.2; 147 } 148 149 fOldFrameTime = newFrameTime; 150 151 LockGL(); 152 153 // TODO: enable once double buffering is supported 154 //glDrawBuffer(GL_BACK); 155 156 glEnable(GL_BLEND); 157 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 158 159 glColor4f(0.0, 0.0, 0.0, alpha); 160 glRectd(0.0, 0.0, fWidth, fHeight); 161 162 fFlurryInfo_t->dframe++; 163 fFlurryInfo_t->fOldTime = fFlurryInfo_t->fTime; 164 fFlurryInfo_t->fTime = _SecondsSinceStart() + fFlurryInfo_t->randomSeed; 165 fFlurryInfo_t->fDeltaTime = fFlurryInfo_t->fTime - fFlurryInfo_t->fOldTime; 166 fFlurryInfo_t->drag = (float)pow(0.9965, fFlurryInfo_t->fDeltaTime * 85.0); 167 168 UpdateStar(fFlurryInfo_t, fFlurryInfo_t->star); 169 170 glEnable(GL_BLEND); 171 glShadeModel(GL_SMOOTH); 172 glBlendFunc(GL_SRC_ALPHA, GL_ONE); 173 174 for (int32 i = 0; i < fFlurryInfo_t->numStreams; ++i) { 175 fFlurryInfo_t->spark[i]->color[0] = 1.0; 176 fFlurryInfo_t->spark[i]->color[1] = 1.0; 177 fFlurryInfo_t->spark[i]->color[2] = 1.0; 178 fFlurryInfo_t->spark[i]->color[3] = 1.0; 179 180 UpdateSpark(fFlurryInfo_t, fFlurryInfo_t->spark[i]); 181 } 182 183 UpdateSmoke_ScalarBase(fFlurryInfo_t, fFlurryInfo_t->s); 184 185 glEnable(GL_BLEND); 186 glEnable(GL_TEXTURE_2D); 187 glBlendFunc(GL_SRC_ALPHA, GL_ONE); 188 189 const double brite = pow(deltaFrameTime, 0.75) * 10.0; 190 DrawSmoke_Scalar(fFlurryInfo_t, fFlurryInfo_t->s, 191 brite * fFlurryInfo_t->briteFactor); 192 193 glDisable(GL_TEXTURE_2D); 194 glDisable(GL_BLEND); 195 196 glFinish(); 197 198 SwapBuffers(); 199 UnlockGL(); 200 } 201 202 203 void 204 FlurryView::FrameResized(float newWidth, float newHeight) 205 { 206 LockGL(); 207 208 BGLView::FrameResized(newWidth, newHeight); 209 210 if (fFlurryInfo_t) { 211 fWidth = newWidth; 212 fHeight = newHeight; 213 214 fFlurryInfo_t->sys_glWidth = fWidth; 215 fFlurryInfo_t->sys_glHeight = fHeight; 216 217 glViewport(0, 0, int(fWidth), int(fHeight)); 218 glMatrixMode(GL_PROJECTION); 219 glLoadIdentity(); 220 gluOrtho2D(0.0, fWidth, 0.0, fHeight); 221 glMatrixMode(GL_MODELVIEW); 222 223 glClearColor(0.0, 0.0, 0.0, 1.0); 224 glClear(GL_COLOR_BUFFER_BIT); 225 226 glFlush(); 227 } 228 229 UnlockGL(); 230 } 231 232 233 void 234 FlurryView::_SetupFlurryBaseInfo() 235 { 236 fFlurryInfo_t = (flurry_info_t *)malloc(sizeof(flurry_info_t)); 237 238 if (!fFlurryInfo_t) 239 return; 240 241 fFlurryInfo_t->next = NULL; 242 fFlurryInfo_t->randomSeed = RandFlt(0.0, 300.0); 243 244 fFlurryInfo_t->dframe = 0; 245 fFlurryInfo_t->fOldTime = 0.0; 246 fFlurryInfo_t->sys_glWidth = fWidth; 247 fFlurryInfo_t->sys_glHeight = fHeight; 248 fFlurryInfo_t->fTime = _SecondsSinceStart() + fFlurryInfo_t->randomSeed; 249 fFlurryInfo_t->fDeltaTime = fFlurryInfo_t->fTime - fFlurryInfo_t->fOldTime; 250 251 fFlurryInfo_t->numStreams = 5; 252 fFlurryInfo_t->briteFactor = 1.0; 253 fFlurryInfo_t->streamExpansion = 10000.0; 254 fFlurryInfo_t->currentColorMode = tiedyeColorMode; 255 256 fFlurryInfo_t->s = (SmokeV*)malloc(sizeof(SmokeV)); 257 InitSmoke(fFlurryInfo_t->s); 258 259 fFlurryInfo_t->star = (Star*)malloc(sizeof(Star)); 260 InitStar(fFlurryInfo_t->star); 261 262 fFlurryInfo_t->star->rotSpeed = 1.0; 263 264 for (int32 i = 0; i < MAX_SPARKS; ++i) { 265 fFlurryInfo_t->spark[i] = (Spark*)malloc(sizeof(Spark)); 266 InitSpark(fFlurryInfo_t->spark[i]); 267 fFlurryInfo_t->spark[i]->mystery = 1800 * (i + 1) / 13; 268 UpdateSpark(fFlurryInfo_t, fFlurryInfo_t->spark[i]); 269 } 270 271 for (int32 i = 0; i < NUMSMOKEPARTICLES / 4; ++i) { 272 for (int32 k = 0; k < 4; ++k) 273 fFlurryInfo_t->s->p[i].dead.i[k] = 1; 274 } 275 } 276 277 278 double 279 FlurryView::_CurrentTime() const 280 { 281 return double(BDateTime::CurrentDateTime(B_LOCAL_TIME).Time_t() + 282 double(BTime::CurrentTime(B_LOCAL_TIME).Millisecond() / 1000.0)); 283 } 284 285 286 double 287 FlurryView::_SecondsSinceStart() const 288 { 289 return _CurrentTime() - fStartTime; 290 } 291 292 293 // #pragma mark - Flurry 294 295 296 extern "C" BScreenSaver* 297 instantiate_screen_saver(BMessage* archive, image_id imageId) 298 { 299 return new Flurry(archive, imageId); 300 } 301 302 303 Flurry::Flurry(BMessage* archive, image_id imageId) 304 : BScreenSaver(archive, imageId), 305 fFlurryView(NULL) 306 { 307 struct timeval tv; 308 gettimeofday(&tv, NULL); 309 310 srand((999 * tv.tv_sec) + (1001 * tv.tv_usec) + (1003 * getpid())); 311 } 312 313 314 Flurry::~Flurry() 315 { 316 } 317 318 319 status_t 320 Flurry::InitCheck() 321 { 322 return B_OK; 323 } 324 325 326 status_t 327 Flurry::StartSaver(BView* view, bool preview) 328 { 329 status_t status = B_ERROR; 330 331 if (preview) 332 return status; 333 334 SetTickSize(50000); 335 336 fFlurryView = new (std::nothrow) FlurryView(view->Bounds()); 337 if (fFlurryView) { 338 if (fFlurryView->InitCheck() != B_OK) { 339 delete fFlurryView; 340 fFlurryView = NULL; 341 } else { 342 status = B_OK; 343 view->AddChild(fFlurryView); 344 } 345 } 346 347 return status; 348 } 349 350 351 void 352 Flurry::StopSaver() 353 { 354 if (fFlurryView != NULL) 355 fFlurryView->EnableDirectMode(false); 356 } 357 358 359 void 360 Flurry::DirectDraw(int32 frame) 361 { 362 fFlurryView->DrawFlurryScreenSaver(); 363 } 364 365 366 void 367 Flurry::DirectConnected(direct_buffer_info* info) 368 { 369 // Enable or disable direct rendering 370 #if 1 371 if (fFlurryView != NULL) { 372 fFlurryView->DirectConnected(info); 373 fFlurryView->EnableDirectMode(true); 374 } 375 #endif 376 } 377 378 379 void 380 Flurry::StartConfig(BView* configView) 381 { 382 } 383 384 385 void 386 Flurry::StopConfig() 387 { 388 } 389 390 391 status_t 392 Flurry::SaveState(BMessage* into) const 393 { 394 return B_ERROR; 395 } 396