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