1 /* 2 * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Copyright 2015, Augustin Cavalier <waddlesplash>. All rights reserved. 4 * Distributed under the terms of the MIT License. 5 * 6 * Effect from corTeX / Optimum. 7 */ 8 9 10 #include <AppKit.h> 11 #include <Catalog.h> 12 #include <ColorMenuItem.h> 13 #include <ControlLook.h> 14 #include <InterfaceKit.h> 15 #include <LayoutBuilder.h> 16 #include <MenuField.h> 17 #include <ScreenSaver.h> 18 #include <String.h> 19 #include <SupportDefs.h> 20 #include <Window.h> 21 22 #include <math.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 27 28 #undef B_TRANSLATION_CONTEXT 29 #define B_TRANSLATION_CONTEXT "Nebula Screen Saver" 30 31 32 typedef struct 33 { 34 int x, y, z, r; 35 } p3; 36 37 typedef float matrix[3][3]; 38 39 #define GMAX 5000 40 p3 gal[GMAX]; 41 float precos[512]; 42 float presin[512]; 43 44 typedef unsigned short word; 45 46 extern "C" { 47 #include "Draw.h" 48 #include "DrawStars.h" 49 } 50 51 const uint32 kMsgWidth = 'widt'; 52 const uint32 kMsgColorScheme = 'cols'; 53 const uint32 kMsgBlankBorders = 'blbr'; 54 const uint32 kMsgMotionBlur = 'blur'; 55 const uint32 kMsgSpeed = 'sped'; 56 const uint32 kMsgFrames = 'mfps'; 57 58 float gSpeed; 59 bool gMotionBlur; 60 int32 gSettingsWidth; 61 int32 gWidth; 62 int32 gHeight; 63 float gMaxFramesPerSecond; 64 BBitmap* gBitmap; 65 BScreenSaver* gScreenSaver; 66 uint32 gPalette[256]; 67 int8 gPaletteScheme; 68 int8 gBlankBorders; 69 char* gBuffer8; /* working 8bit buffer */ 70 71 72 inline float 73 ocos(float a) 74 { 75 return (precos[(int)(a * 256 / M_PI) & 511]); 76 } 77 78 inline float 79 osin(float a) 80 { 81 return (presin[(int)(a * 256 / M_PI) & 511]); 82 } 83 84 85 void 86 mulmat(matrix* a, matrix* b, matrix* c) 87 { 88 int i, j; 89 90 for (i = 0; i < 3; i++) { 91 for (j = 0; j < 3; j++) { 92 (*c)[i][j] = (*a)[i][0] * (*b)[0][j] + 93 (*a)[i][1] * (*b)[1][j] + 94 (*a)[i][2] * (*b)[2][j]; 95 } 96 } 97 } 98 99 100 inline void 101 mulvec(matrix* a, float* x, float* y, float* z) 102 { 103 float nx = *x, ny = *y, nz = *z; 104 105 *x = nx * (*a)[0][0] + ny * (*a)[0][1] + nz * (*a)[0][2]; 106 *y = nx * (*a)[1][0] + ny * (*a)[1][1] + nz * (*a)[1][2]; 107 *z = nx * (*a)[2][0] + ny * (*a)[2][1] + nz * (*a)[2][2]; 108 } 109 110 111 void 112 setrmat(float a, float b, float c, matrix* m) 113 { 114 int i, j; 115 for (i = 0; i < 3; i++) 116 for (j = 0; j < 3; j++) 117 (*m)[i][j] = (float)(i == j); 118 119 if (a != 0) { 120 (*m)[0][0] = cos(a); (*m)[0][1] = sin(a); 121 (*m)[1][0] = sin(a); (*m)[1][1] = -cos(a); 122 return; 123 } 124 if (b != 0) { 125 (*m)[0][0] = cos(b); (*m)[0][2] = sin(b); 126 (*m)[2][0] = sin(b); (*m)[2][2] = -cos(b); 127 return; 128 } 129 (*m)[1][1] = cos(c); (*m)[1][2] = sin(c); 130 (*m)[2][1] = sin(c); (*m)[2][2] = -cos(c); 131 } 132 133 134 void 135 rotate3d(float* xr, float* yr, float* zr, /* point to rotate */ 136 float ax, float ay, float az) /* the 3 angles (order ?..) */ 137 { 138 float xr2, yr2, zr2; 139 140 xr2 = (*xr * ocos(az) + *yr * osin(az)); 141 yr2 = (*xr * osin(az) - *yr * ocos(az)); 142 *xr = xr2; 143 *yr = yr2; 144 145 xr2 = (*xr * ocos(ay) + *zr * osin(ay)); 146 zr2 = (*xr * osin(ay) - *zr * ocos(ay)); 147 *xr = xr2; 148 *zr = zr2; 149 150 zr2 = (*zr * ocos(ax) + *yr * osin(ax)); 151 yr2 = (*zr * osin(ax) - *yr * ocos(ax)); 152 *zr = zr2; 153 *yr = yr2; 154 } 155 156 157 void 158 drawshdisk(int x0, int y0, int r) 159 { 160 int x = 0; 161 int y; 162 int ly; /* last y */ 163 int delta; 164 int c; /* color at center */ 165 int d; /* delta */ 166 167 #define SLIMIT 17 168 #define SRANGE 15 169 170 if (r <= SLIMIT) { 171 /* range checking is already (more or less) done... */ 172 draw_stars(gWidth, &gBuffer8[x0 + gWidth * y0], 10 + r * 5); 173 //gBuffer8[x0 + W * y0] = 10 + r * 5; 174 return; 175 } 176 177 if (r < SLIMIT + SRANGE) 178 r = ((r - SLIMIT) * SLIMIT) / SRANGE + 1; 179 180 y = ly = r; /* AAaargh */ 181 delta = 3 - 2 * r; 182 183 do { 184 if (y != ly) { 185 /* dont overlap these lines */ 186 c = ((r - y + 1) << 13) / r; 187 d = -c / (x + 1); 188 189 if (y == x + 1) /* this would overlap with the next x lines */ 190 goto TOTO; /* WHY NOT */ 191 192 /* note : for "normal" numbers (not too big) : 193 (unsigned int)(x) < M <=> 0<=x<H 194 (because if x<0, then (unsigned)(x) = 2**32-|x| which is 195 BIG and thus >H ) 196 197 This is clearly a stupid, unmaintanable, unreadable 198 "optimization". But i like it :) 199 */ 200 if ((uint32)(y0 - y - 1) < gHeight - 3) 201 memshset(&gBuffer8[x0 + gWidth * (y0 - y + 1)], c, d, x); 202 203 if ((uint32)(y0 + y - 1) < gHeight - 3) 204 memshset(&gBuffer8[x0 + gWidth*(y0 + y)], c, d, x); 205 } 206 TOTO: 207 c = ((r - x + 1) << 13) / r; 208 d = -c / (y); 209 210 if ((uint32)(y0 - x - 1) < gHeight - 3) 211 memshset(&gBuffer8[x0 + gWidth*(y0 - x)], c, d, y); 212 if ((uint32)(y0 + x - 1) < gHeight - 3) 213 memshset(&gBuffer8[x0 + gWidth * (y0 + x + 1)], c, d, y); 214 215 ly = y; 216 if (delta < 0) 217 delta += 4 * x + 6; 218 else { 219 delta += 4 * (x - y) + 10; 220 y--; 221 } 222 x++; 223 } while (x < y); 224 } 225 226 227 void 228 drawGalaxy() 229 { 230 int r; 231 int x, y; 232 float rx, ry, rz; 233 int i; 234 float oa, ob, oc; 235 float t; 236 float a, b, c; 237 matrix ma, mb, mc, mr; 238 239 /* t is the parametric coordinate for the animation; 240 change the scale value to change the speed of anim 241 (independant of processor speed) 242 */ 243 static bigtime_t firstTime = system_time(); 244 t = ((double)gSpeed * system_time() - firstTime) / 1000000.0; 245 //opti_scale_time(0.418, &demo_elapsed_time); 246 247 a = 0.9 * t; 248 b = t; 249 c = 1.1 * t; 250 251 setrmat(a, 0, 0, &ma); 252 setrmat(0, b, 0, &mb); 253 mulmat(&ma, &mb, &mc); 254 setrmat(0, 0, c, &ma); 255 mulmat(&ma, &mc, &mr); 256 257 oa = 140 * osin(a); 258 ob = 140 * ocos(b); 259 oc = 240 * osin(c); 260 261 if (gMotionBlur) { 262 /* mblur does something like that: 263 * (or did, perhaps it's another version!..) 264 265 for (i = 0; i < W * H; i++) 266 gBuffer8[i]= (gBuffer8[i] >> 3) + (gBuffer8[i] >> 1); 267 */ 268 mblur (gBuffer8, gWidth * gHeight); 269 } else 270 memset(gBuffer8, 0, gWidth * gHeight); 271 272 for (i = 0; i < GMAX; i++) { 273 rx = gal[i].x; 274 ry = gal[i].y; 275 rz = gal[i].z; 276 277 mulvec(&mr, &rx, &ry, &rz); 278 279 rx += oa; 280 ry += ob; 281 rz += oc; 282 rz += 300; 283 284 if (rz > 5) { 285 x = (int)(15 * rx / (rz / 5 + 1)) + gWidth / 2; 286 /* tain jcomprend plus rien */ 287 y = (int)(15 * ry/ (rz / 5 + 1)) + gHeight / 2; 288 /* a ces formules de daube !! */ 289 r = (int)(3 * gal[i].r / (rz / 4 + 3)) + 2; 290 291 if (x > 5 && x < gWidth - 6 && y > 5 && y < gHeight - 6) 292 // if ((uint32)x < gWidth - 1 && (uint32)y < gHeight - 1) 293 drawshdisk(x, y, r); 294 } 295 } 296 } 297 298 299 void 300 setPalette() 301 { 302 int i; 303 304 switch (gPaletteScheme) { 305 case 0: // yellow 306 default: 307 for (i = 0; i < 30; i++) 308 gPalette[i] = (uint8)(i * 8 / 10) << 16 309 | (uint8)(i * 6 / 10) << 8; 310 // | (uint8)(i*3/10); 311 312 for (i = 30; i < 256; i++) { 313 uint8 r = (i); 314 uint8 g = (i * i >> 8); //(i*8/10); 315 uint8 b = i >= 240 ? (i - 240) << 3 : 0; //(i * 2 / 10); 316 317 gPalette[i] = ((r << 16) | (g << 8) | (b)); 318 } 319 break; 320 321 case 1: // blue 322 for (i = 0; i < 30; i++) 323 gPalette[i] = (uint8)(i * 8 / 10); 324 // << 16 | (uint8)(i * 6 / 10) << 8; 325 // | (uint8)(i * 3 / 10); 326 327 for (i = 30; i < 256; i++) { 328 uint8 b = (i); 329 uint8 g = (i * i >> 8); //(i * 8 / 10); 330 uint8 r = i >= 240 ? (i - 240) << 3 : 0; //(i * 2 / 10); 331 332 gPalette[i] = ((r << 16) | (g << 8) | (b)); 333 } 334 break; 335 336 case 2: // red 337 for (i = 0; i < 128; i++) 338 gPalette[i] = (uint8)i << 16; 339 // << 16 | (uint8)(i * 6/10) << 8; 340 // | (uint8)(i * 3 / 10); 341 342 for (i = 128;i < 256;i++) 343 { 344 uint8 r = i; 345 uint8 c = (uint8)((cos((i - 256) / 42.0) * 0.5 + 0.5) * 225); 346 347 gPalette[i] = ((r << 16) | (c << 8) | c); 348 } 349 /* for (i = 192; i < 224; i++) 350 { 351 uint8 c = (i - 192); 352 gPalette[i] = gPalette[i] & 0xff0000 | c << 8 | c; 353 } 354 for (i = 224; i < 256; i++) 355 { 356 uint8 c = (i-224) / 2; 357 c = 32 + c * c * 6 / 10; 358 gPalette[i] = gPalette[i] & 0xff0000 | c << 8 | c; 359 } 360 */ break; 361 362 case 3: // green 363 for (i = 0; i < 30; i++) 364 gPalette[i] = (uint8)(i * 8 / 10) << 8; 365 // << 16 | (uint8)(i * 6 / 10) << 8; 366 // | (uint8)(i * 3 / 10); 367 368 for (i = 30; i < 256; i++) { 369 uint8 g = (i); 370 uint8 r = (i * i >> 8); //(i * 8 / 10); 371 uint8 b = i >= 240 ? (i-240) << 3 : 0; //(i * 2 / 10); 372 373 gPalette[i] = ((r << 16) | (g << 8) | (b)); 374 } 375 break; 376 377 case 4: // grey 378 for (i = 0; i < 256; i++) { 379 uint8 c = i * 15 / 16 + 10; 380 gPalette[i] = c << 16 | c << 8 | c; 381 } 382 break; 383 case 5: // cold 384 for (i = 0; i < 30; i++) 385 gPalette[i] = (uint8)(i * 8 / 10) << 16; 386 // << 16 | (uint8)(i * 6 / 10) << 8; 387 // | (uint8)(i * 3 / 10); 388 389 for (i = 30; i < 256; i++) { 390 uint8 r = i; 391 uint8 c = (uint8)((cos((i - 255) / 82.0) * 0.5 + 0.5) * 255); 392 393 gPalette[i] = ((r << 16) | (c << 8) | c); 394 } 395 break; 396 397 case 6: // original 398 for (i = 0; i < 256; i++) { 399 uint32 c = *(char *)&i; 400 gPalette[i] = c << 16 | c << 8; 401 } 402 break; 403 } 404 /* for (i = 0;i < 256;i++) 405 { 406 uint8 r = (i); 407 uint8 g = (i * i >> 8); //(i * 8 / 10); 408 uint8 b = 0; //(i * 2 / 10); 409 410 gPalette[i] = ((r << 16) | (g << 8) | (b)); 411 } 412 */ 413 /* for (i = 240; i < 256; i++) 414 gPalette[i] = (uint8)i << 16 | (uint8)i << 8 | (uint8)(i * 6 / 10); 415 */ 416 } 417 418 419 // #pragma mark - SimpleSlider 420 421 422 class SimpleSlider : public BSlider { 423 public: 424 SimpleSlider(const char* label, BMessage* message) 425 : 426 BSlider(B_EMPTY_STRING, B_EMPTY_STRING, message, 1, 100, B_HORIZONTAL) 427 { 428 SetLimitLabels("1", "100"); 429 SetHashMarks(B_HASH_MARKS_BOTTOM); 430 SetHashMarkCount(11); 431 fLabel = label; 432 }; 433 434 const char* UpdateText() const 435 { 436 fText.SetToFormat("%s: %d", fLabel, Value()); 437 return fText.String(); 438 }; 439 440 private: 441 mutable BString fText; 442 const char* fLabel; 443 }; 444 445 446 // #pragma mark - SettingsView 447 448 449 class SettingsView : public BView { 450 public: 451 SettingsView(BRect frame); 452 453 virtual void AttachedToWindow(); 454 virtual void MessageReceived(BMessage* message); 455 456 private: 457 BMenuField* fWidthMenuField; 458 BMenuField* fColorMenuField; 459 BMenuField* fBorderMenuField; 460 BCheckBox* fMotionCheck; 461 BSlider* fSpeedSlider; 462 BSlider* fFramesSlider; 463 }; 464 465 466 SettingsView::SettingsView(BRect frame) 467 : 468 BView(frame, "", B_FOLLOW_ALL, B_WILL_DRAW) 469 { 470 SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 471 472 BStringView* titleString = new BStringView(B_EMPTY_STRING, 473 B_TRANSLATE("Nebula")); 474 titleString->SetFont(be_bold_font); 475 476 BStringView* copyrightString = new BStringView(B_EMPTY_STRING, 477 B_TRANSLATE("© 2001-2004 Axel Dörfler.")); 478 479 BPopUpMenu* popUpMenu; 480 481 int32 widths[] = { 482 0, 483 320, 484 512, 485 576, 486 640, 487 800, 488 1024, 489 1152, 490 1280, 491 1400, 492 1600 493 }; 494 495 size_t widthsLength = sizeof(widths) / sizeof(widths[0]); 496 497 popUpMenu = new BPopUpMenu(""); 498 for (size_t i = 0; i < widthsLength; i++) { 499 BString label; 500 if (widths[i] == 0) 501 label.SetTo("screen resolution"); 502 else 503 label.SetToFormat("%" B_PRId32 " pixels", widths[i]); 504 505 BMessage* message = new BMessage(kMsgWidth); 506 message->AddInt32("width", widths[i]); 507 508 const char* l = label.String(); 509 BMenuItem* item = new BMenuItem(B_TRANSLATE(l), message); 510 popUpMenu->AddItem(item); 511 item->SetMarked(gSettingsWidth == widths[i]); 512 } 513 514 fWidthMenuField = new BMenuField("res", B_TRANSLATE("Internal width:"), 515 popUpMenu); 516 517 const char* colorSchemeLabels[] = { 518 B_TRANSLATE("yellow"), 519 B_TRANSLATE("cyan"), 520 B_TRANSLATE("red"), 521 B_TRANSLATE("green"), 522 B_TRANSLATE("grey"), 523 B_TRANSLATE("cold"), 524 B_TRANSLATE("orange (original)") 525 }; 526 527 rgb_color colorSchemeColors[] = { 528 (rgb_color){ 255, 220, 0 }, 529 (rgb_color){ 127, 219, 255 }, 530 (rgb_color){ 255, 65, 54 }, 531 (rgb_color){ 46, 204, 64 }, 532 (rgb_color){ 170, 170, 170 }, 533 (rgb_color){ 234, 234, 234 }, 534 (rgb_color){ 255, 133, 27 } 535 }; 536 537 popUpMenu = new BPopUpMenu(""); 538 for (int i = 0; i < 7; i++) { 539 BMessage* message = new BMessage(kMsgColorScheme); 540 message->AddInt8("scheme", (int8)i); 541 BColorMenuItem* item = new BColorMenuItem(colorSchemeLabels[i], 542 message, colorSchemeColors[i]); 543 popUpMenu->AddItem(item); 544 item->SetMarked(gPaletteScheme == i); 545 } 546 547 fColorMenuField = new BMenuField("col", B_TRANSLATE("Color:"), popUpMenu); 548 549 const char* blankBorderFormats[] = { 550 B_TRANSLATE("fullscreen, no borders"), 551 B_TRANSLATE("16:9, wide-screen"), 552 B_TRANSLATE("2:3.5, cinemascope"), 553 B_TRANSLATE("only a slit") 554 }; 555 556 popUpMenu = new BPopUpMenu(""); 557 for (int8 i = 0; i < 4; i++) { 558 BMessage* message = new BMessage(kMsgBlankBorders); 559 message->AddInt8("border", i); 560 BMenuItem* item = new BMenuItem(blankBorderFormats[i], message); 561 popUpMenu->AddItem(item); 562 item->SetMarked(gBlankBorders == i); 563 } 564 565 fBorderMenuField = new BMenuField("cinema", B_TRANSLATE("Format:"), 566 popUpMenu); 567 568 fMotionCheck = new BCheckBox(B_EMPTY_STRING, 569 B_TRANSLATE("Enable motion blur"), new BMessage(kMsgMotionBlur)); 570 fMotionCheck->SetValue((int)gMotionBlur); 571 572 fSpeedSlider = new SimpleSlider(B_TRANSLATE("Speed"), 573 new BMessage(kMsgSpeed)); 574 fSpeedSlider->SetValue((gSpeed - 0.002) / 0.05); 575 576 fFramesSlider = new SimpleSlider(B_TRANSLATE("Maximum Frames Per Second"), 577 new BMessage(kMsgFrames)); 578 fFramesSlider->SetValue(gMaxFramesPerSecond); 579 580 BLayoutBuilder::Group<>(this, B_VERTICAL, B_USE_HALF_ITEM_SPACING) 581 .SetInsets(B_USE_DEFAULT_SPACING) 582 .Add(titleString) 583 .Add(copyrightString) 584 .AddStrut(roundf(be_control_look->DefaultItemSpacing() / 2)) 585 .AddGlue() 586 .AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING) 587 .Add(fColorMenuField->CreateLabelLayoutItem(), 0, 0) 588 .AddGroup(B_HORIZONTAL, 0.0f, 1, 0) 589 .Add(fColorMenuField->CreateMenuBarLayoutItem(), 0.0f) 590 .AddGlue() 591 .End() 592 .Add(fWidthMenuField->CreateLabelLayoutItem(), 0, 1) 593 .AddGroup(B_HORIZONTAL, 0.0f, 1, 1) 594 .Add(fWidthMenuField->CreateMenuBarLayoutItem(), 0.0f) 595 .AddGlue() 596 .End() 597 .Add(fBorderMenuField->CreateLabelLayoutItem(), 0, 2) 598 .AddGroup(B_HORIZONTAL, 0.0f, 1, 2) 599 .Add(fBorderMenuField->CreateMenuBarLayoutItem(), 0.0f) 600 .AddGlue() 601 .End() 602 .Add(fMotionCheck, 1, 3) 603 .End() 604 .Add(fSpeedSlider) 605 .Add(fFramesSlider) 606 .End(); 607 } 608 609 610 void 611 SettingsView::AttachedToWindow() 612 { 613 fWidthMenuField->Menu()->SetTargetForItems(this); 614 fColorMenuField->Menu()->SetTargetForItems(this); 615 fBorderMenuField->Menu()->SetTargetForItems(this); 616 fMotionCheck->SetTarget(this); 617 fSpeedSlider->SetTarget(this); 618 fFramesSlider->SetTarget(this); 619 } 620 621 622 void 623 SettingsView::MessageReceived(BMessage* message) 624 { 625 switch(message->what) { 626 case kMsgWidth: 627 message->FindInt32("width", &gSettingsWidth); 628 break; 629 630 case kMsgColorScheme: 631 if (message->FindInt8("scheme", &gPaletteScheme) == B_OK) 632 setPalette(); 633 break; 634 635 case kMsgBlankBorders: 636 message->FindInt8("border", &gBlankBorders); 637 break; 638 639 case kMsgMotionBlur: 640 gMotionBlur = fMotionCheck->Value() > 0; 641 break; 642 643 case kMsgSpeed: 644 gSpeed = 0.002 + 0.05 * fSpeedSlider->Value(); 645 break; 646 647 case kMsgFrames: 648 gMaxFramesPerSecond = fFramesSlider->Value(); 649 gScreenSaver->SetTickSize( 650 (bigtime_t)(1000000LL / gMaxFramesPerSecond)); 651 break; 652 } 653 } 654 655 656 657 // #pragma mark - Nebula 658 659 660 class Nebula : public BScreenSaver { 661 public: 662 Nebula(BMessage* message, image_id id); 663 664 virtual void StartConfig(BView* view); 665 virtual status_t SaveState(BMessage* state) const; 666 667 virtual status_t StartSaver(BView* view, bool preview); 668 virtual void StopSaver(); 669 virtual void Draw(BView* view, int32 frame); 670 671 private: 672 float fFactor; 673 bool fStarted; 674 }; 675 676 677 Nebula::Nebula(BMessage* message, image_id id) 678 : 679 BScreenSaver(message, id), 680 fStarted(false) 681 { 682 message->FindFloat("speed", 0, &gSpeed); 683 message->FindInt32("width", 0, &gSettingsWidth); 684 message->FindBool("motionblur", 0, &gMotionBlur); 685 message->FindFloat("max_fps", 0, &gMaxFramesPerSecond); 686 message->FindInt8("scheme", 0, &gPaletteScheme); 687 message->FindInt8("border", 0, &gBlankBorders); 688 689 if (gSpeed < 0.01f) 690 gSpeed = 0.4f; 691 692 if (gMaxFramesPerSecond < 1.f) 693 gMaxFramesPerSecond = 40.0f; 694 695 gScreenSaver = this; 696 } 697 698 699 void 700 Nebula::StartConfig(BView* view) 701 { 702 view->AddChild(new SettingsView(view->Bounds())); 703 } 704 705 706 status_t 707 Nebula::SaveState(BMessage* state) const 708 { 709 state->AddFloat("speed", gSpeed); 710 state->AddInt32("width", gSettingsWidth); 711 state->AddBool("motionblur", gMotionBlur); 712 state->AddFloat("max_fps", gMaxFramesPerSecond); 713 state->AddInt8("scheme", gPaletteScheme); 714 state->AddInt8("border", gBlankBorders); 715 716 return B_OK; 717 } 718 719 720 status_t 721 Nebula::StartSaver(BView* view, bool preview) 722 { 723 // initialize palette 724 setPalette(); 725 726 int i; 727 for (i = 0; i < 512; i++) { 728 precos[i]=cos(i * M_PI / 256); 729 presin[i]=sin(i * M_PI / 256); 730 } 731 732 // uniforme cubique 733 /* for (i = 0;i < GMAX;i++) 734 { 735 gal[i].x = 1 * ((rand()&1023) - 512); 736 gal[i].y = 1 * ((rand()&1023) - 512); 737 gal[i].z = 1 * ((rand()&1023) - 512); 738 gal[i].r = rand() & 63; 739 } 740 */ 741 742 for (i = 0; i < GMAX; i++) { 743 float r, th, h, dth; 744 745 r = rand() * 1.0 / RAND_MAX; 746 r = (1 - r) * (1 - r) + 0.05; 747 748 if (r < 0.12) 749 th = rand() * M_PI * 2 / RAND_MAX; 750 else { 751 th = (rand() & 3) * M_PI_2 + r * r * 2; 752 dth = rand() * 1.0 / RAND_MAX; 753 dth = dth * dth * 2; 754 th += dth; 755 } 756 gal[i].x = (int)(512 * r * cos(th)); 757 gal[i].z = (int)(512 * r * sin(th)); 758 h = (1 + cos(r * M_PI)) * 150; 759 dth = rand() * 1.0 / RAND_MAX; 760 gal[i].y = (int)(h * (dth - 0.5)); 761 gal[i].r = (int)((2 - r) * 60 + 31); 762 } 763 gal[0].x = gal[0].y = gal[0].z = 0; 764 gal[0].r = 320; 765 766 if (gSettingsWidth == 0) 767 gWidth = view->Bounds().Width(); 768 else 769 gWidth = gSettingsWidth; 770 771 fFactor = (view->Bounds().Width()+1) / gWidth; 772 if ((int)fFactor != fFactor) 773 fFactor += 0.01; 774 775 // 4:3 776 gHeight = (int32)((view->Bounds().Height()+1)/fFactor + 0.5f); 777 // calculate blank border format (if not in preview) 778 if (!preview) switch (gBlankBorders) { 779 case 1: // 16:9 780 gHeight = (int32)(gHeight * 0.703125 + 0.5); 781 break; 782 case 2: // 2:3.5 783 gHeight = (int32)(gHeight * 0.534 + 0.5); 784 break; 785 case 3: 786 gHeight /= 5; 787 break; 788 } 789 view->SetScale(fFactor); 790 791 gBitmap = new BBitmap(BRect(0, 0, gWidth - 1, gHeight - 1), B_RGB32); 792 gBuffer8 = (char*)malloc(gWidth * gHeight); 793 794 SetTickSize((bigtime_t)(1000000LL / gMaxFramesPerSecond)); 795 fStarted = true; 796 797 return B_OK; 798 } 799 800 801 void 802 Nebula::StopSaver() 803 { 804 free(gBuffer8); 805 gBuffer8 = NULL; 806 807 delete gBitmap; 808 gBitmap = NULL; 809 } 810 811 812 void 813 Nebula::Draw(BView* view, int32) 814 { 815 if (fStarted) { 816 view->SetHighColor(0, 0, 0, 0); 817 view->FillRect(view->Frame()); 818 view->MovePenTo(0, 819 (view->Bounds().Height() / fFactor - 1 - gHeight) / 2); 820 821 fStarted = false; 822 } 823 uint32* buffer32 = (uint32*)gBitmap->Bits(); 824 825 drawGalaxy(); 826 827 for (int x = 0, end = gWidth * gHeight; x < end; x++) 828 buffer32[x] = gPalette[(uint8)gBuffer8[x]]; 829 830 view->DrawBitmap(gBitmap); 831 } 832 833 834 // #pragma mark - instantiate_screen_saver 835 836 837 extern "C" _EXPORT BScreenSaver* 838 instantiate_screen_saver(BMessage* message, image_id image) 839 { 840 return new Nebula(message, image); 841 } 842