1*57d51b24SRyan Leavengood /* 2*57d51b24SRyan Leavengood * Copyright 2010-2011, Haiku, Inc. All Rights Reserved. 3*57d51b24SRyan Leavengood * Distributed under the terms of the MIT license. 4*57d51b24SRyan Leavengood * 5*57d51b24SRyan Leavengood * Authors: 6*57d51b24SRyan Leavengood * Deyan Genovski, deangenovski@gmail.com 7*57d51b24SRyan Leavengood * Geoffry Song, goffrie@gmail.com 8*57d51b24SRyan Leavengood */ 9*57d51b24SRyan Leavengood #include "Leaves.h" 10*57d51b24SRyan Leavengood 11*57d51b24SRyan Leavengood #include <stdlib.h> 12*57d51b24SRyan Leavengood #include <time.h> 13*57d51b24SRyan Leavengood 14*57d51b24SRyan Leavengood #include <AffineTransform.h> 15*57d51b24SRyan Leavengood #include <GradientLinear.h> 16*57d51b24SRyan Leavengood #include <Shape.h> 17*57d51b24SRyan Leavengood #include <Slider.h> 18*57d51b24SRyan Leavengood #include <TextView.h> 19*57d51b24SRyan Leavengood 20*57d51b24SRyan Leavengood 21*57d51b24SRyan Leavengood // path data for the leaf shape 22*57d51b24SRyan Leavengood static const BPoint kLeafBegin(56.24793f, 15.46287f); 23*57d51b24SRyan Leavengood static BPoint kLeafCurves[][3] = { 24*57d51b24SRyan Leavengood { BPoint(61.14, 28.89), BPoint(69.78, 38.25), BPoint(83.48, 44.17) }, 25*57d51b24SRyan Leavengood { BPoint(99.46, 37.52), BPoint(113.27, 29.61), BPoint(134.91, 30.86) }, 26*57d51b24SRyan Leavengood { BPoint(130.58, 36.53), BPoint(126.74, 42.44), BPoint(123.84, 48.81) }, 27*57d51b24SRyan Leavengood { BPoint(131.81, 42.22), BPoint(137.53, 38.33), BPoint(144.37, 33.10) }, 28*57d51b24SRyan Leavengood { BPoint(169.17, 23.55), BPoint(198.90, 15.55), BPoint(232.05, 10.51) }, 29*57d51b24SRyan Leavengood { BPoint(225.49, 18.37), BPoint(219.31, 28.17), BPoint(217.41, 40.24) }, 30*57d51b24SRyan Leavengood { BPoint(227.70, 26.60), BPoint(239.97, 14.63), BPoint(251.43, 8.36) }, 31*57d51b24SRyan Leavengood { BPoint(288.89, 9.12), BPoint(322.73, 14.33), BPoint(346.69, 31.67) }, 32*57d51b24SRyan Leavengood { BPoint(330.49, 37.85), BPoint(314.36, 44.25), BPoint(299.55, 54.17) }, 33*57d51b24SRyan Leavengood { BPoint(292.48, 52.54), BPoint(289.31, 49.70), BPoint(285.62, 47.03) }, 34*57d51b24SRyan Leavengood { BPoint(283.73, 54.61), BPoint(284.46, 57.94), BPoint(285.62, 60.60) }, 35*57d51b24SRyan Leavengood { BPoint(259.78, 76.14), BPoint(233.24, 90.54), BPoint(202.41, 98.10) }, 36*57d51b24SRyan Leavengood { BPoint(194.43, 95.36), BPoint(185.96, 92.39), BPoint(179.63, 88.33) }, 37*57d51b24SRyan Leavengood { BPoint(180.15, 94.75), BPoint(182.73, 99.76), BPoint(185.62, 104.53) }, 38*57d51b24SRyan Leavengood { BPoint(154.83, 119.46), BPoint(133.21, 118.97), BPoint(125.62, 94.88) }, 39*57d51b24SRyan Leavengood { BPoint(124.70, 98.79), BPoint(124.11, 103.67), BPoint(124.19, 110.60) }, 40*57d51b24SRyan Leavengood { BPoint(116.42, 111.81), BPoint(85.82, 99.60), BPoint(83.25, 51.96) }, 41*57d51b24SRyan Leavengood { BPoint(62.50, 42.57), BPoint(58.12, 33.18), BPoint(50.98, 23.81) } }; 42*57d51b24SRyan Leavengood static const int kLeafCurveCount = sizeof(kLeafCurves) / sizeof(kLeafCurves[0]); 43*57d51b24SRyan Leavengood static const float kLeafWidth = 372.f; 44*57d51b24SRyan Leavengood static const float kLeafHeight = 121.f; 45*57d51b24SRyan Leavengood 46*57d51b24SRyan Leavengood // leaf colors 47*57d51b24SRyan Leavengood static const rgb_color kColors[][2] = { 48*57d51b24SRyan Leavengood { {255, 114, 0, 255}, {255, 159, 0, 255} }, 49*57d51b24SRyan Leavengood { {50, 160, 40, 255}, {125, 210, 32, 255} }, 50*57d51b24SRyan Leavengood { {250, 190, 30, 255}, {255, 214, 125, 255} } }; 51*57d51b24SRyan Leavengood static const int kColorCount = sizeof(kColors) / sizeof(kColors[0]); 52*57d51b24SRyan Leavengood 53*57d51b24SRyan Leavengood // bounds for settings 54*57d51b24SRyan Leavengood static const int kMinimumDropRate = 2, kMaximumDropRate = 50; 55*57d51b24SRyan Leavengood static const int kMinimumLeafSize = 50, kMaximumLeafSize = 1000; 56*57d51b24SRyan Leavengood static const int kMaximumSizeVariation = 200; 57*57d51b24SRyan Leavengood 58*57d51b24SRyan Leavengood enum { 59*57d51b24SRyan Leavengood MSG_SET_DROP_RATE = 'drop', 60*57d51b24SRyan Leavengood MSG_SET_LEAF_SIZE = 'size', 61*57d51b24SRyan Leavengood MSG_SET_SIZE_VARIATION = 'svry', 62*57d51b24SRyan Leavengood }; 63*57d51b24SRyan Leavengood 64*57d51b24SRyan Leavengood 65*57d51b24SRyan Leavengood extern "C" BScreenSaver* 66*57d51b24SRyan Leavengood instantiate_screen_saver(BMessage* msg, image_id image) 67*57d51b24SRyan Leavengood { 68*57d51b24SRyan Leavengood return new Leaves(msg, image); 69*57d51b24SRyan Leavengood } 70*57d51b24SRyan Leavengood 71*57d51b24SRyan Leavengood 72*57d51b24SRyan Leavengood Leaves::Leaves(BMessage* archive, image_id id) 73*57d51b24SRyan Leavengood : 74*57d51b24SRyan Leavengood BScreenSaver(archive, id), 75*57d51b24SRyan Leavengood fDropRateSlider(NULL), 76*57d51b24SRyan Leavengood fLeafSizeSlider(NULL), 77*57d51b24SRyan Leavengood fSizeVariationSlider(NULL), 78*57d51b24SRyan Leavengood fDropRate(10), 79*57d51b24SRyan Leavengood fLeafSize(150), 80*57d51b24SRyan Leavengood fSizeVariation(50) 81*57d51b24SRyan Leavengood { 82*57d51b24SRyan Leavengood if (archive) { 83*57d51b24SRyan Leavengood if (archive->FindInt32("Leaves drop rate", &fDropRate) != B_OK) 84*57d51b24SRyan Leavengood fDropRate = 10; 85*57d51b24SRyan Leavengood if (archive->FindInt32("Leaves size", &fLeafSize) != B_OK) 86*57d51b24SRyan Leavengood fLeafSize = 150; 87*57d51b24SRyan Leavengood if (archive->FindInt32("Leaves variation", &fSizeVariation) != B_OK) 88*57d51b24SRyan Leavengood fSizeVariation = 50; 89*57d51b24SRyan Leavengood } 90*57d51b24SRyan Leavengood } 91*57d51b24SRyan Leavengood 92*57d51b24SRyan Leavengood 93*57d51b24SRyan Leavengood void 94*57d51b24SRyan Leavengood Leaves::StartConfig(BView* view) 95*57d51b24SRyan Leavengood { 96*57d51b24SRyan Leavengood BRect bounds = view->Bounds(); 97*57d51b24SRyan Leavengood bounds.InsetBy(10, 10); 98*57d51b24SRyan Leavengood BRect frame(0, 0, bounds.Width(), 20); 99*57d51b24SRyan Leavengood 100*57d51b24SRyan Leavengood fDropRateSlider = new BSlider(frame, "drop rate", "Drop rate:", 101*57d51b24SRyan Leavengood new BMessage(MSG_SET_DROP_RATE), kMinimumDropRate, kMaximumDropRate, 102*57d51b24SRyan Leavengood B_BLOCK_THUMB, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM); 103*57d51b24SRyan Leavengood fDropRateSlider->SetValue(fDropRate); 104*57d51b24SRyan Leavengood fDropRateSlider->ResizeToPreferred(); 105*57d51b24SRyan Leavengood bounds.bottom -= fDropRateSlider->Bounds().Height() * 1.5; 106*57d51b24SRyan Leavengood fDropRateSlider->MoveTo(bounds.LeftBottom()); 107*57d51b24SRyan Leavengood view->AddChild(fDropRateSlider); 108*57d51b24SRyan Leavengood 109*57d51b24SRyan Leavengood fLeafSizeSlider = new BSlider(frame, "leaf size", "Leaf size:", 110*57d51b24SRyan Leavengood new BMessage(MSG_SET_LEAF_SIZE), kMinimumLeafSize, kMaximumLeafSize, 111*57d51b24SRyan Leavengood B_BLOCK_THUMB, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM); 112*57d51b24SRyan Leavengood fLeafSizeSlider->SetValue(fLeafSize); 113*57d51b24SRyan Leavengood fLeafSizeSlider->ResizeToPreferred(); 114*57d51b24SRyan Leavengood bounds.bottom -= fLeafSizeSlider->Bounds().Height() * 1.5; 115*57d51b24SRyan Leavengood fLeafSizeSlider->MoveTo(bounds.LeftBottom()); 116*57d51b24SRyan Leavengood view->AddChild(fLeafSizeSlider); 117*57d51b24SRyan Leavengood 118*57d51b24SRyan Leavengood fSizeVariationSlider = new BSlider(frame, "variation", "Size variation:", 119*57d51b24SRyan Leavengood new BMessage(MSG_SET_SIZE_VARIATION), 0, kMaximumSizeVariation, 120*57d51b24SRyan Leavengood B_BLOCK_THUMB, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM); 121*57d51b24SRyan Leavengood fSizeVariationSlider->SetValue(fSizeVariation); 122*57d51b24SRyan Leavengood fSizeVariationSlider->ResizeToPreferred(); 123*57d51b24SRyan Leavengood bounds.bottom -= fSizeVariationSlider->Bounds().Height() * 1.5; 124*57d51b24SRyan Leavengood fSizeVariationSlider->MoveTo(bounds.LeftBottom()); 125*57d51b24SRyan Leavengood view->AddChild(fSizeVariationSlider); 126*57d51b24SRyan Leavengood 127*57d51b24SRyan Leavengood BTextView* textView = new BTextView(bounds, B_EMPTY_STRING, 128*57d51b24SRyan Leavengood bounds.OffsetToCopy(0., 0.), B_FOLLOW_ALL, B_WILL_DRAW); 129*57d51b24SRyan Leavengood textView->SetViewColor(view->ViewColor()); 130*57d51b24SRyan Leavengood textView->Insert("Leaves\n\n" 131*57d51b24SRyan Leavengood "by Deyan Genovski, Geoffry Song\n\n"); 132*57d51b24SRyan Leavengood textView->SetStylable(true); 133*57d51b24SRyan Leavengood textView->SetFontAndColor(0, 6, be_bold_font); 134*57d51b24SRyan Leavengood textView->MakeEditable(false); 135*57d51b24SRyan Leavengood view->AddChild(textView); 136*57d51b24SRyan Leavengood 137*57d51b24SRyan Leavengood BWindow* window = view->Window(); 138*57d51b24SRyan Leavengood if (window) window->AddHandler(this); 139*57d51b24SRyan Leavengood 140*57d51b24SRyan Leavengood fDropRateSlider->SetTarget(this); 141*57d51b24SRyan Leavengood fLeafSizeSlider->SetTarget(this); 142*57d51b24SRyan Leavengood fSizeVariationSlider->SetTarget(this); 143*57d51b24SRyan Leavengood } 144*57d51b24SRyan Leavengood 145*57d51b24SRyan Leavengood 146*57d51b24SRyan Leavengood status_t 147*57d51b24SRyan Leavengood Leaves::StartSaver(BView* view, bool preview) 148*57d51b24SRyan Leavengood { 149*57d51b24SRyan Leavengood SetTickSize(10000000 / fDropRate); 150*57d51b24SRyan Leavengood srand48(time(NULL)); 151*57d51b24SRyan Leavengood 152*57d51b24SRyan Leavengood view->SetLineMode(B_ROUND_CAP, B_ROUND_JOIN); 153*57d51b24SRyan Leavengood 154*57d51b24SRyan Leavengood return B_OK; 155*57d51b24SRyan Leavengood } 156*57d51b24SRyan Leavengood 157*57d51b24SRyan Leavengood 158*57d51b24SRyan Leavengood status_t 159*57d51b24SRyan Leavengood Leaves::SaveState(BMessage* into) const 160*57d51b24SRyan Leavengood { 161*57d51b24SRyan Leavengood status_t status; 162*57d51b24SRyan Leavengood if ((status = into->AddInt32("Leaves drop rate", fDropRate)) != B_OK) 163*57d51b24SRyan Leavengood return status; 164*57d51b24SRyan Leavengood if ((status = into->AddInt32("Leaves size", fLeafSize)) != B_OK) 165*57d51b24SRyan Leavengood return status; 166*57d51b24SRyan Leavengood if ((status = into->AddInt32("Leaves variation", fSizeVariation)) != B_OK) 167*57d51b24SRyan Leavengood return status; 168*57d51b24SRyan Leavengood return B_OK; 169*57d51b24SRyan Leavengood } 170*57d51b24SRyan Leavengood 171*57d51b24SRyan Leavengood 172*57d51b24SRyan Leavengood void 173*57d51b24SRyan Leavengood Leaves::MessageReceived(BMessage* message) 174*57d51b24SRyan Leavengood { 175*57d51b24SRyan Leavengood switch (message->what) { 176*57d51b24SRyan Leavengood case MSG_SET_DROP_RATE: 177*57d51b24SRyan Leavengood fDropRate = fDropRateSlider->Value(); 178*57d51b24SRyan Leavengood break; 179*57d51b24SRyan Leavengood case MSG_SET_LEAF_SIZE: 180*57d51b24SRyan Leavengood fLeafSize = fLeafSizeSlider->Value(); 181*57d51b24SRyan Leavengood break; 182*57d51b24SRyan Leavengood case MSG_SET_SIZE_VARIATION: 183*57d51b24SRyan Leavengood fSizeVariation = fSizeVariationSlider->Value(); 184*57d51b24SRyan Leavengood break; 185*57d51b24SRyan Leavengood default: 186*57d51b24SRyan Leavengood BHandler::MessageReceived(message); 187*57d51b24SRyan Leavengood } 188*57d51b24SRyan Leavengood } 189*57d51b24SRyan Leavengood 190*57d51b24SRyan Leavengood 191*57d51b24SRyan Leavengood void 192*57d51b24SRyan Leavengood Leaves::Draw(BView* view, int32 frame) 193*57d51b24SRyan Leavengood { 194*57d51b24SRyan Leavengood float scale = fLeafSize / kLeafWidth / (kMaximumLeafSize * 2); 195*57d51b24SRyan Leavengood scale *= view->Bounds().Width(); 196*57d51b24SRyan Leavengood scale += scale * drand48() * fSizeVariation / 100.; 197*57d51b24SRyan Leavengood 198*57d51b24SRyan Leavengood BAffineTransform transform; 199*57d51b24SRyan Leavengood transform.TranslateBy(-kLeafWidth / 2, -kLeafHeight / 2); 200*57d51b24SRyan Leavengood // draw the leaf centered on the point 201*57d51b24SRyan Leavengood transform.RotateBy(drand48() * 2. * M_PI); 202*57d51b24SRyan Leavengood if ((rand() & 64) == 0) transform.ScaleBy(-1., 1.); 203*57d51b24SRyan Leavengood // flip half of the time 204*57d51b24SRyan Leavengood transform.ScaleBy(scale); 205*57d51b24SRyan Leavengood transform.TranslateBy(_RandomPoint(view->Bounds())); 206*57d51b24SRyan Leavengood 207*57d51b24SRyan Leavengood BPoint center = transform.Apply(BPoint(kLeafWidth / 2, kLeafHeight / 2)); 208*57d51b24SRyan Leavengood BPoint gradientOffset = BPoint(60 * scale, 80 * scale); 209*57d51b24SRyan Leavengood BGradientLinear gradient(center - gradientOffset, center + gradientOffset); 210*57d51b24SRyan Leavengood int color = (rand() / 7) % kColorCount; 211*57d51b24SRyan Leavengood gradient.AddColor(kColors[color][0], 0.f); 212*57d51b24SRyan Leavengood gradient.AddColor(kColors[color][1], 255.f); 213*57d51b24SRyan Leavengood 214*57d51b24SRyan Leavengood BShape leafShape; 215*57d51b24SRyan Leavengood leafShape.MoveTo(transform.Apply(kLeafBegin)); 216*57d51b24SRyan Leavengood for (int i = 0; i < kLeafCurveCount; ++i) { 217*57d51b24SRyan Leavengood BPoint control[3]; 218*57d51b24SRyan Leavengood for (int j = 0; j < 3; ++j) 219*57d51b24SRyan Leavengood control[j] = transform.Apply(kLeafCurves[i][j]); 220*57d51b24SRyan Leavengood leafShape.BezierTo(control); 221*57d51b24SRyan Leavengood } 222*57d51b24SRyan Leavengood leafShape.Close(); 223*57d51b24SRyan Leavengood 224*57d51b24SRyan Leavengood view->PushState(); 225*57d51b24SRyan Leavengood view->SetDrawingMode(B_OP_ALPHA); 226*57d51b24SRyan Leavengood view->SetHighColor(0, 0, 0, 50); 227*57d51b24SRyan Leavengood for (int i = 2; i >= 0; --i) { 228*57d51b24SRyan Leavengood view->SetOrigin(i * 0.1, i * 0.3); 229*57d51b24SRyan Leavengood view->SetPenSize(i * 2); 230*57d51b24SRyan Leavengood view->StrokeShape(&leafShape); 231*57d51b24SRyan Leavengood } 232*57d51b24SRyan Leavengood view->PopState(); 233*57d51b24SRyan Leavengood view->FillShape(&leafShape, gradient); 234*57d51b24SRyan Leavengood } 235*57d51b24SRyan Leavengood 236*57d51b24SRyan Leavengood 237*57d51b24SRyan Leavengood inline BPoint 238*57d51b24SRyan Leavengood Leaves::_RandomPoint(const BRect& bound) 239*57d51b24SRyan Leavengood { 240*57d51b24SRyan Leavengood return BPoint(drand48() * (bound.right - bound.left) + bound.left, 241*57d51b24SRyan Leavengood drand48() * (bound.bottom - bound.top) + bound.top); 242*57d51b24SRyan Leavengood } 243*57d51b24SRyan Leavengood 244