1/* 2 3Copyright (c) 2002, Calum Robinson 4All rights reserved. 5 6Redistribution and use in source and binary forms, with or without 7modification, 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 20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 24ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 27ANY 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 29SOFTWARE, 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 55using namespace BPrivate; 56 57 58// #pragma mark - FlurryView 59 60 61FlurryView::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 81FlurryView::~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 97status_t 98FlurryView::InitCheck() const 99{ 100 return (fFlurryInfo != NULL) ? B_OK : B_ERROR; 101} 102 103 104void 105FlurryView::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 139void 140FlurryView::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 208void 209FlurryView::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 238void 239FlurryView::_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 283double 284FlurryView::_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 291double 292FlurryView::_SecondsSinceStart() const 293{ 294 return _CurrentTime() - fStartTime; 295} 296 297 298// #pragma mark - Flurry 299 300 301extern "C" BScreenSaver* 302instantiate_screen_saver(BMessage* archive, image_id imageId) 303{ 304 return new Flurry(archive, imageId); 305} 306 307 308Flurry::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 320Flurry::~Flurry() 321{ 322} 323 324 325status_t 326Flurry::InitCheck() 327{ 328 return B_OK; 329} 330 331 332status_t 333Flurry::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 354void 355Flurry::StopSaver() 356{ 357 if (fFlurryView != NULL) 358 fFlurryView->EnableDirectMode(false); 359} 360 361 362void 363Flurry::Draw(BView*, int32 frame) 364{ 365 fFlurryView->DrawFlurryScreenSaver(); 366} 367 368 369void 370Flurry::DirectConnected(direct_buffer_info* info) 371{ 372 if (fFlurryView != NULL) { 373 fFlurryView->DirectConnected(info); 374 fFlurryView->EnableDirectMode(true); 375 } 376} 377 378 379void 380Flurry::StartConfig(BView* configView) 381{ 382} 383 384 385void 386Flurry::StopConfig() 387{ 388} 389 390 391status_t 392Flurry::SaveState(BMessage* into) const 393{ 394 return B_ERROR; 395} 396