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 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 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 98 FlurryView::InitCheck() const 99 { 100 return (fFlurryInfo != NULL) ? B_OK : B_ERROR; 101 } 102 103 104 void 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 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 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 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 284 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 292 FlurryView::_SecondsSinceStart() const 293 { 294 return _CurrentTime() - fStartTime; 295 } 296 297 298 // #pragma mark - Flurry 299 300 301 extern "C" BScreenSaver* 302 instantiate_screen_saver(BMessage* archive, image_id imageId) 303 { 304 return new Flurry(archive, imageId); 305 } 306 307 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 320 Flurry::~Flurry() 321 { 322 } 323 324 325 status_t 326 Flurry::InitCheck() 327 { 328 return B_OK; 329 } 330 331 332 status_t 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 355 Flurry::StopSaver() 356 { 357 if (fFlurryView != NULL) 358 fFlurryView->EnableDirectMode(false); 359 } 360 361 362 void 363 Flurry::DirectDraw(int32 frame) 364 { 365 fFlurryView->DrawFlurryScreenSaver(); 366 } 367 368 369 void 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 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